am ad23333f: am 945080b5: am 1e86994c: Merge "MtpData bmp format file can\'t recognize when copy bmp into DUT"

* commit 'ad23333f728471a7f2c49cd1c9575f1cea2503f6':
  MtpData bmp format file can't recognize when copy bmp into DUT
diff --git a/Android.mk b/Android.mk
index b9157fe..be98487 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 \
@@ -711,9 +726,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/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..cab0cf5
--- /dev/null
+++ b/api/17.txt
@@ -0,0 +1,47989 @@
+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 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 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 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 STORAGE = "android.permission-group.STORAGE";
+    field public static final java.lang.String SYSTEM_TOOLS = "android.permission-group.SYSTEM_TOOLS";
+  }
+
+  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 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 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 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 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 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_alignLeft = 16843143; // 0x1010187
+    field public static final int layout_alignParentBottom = 16843150; // 0x101018e
+    field public static final int layout_alignParentLeft = 16843147; // 0x101018b
+    field public static final int layout_alignParentRight = 16843149; // 0x101018d
+    field public static final int layout_alignParentTop = 16843148; // 0x101018c
+    field public static final int layout_alignRight = 16843145; // 0x1010189
+    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_marginLeft = 16842999; // 0x10100f7
+    field public static final int layout_marginRight = 16843001; // 0x10100f9
+    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_toLeftOf = 16843138; // 0x1010182
+    field public static final int layout_toRightOf = 16843139; // 0x1010183
+    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 listPreferredItemPaddingLeft = 16843683; // 0x10103a3
+    field public static final int listPreferredItemPaddingRight = 16843684; // 0x10103a4
+    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 paddingLeft = 16842966; // 0x10100d6
+    field public static final int paddingRight = 16842968; // 0x10100d8
+    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 permissionGroup = 16842762; // 0x101000a
+    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 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 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 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 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 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 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 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 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 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_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_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_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_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_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_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 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 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 getFragmentManager();
+    method public final int getId();
+    method public android.app.LoaderManager getLoaderManager();
+    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 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 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 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 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 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 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 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_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 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 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 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 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 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_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 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 int autoAdvanceViewId;
+    field public android.content.ComponentName configure;
+    field public int icon;
+    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;
+  }
+
+}
+
+package android.bluetooth {
+
+  public final class BluetoothA2dp 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 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 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 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 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 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 sendStickyBroadcast(android.content.Intent);
+    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 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 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 int MODE_WORLD_READABLE = 1; // 0x1
+    field public static final 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 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 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 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 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 sendStickyBroadcast(android.content.Intent);
+    method public void sendStickyOrderedBroadcast(android.content.Intent, 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_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_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_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_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_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER";
+    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 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_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_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_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_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_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 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 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_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 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 int descriptionRes;
+    field public java.lang.CharSequence nonLocalizedDescription;
+  }
+
+  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 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 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 java.lang.String authority;
+    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();
+    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_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 boolean isLayoutSizeAtLeast(int);
+    method public static boolean needNewResources(int, int);
+    method public void readFromParcel(android.os.Parcel);
+    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 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_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 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 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 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(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 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 isMutable();
+    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 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 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 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 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 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_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.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 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 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 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 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 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 abstract class LocationProvider {
+    method public abstract int getAccuracy();
+    method public java.lang.String getName();
+    method public abstract int getPowerRequirement();
+    method public abstract 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();
+    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 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 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_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_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_UNKNOWN = 1; // 0x1
+    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_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_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_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 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 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 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_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 {
+    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 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 setKeyManagers(javax.net.ssl.KeyManager[]);
+    method public void setNpnProtocols(byte[][]);
+    method public void setTrustManagers(javax.net.ssl.TrustManager[]);
+  }
+
+  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
+  }
+
+}
+
+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;
+  }
+
+  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 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 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 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 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 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_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 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
+  }
+
+  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);
+    field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000
+    field public static final 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
+  }
+
+  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 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 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 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 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 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 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";
+  }
+
+  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 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 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_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_VIDEO_CAMERA = "android.media.action.VIDEO_CAMERA";
+    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 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 synchronized 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 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 android.net.Uri CONTENT_URI;
+    field public static final 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 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 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 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 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 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 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 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 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 boolean getShowGTalkServiceStatus(android.content.ContentResolver);
+    method public static synchronized 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);
+    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 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 ANDROID_ID = "android_id";
+    field public static final 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 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 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 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 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 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 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 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 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 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 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 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_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 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 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 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 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.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 abstract class CellLocation {
+    ctor public CellLocation();
+    method public static android.telephony.CellLocation getEmpty();
+    method public static void requestLocationUpdate();
+  }
+
+  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 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_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 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 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 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 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 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 sendStickyBroadcast(android.content.Intent);
+    method public void sendStickyOrderedBroadcast(android.content.Intent, 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 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 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 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 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 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 java.lang.String getAMPMString(int);
+    method public static java.lang.String getDayOfWeekString(int, int);
+    method public static 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 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 int FORMAT_12HOUR = 64; // 0x40
+    field public static final 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 int FORMAT_CAP_AMPM = 256; // 0x100
+    field public static final int FORMAT_CAP_MIDNIGHT = 4096; // 0x1000
+    field public static final int FORMAT_CAP_NOON = 1024; // 0x400
+    field public static final 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 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 java.lang.String HOUR_MINUTE_24 = "%H:%M";
+    field public static final int LENGTH_LONG = 10; // 0xa
+    field public static final int LENGTH_MEDIUM = 20; // 0x14
+    field public static final int LENGTH_SHORT = 30; // 0x1e
+    field public static final int LENGTH_SHORTER = 40; // 0x28
+    field public static final 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 int[] sameMonthTable;
+    field public static final 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 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 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 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 floor(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();
+  }
+
+  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 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 deprecated int getHeight();
+    method public void getMetrics(android.util.DisplayMetrics);
+    method public deprecated int getOrientation();
+    method public int getPixelFormat();
+    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();
+    field public static final int DEFAULT_DISPLAY = 0; // 0x0
+  }
+
+  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, int, int, android.graphics.Rect);
+    method public static void applyDisplay(int, android.graphics.Rect, android.graphics.Rect);
+    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 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 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 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 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 getLayerType();
+    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 getPaddingLeft();
+    method public int getPaddingRight();
+    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 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 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 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 setLayerType(int, android.graphics.Paint);
+    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 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 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 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_INHERIT = 0; // 0x0
+    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 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 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.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 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_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_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 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 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 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);
+    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 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 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 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 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 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 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 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 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 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 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 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 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 void setNetworkAvailable(boolean);
+    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 synchronized 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 setOnItemClickListener(android.widget.AdapterView.OnItemClickListener);
+    method public void setOnItemSelectedListener(android.widget.AdapterView.OnItemSelectedListener);
+    method public void setThreshold(int);
+    method public void setValidator(android.widget.AutoCompleteTextView.Validator);
+    method public void showDropDown();
+  }
+
+  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 onPaddingChanged(int);
+    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 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_LEFT = 5; // 0x5
+    field public static final int ALIGN_PARENT_BOTTOM = 12; // 0xc
+    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_TOP = 10; // 0xa
+    field public static final int ALIGN_RIGHT = 7; // 0x7
+    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 LEFT_OF = 0; // 0x0
+    field public static final int RIGHT_OF = 1; // 0x1
+    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();
+    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 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 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 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 int getCompoundPaddingBottom();
+    method public int getCompoundPaddingLeft();
+    method public int getCompoundPaddingRight();
+    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 float getTextScaleX();
+    method public float getTextSize();
+    method public int getTotalPaddingBottom();
+    method public int getTotalPaddingLeft();
+    method public int getTotalPaddingRight();
+    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 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 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 setPaddingRelative(int, int, int, int);
+    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 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 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 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 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..4abcaee 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 {
@@ -551,6 +570,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 +614,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 +623,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 +649,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 +680,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 +754,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 +770,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 +792,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
@@ -879,6 +916,7 @@
     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 +966,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 +974,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 +1005,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 +1045,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
@@ -1097,6 +1139,8 @@
     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 widgetFeatures = 16843715; // 0x10103c3
     field public static final int widgetLayout = 16843243; // 0x10101eb
     field public static final int width = 16843097; // 0x1010159
     field public static final int windowActionBar = 16843469; // 0x10102cd
@@ -2043,6 +2087,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
@@ -2992,6 +3037,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 +3370,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 +3423,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);
@@ -3848,9 +3897,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 +3929,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 +4166,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 +4207,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_WIDGETS = 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 +4243,7 @@
     method public java.util.List<android.content.ComponentName> getActiveAdmins();
     method public boolean getCameraDisabled(android.content.ComponentName);
     method public int getCurrentFailedPasswordAttempts();
+    method public int getKeyguardWidgetsDisabled(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 +4267,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 setKeyguardWidgetsDisabled(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 +4291,8 @@
     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_WIDGETS_ALL = 2147483647; // 0x7fffffff
+    field public static final int KEYGUARD_DISABLE_WIDGETS_NONE = 0; // 0x0
     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 +4400,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 +4422,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 +4452,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";
@@ -4409,9 +4479,15 @@
     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 static final int WIDGET_FEATURES_CLOCK = 1; // 0x1
+    field public static final int WIDGET_FEATURES_NONE = 0; // 0x0
+    field public static final int WIDGET_FEATURES_STATUS = 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 +4498,8 @@
     field public android.content.ComponentName provider;
     field public int resizeMode;
     field public int updatePeriodMillis;
+    field public int widgetCategory;
+    field public int widgetFeatures;
   }
 
 }
@@ -4429,6 +4507,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 +5133,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 +5320,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 +5377,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 +5424,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";
@@ -5361,6 +5450,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 +5470,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 +5519,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;
@@ -5715,6 +5813,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";
@@ -5742,6 +5841,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 +5907,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 +6057,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 +6293,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 +6318,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 +6364,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 +6374,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 +6547,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,6 +6612,7 @@
     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";
@@ -6552,6 +6667,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 +6717,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 +6730,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 +6740,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 +6751,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;
@@ -6676,6 +6799,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 +6895,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 +6929,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 +6944,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 +6963,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;
@@ -6942,7 +7077,7 @@
     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 deprecated 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();
@@ -7307,7 +7442,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 +7459,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 +8219,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);
@@ -8110,6 +8247,7 @@
     method public final int getWidth();
     method public final boolean hasAlpha();
     method public final boolean isMutable();
+    method public final boolean isPremultiplied();
     method public final boolean isRecycled();
     method public void prepareToDraw();
     method public void recycle();
@@ -8599,6 +8737,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 +8787,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);
@@ -9242,6 +9382,7 @@
     method public android.graphics.drawable.Drawable getCurrent();
     method public int getIntrinsicHeight();
     method public int getIntrinsicWidth();
+    method public int getLayoutDirection();
     method public final int getLevel();
     method public int getMinimumHeight();
     method public int getMinimumWidth();
@@ -9269,6 +9410,7 @@
     method public void setColorFilter(int, android.graphics.PorterDuff.Mode);
     method public void setDither(boolean);
     method public void setFilterBitmap(boolean);
+    method public void setLayoutDirection(int);
     method public final boolean setLevel(int);
     method public boolean setState(int[]);
     method public boolean setVisible(boolean, boolean);
@@ -9547,6 +9689,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();
@@ -9754,6 +9897,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 +9947,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 +10070,23 @@
 
 }
 
+package android.hardware.display {
+
+  public final class DisplayManager {
+    method public android.view.Display getDisplay(int);
+    method public android.view.Display[] getDisplays();
+    method public void registerDisplayListener(android.hardware.display.DisplayManager.DisplayListener, android.os.Handler);
+    method public void unregisterDisplayListener(android.hardware.display.DisplayManager.DisplayListener);
+  }
+
+  public static abstract interface DisplayManager.DisplayListener {
+    method public abstract void onDisplayAdded(int);
+    method public abstract void onDisplayChanged(int);
+    method public abstract void onDisplayRemoved(int);
+  }
+
+}
+
 package android.hardware.input {
 
   public final class InputManager {
@@ -10089,6 +10250,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 +10263,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 +10283,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();
@@ -10399,7 +10563,7 @@
     field public static final android.os.Parcelable.Creator CREATOR;
   }
 
-  public class Criteria implements android.os.Parcelable {
+  public deprecated class Criteria implements android.os.Parcelable {
     ctor public Criteria();
     ctor public Criteria(android.location.Criteria);
     method public int describeContents();
@@ -10445,6 +10609,13 @@
     method public static boolean isPresent();
   }
 
+  public final class Geofence implements android.os.Parcelable {
+    method public static android.location.Geofence createCircle(double, double, float);
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
   public final class GpsSatellite {
     method public float getAzimuth();
     method public float getElevation();
@@ -10482,14 +10653,15 @@
     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 deprecated void dump(android.util.Printer, java.lang.String);
     method public float getAccuracy();
     method public double getAltitude();
     method public float getBearing();
+    method public long getElapsedRealtimeNano();
     method public android.os.Bundle getExtras();
     method public double getLatitude();
     method public double getLongitude();
-    method public java.lang.String getProvider();
+    method public deprecated java.lang.String getProvider();
     method public float getSpeed();
     method public long getTime();
     method public boolean hasAccuracy();
@@ -10505,6 +10677,7 @@
     method public void setAccuracy(float);
     method public void setAltitude(double);
     method public void setBearing(float);
+    method public void setElapsedRealtimeNano(long);
     method public void setExtras(android.os.Bundle);
     method public void setLatitude(double);
     method public void setLongitude(double);
@@ -10526,67 +10699,97 @@
   }
 
   public class LocationManager {
+    method public void addGeofence(android.location.LocationRequest, android.location.Geofence, android.app.PendingIntent);
     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 deprecated void addProximityAlert(double, double, float, long, android.app.PendingIntent);
+    method public deprecated void addTestProvider(java.lang.String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
+    method public deprecated void clearTestProviderEnabled(java.lang.String);
+    method public deprecated void clearTestProviderLocation(java.lang.String);
+    method public deprecated void clearTestProviderStatus(java.lang.String);
+    method public deprecated java.util.List<java.lang.String> getAllProviders();
+    method public deprecated 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 deprecated android.location.Location getLastKnownLocation(java.lang.String);
+    method public android.location.Location getLastLocation();
+    method public deprecated android.location.LocationProvider getProvider(java.lang.String);
+    method public deprecated java.util.List<java.lang.String> getProviders(boolean);
+    method public deprecated java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean);
+    method public deprecated boolean isProviderEnabled(java.lang.String);
+    method public void removeAllGeofences(android.app.PendingIntent);
+    method public void removeGeofence(android.location.Geofence, android.app.PendingIntent);
     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 deprecated void removeProximityAlert(android.app.PendingIntent);
+    method public deprecated 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";
+    method public deprecated void requestLocationUpdates(java.lang.String, long, float, android.location.LocationListener);
+    method public deprecated void requestLocationUpdates(java.lang.String, long, float, android.location.LocationListener, android.os.Looper);
+    method public deprecated void requestLocationUpdates(long, float, android.location.Criteria, android.location.LocationListener, android.os.Looper);
+    method public deprecated void requestLocationUpdates(java.lang.String, long, float, android.app.PendingIntent);
+    method public deprecated void requestLocationUpdates(long, float, android.location.Criteria, android.app.PendingIntent);
+    method public void requestLocationUpdates(android.location.LocationRequest, android.location.LocationListener, android.os.Looper);
+    method public void requestLocationUpdates(android.location.LocationRequest, android.app.PendingIntent);
+    method public deprecated void requestSingleUpdate(java.lang.String, android.location.LocationListener, android.os.Looper);
+    method public deprecated void requestSingleUpdate(android.location.Criteria, android.location.LocationListener, android.os.Looper);
+    method public deprecated void requestSingleUpdate(java.lang.String, android.app.PendingIntent);
+    method public deprecated void requestSingleUpdate(android.location.Criteria, android.app.PendingIntent);
+    method public deprecated boolean sendExtraCommand(java.lang.String, java.lang.String, android.os.Bundle);
+    method public deprecated void setTestProviderEnabled(java.lang.String, boolean);
+    method public deprecated void setTestProviderLocation(java.lang.String, android.location.Location);
+    method public deprecated void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long);
+    field public static final deprecated 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 deprecated 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";
+    field public static final deprecated java.lang.String KEY_STATUS_CHANGED = "status";
+    field public static final deprecated java.lang.String NETWORK_PROVIDER = "network";
+    field public static final deprecated java.lang.String PASSIVE_PROVIDER = "passive";
+    field public static final deprecated java.lang.String PROVIDERS_CHANGED_ACTION = "android.location.PROVIDERS_CHANGED";
   }
 
-  public abstract class LocationProvider {
-    method public abstract int getAccuracy();
+  public deprecated 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
   }
 
+  public final class LocationRequest implements android.os.Parcelable {
+    method public static android.location.LocationRequest create();
+    method public int describeContents();
+    method public long getExpireAt();
+    method public long getFastestInterval();
+    method public long getInterval();
+    method public int getNumUpdates();
+    method public int getQuality();
+    method public android.location.LocationRequest setExpireAt(long);
+    method public android.location.LocationRequest setExpireIn(long);
+    method public android.location.LocationRequest setFastestInterval(long);
+    method public android.location.LocationRequest setInterval(long);
+    method public android.location.LocationRequest setNumUpdates(int);
+    method public android.location.LocationRequest setQuality(int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int ACCURACY_BLOCK = 102; // 0x66
+    field public static final int ACCURACY_CITY = 104; // 0x68
+    field public static final int ACCURACY_FINE = 100; // 0x64
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int POWER_HIGH = 203; // 0xcb
+    field public static final int POWER_LOW = 201; // 0xc9
+    field public static final int POWER_NONE = 200; // 0xc8
+  }
+
 }
 
 package android.media {
@@ -11305,6 +11508,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 +11570,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 +11665,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
@@ -12353,6 +12563,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 +12608,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 +12686,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;
@@ -13114,6 +13326,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 {
@@ -13747,6 +13960,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 +15035,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 +15065,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 +15625,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 +15653,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 +15720,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 +16380,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 +16414,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 +16457,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 +16548,7 @@
   public final class SystemClock {
     method public static long currentThreadTimeMillis();
     method public static long elapsedRealtime();
+    method public static long elapsedRealtimeNano();
     method public static boolean setCurrentTimeMillis(long);
     method public static void sleep(long);
     method public static long uptimeMillis();
@@ -16177,6 +16570,19 @@
     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 java.lang.String getUserName();
+  }
+
   public abstract class Vibrator {
     method public abstract void cancel();
     method public abstract boolean hasVibrator();
@@ -16956,9 +17362,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";
   }
@@ -18010,6 +18418,7 @@
     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_VIDEO_CAMERA = "android.media.action.VIDEO_CAMERA";
     field public static final java.lang.String MEDIA_IGNORE_FILENAME = ".nomedia";
     field public static final java.lang.String MEDIA_SCANNER_VOLUME = "volume";
@@ -18349,6 +18758,53 @@
     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 synchronized 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 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 DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled";
+    field public static final java.lang.String DEVICE_PROVISIONED = "device_provisioned";
+    field public static final java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
+    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 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 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 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";
+  }
+
   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);
@@ -18375,28 +18831,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 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 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 +18868,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 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 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 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";
@@ -18447,7 +18903,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 boolean getShowGTalkServiceStatus(android.content.ContentResolver);
+    method public static deprecated boolean getShowGTalkServiceStatus(android.content.ContentResolver);
     method public static synchronized 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);
@@ -18455,18 +18911,18 @@
     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 ANDROID_ID = "android_id";
     field public static final 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";
@@ -18478,7 +18934,7 @@
     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";
@@ -18499,10 +18955,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";
@@ -18515,7 +18971,7 @@
     field public static final 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";
@@ -18543,10 +18999,10 @@
     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 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 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";
@@ -19580,6 +20036,49 @@
     ctor protected ScriptC(android.renderscript.RenderScript, android.content.res.Resources, int);
   }
 
+  public abstract class ScriptIntrinsic extends android.renderscript.Script {
+  }
+
+  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 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 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 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 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 void setAlpha(int, int);
+    method public void setBlue(int, int);
+    method public void setGreen(int, int);
+    method public void setRed(int, int);
+  }
+
   public class Short2 {
     ctor public Short2();
     ctor public Short2(short, short);
@@ -19706,6 +20205,50 @@
 
 }
 
+package android.service.dreams {
+
+  public class Dream extends android.app.Service implements android.view.Window.Callback {
+    ctor public Dream();
+    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 void finish();
+    method public android.view.Window getWindow();
+    method public android.view.WindowManager getWindowManager();
+    method public boolean isInteractive();
+    method protected void lightsOut();
+    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 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 onStart();
+    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 setInteractive(boolean);
+    field public static final java.lang.String METADATA_NAME_CONFIG_ACTIVITY = "android.service.dreams.config_activity";
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.dreams.Dream";
+  }
+
+}
+
 package android.service.textservice {
 
   public abstract class SpellCheckerService extends android.app.Service {
@@ -19992,12 +20535,124 @@
 
 package android.telephony {
 
+  public abstract class CellIdentity implements android.os.Parcelable {
+    method public int describeContents();
+    method public abstract int hashCode();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class CellIdentityCdma extends android.telephony.CellIdentity implements android.os.Parcelable {
+    method public int getBasestationId();
+    method public int getLatitude();
+    method public int getLongitude();
+    method public int getNetworkId();
+    method public int getSystemId();
+    method public int hashCode();
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class CellIdentityGsm extends android.telephony.CellIdentity implements android.os.Parcelable {
+    method public int getCid();
+    method public int getLac();
+    method public int getMcc();
+    method public int getMnc();
+    method public int getPsc();
+    method public int hashCode();
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class CellIdentityLte extends android.telephony.CellIdentity implements android.os.Parcelable {
+    method public int getCi();
+    method public int getMcc();
+    method public int getMnc();
+    method public int getPci();
+    method public int getTac();
+    method public int hashCode();
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class CellInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public long getTimeStamp();
+    method public boolean isRegistered();
+    method public 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();
+    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();
+    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();
+    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 implements android.os.Parcelable {
+    method public int describeContents();
+    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();
+    method public abstract void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public class CellSignalStrengthCdma extends android.telephony.CellSignalStrength implements android.os.Parcelable {
+    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 class CellSignalStrengthGsm extends android.telephony.CellSignalStrength implements android.os.Parcelable {
+    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 class CellSignalStrengthLte extends android.telephony.CellSignalStrength implements android.os.Parcelable {
+    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 +20725,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 +20736,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 +20862,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 +21383,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 +21431,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 +21521,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;
@@ -21513,6 +22180,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 +22719,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 +22991,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 +23069,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 +23121,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);
   }
@@ -22491,6 +23185,10 @@
     method public android.util.JsonWriter value(java.lang.Number) throws java.io.IOException;
   }
 
+  public class LocaleUtil {
+    method public static int getLayoutDirectionFromLocale(java.util.Locale);
+  }
+
   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);
@@ -22560,6 +23258,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,21 +23590,26 @@
   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 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
   }
 
@@ -22978,8 +23682,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 +24600,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;
@@ -24023,6 +24731,9 @@
     method public void buildDrawingCache(boolean);
     method public void buildLayer();
     method public boolean callOnClick();
+    method public boolean canResolveLayoutDirection();
+    method public boolean canResolveTextAlignment();
+    method public boolean canResolveTextDirection();
     method public boolean canScrollHorizontally(int);
     method public boolean canScrollVertically(int);
     method public void cancelLongPress();
@@ -24074,6 +24785,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 +24800,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);
@@ -24111,7 +24824,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,13 +24850,18 @@
     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 int getResolvedLayoutDirection();
+    method public int getResolvedTextAlignment();
+    method public int getResolvedTextDirection();
     method public android.content.res.Resources getResources();
     method public final int getRight();
     method protected float getRightFadingEdgeStrength();
@@ -24164,6 +24884,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();
@@ -24213,10 +24935,13 @@
     method public boolean isHovered();
     method public boolean isInEditMode();
     method public boolean isInTouchMode();
+    method protected static boolean isLayoutDirectionRtl(java.util.Locale);
     method public boolean isLayoutRequested();
+    method public boolean isLayoutRtl();
     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();
@@ -24264,7 +24989,15 @@
     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 onPaddingChanged(int);
     method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+    method public void onResolveDrawables(int);
+    method public void onResolvedLayoutDirectionChanged();
+    method public void onResolvedLayoutDirectionReset();
+    method public void onResolvedTextAlignmentChanged();
+    method public void onResolvedTextAlignmentReset();
+    method public void onResolvedTextDirectionChanged();
+    method public void onResolvedTextDirectionReset();
     method protected void onRestoreInstanceState(android.os.Parcelable);
     method protected android.os.Parcelable onSaveInstanceState();
     method public void onScreenStateChanged(int);
@@ -24307,8 +25040,16 @@
     method public void requestLayout();
     method public boolean requestRectangleOnScreen(android.graphics.Rect);
     method public boolean requestRectangleOnScreen(android.graphics.Rect, boolean);
+    method public void resetResolvedLayoutDirection();
+    method public void resetResolvedTextAlignment();
+    method public void resetResolvedTextDirection();
+    method public void resolveDrawables();
+    method public void resolveLayoutDirection();
+    method public void resolvePadding();
     method public static int resolveSize(int, int);
     method public static int resolveSizeAndState(int, int, int);
+    method public void resolveTextAlignment();
+    method public void resolveTextDirection();
     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);
@@ -24346,7 +25087,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 +25114,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 +25139,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 +25199,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 +25253,21 @@
     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 int TEXT_ALIGNMENT_DEFAULT;
+    field public static final int TEXT_ALIGNMENT_GRAVITY = 1; // 0x1
     field public static final int TEXT_ALIGNMENT_INHERIT = 0; // 0x0
-    field public static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = 131072; // 0x20000
+    field public static final int TEXT_ALIGNMENT_TEXT_END = 3; // 0x3
+    field public static final int TEXT_ALIGNMENT_TEXT_START = 2; // 0x2
+    field public static final int TEXT_ALIGNMENT_VIEW_END = 6; // 0x6
+    field public static final int TEXT_ALIGNMENT_VIEW_START = 5; // 0x5
+    field public static final int TEXT_DIRECTION_ANY_RTL = 2; // 0x2
+    field public static int TEXT_DIRECTION_DEFAULT;
+    field public static final int TEXT_DIRECTION_FIRST_STRONG = 1; // 0x1
+    field public static final int TEXT_DIRECTION_INHERIT = 0; // 0x0
+    field public static final int TEXT_DIRECTION_LOCALE = 5; // 0x5
+    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 +25571,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 onResolveLayoutDirection(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 +25586,14 @@
     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 protected boolean isLayoutRtl();
+    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;
@@ -25128,7 +25901,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 +26024,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 +26083,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 +26120,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 +26764,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 +26782,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 +26896,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 +26965,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 +27044,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 +27061,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 +27091,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 +27106,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 +27118,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 +27131,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 +27153,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 +27164,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 +27181,15 @@
     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 +27272,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 +27287,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 +27302,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,23 +27330,20 @@
     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);
     method public void setWebChromeClient(android.webkit.WebChromeClient);
     method public void setWebViewClient(android.webkit.WebViewClient);
@@ -26681,7 +27427,6 @@
     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 +27790,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 +27906,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 +28048,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);
   }
@@ -27762,6 +28512,7 @@
     method public void setHeight(int);
     method public void setHorizontalOffset(int);
     method public void setInputMethodMode(int);
+    method public void setLayoutDirection(int);
     method public void setListSelector(android.graphics.drawable.Drawable);
     method public void setModal(boolean);
     method public void setOnDismissListener(android.widget.PopupWindow.OnDismissListener);
@@ -28114,19 +28865,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 +28896,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 +28930,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 +29199,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();
@@ -28667,9 +29426,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 +29488,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();
@@ -28756,11 +29521,13 @@
     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 +29571,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 +29591,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 +29667,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 +29693,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 +29705,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..bc9e74e 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;
 
@@ -132,18 +133,34 @@
             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 +170,7 @@
         mStopOption = false;
         mRepeat = 0;
         mProfileFile = null;
-        mUserId = 0;
+        mUserId = defUser;
         Uri data = null;
         String type = null;
 
@@ -317,10 +334,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 +404,30 @@
     }
 
     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.");
         }
     }
 
     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 +456,7 @@
                     packageName = activities.get(0).activityInfo.packageName;
                 }
                 System.out.println("Stopping: " + packageName);
-                mAm.forceStopPackage(packageName);
+                mAm.forceStopPackage(packageName, mUserId);
                 Thread.sleep(250);
             }
     
@@ -457,11 +482,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 +570,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 +604,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 +617,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 +637,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 +666,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 +694,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 +736,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 +769,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,7 +781,24 @@
     }
 
     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;
@@ -718,7 +814,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 +831,6 @@
                 persistent = true;
             } else {
                 System.err.println("Error: Unknown option: " + opt);
-                showUsage();
                 return;
             }
         }
@@ -749,13 +844,27 @@
     }
 
     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 +1153,6 @@
                 gdbPort = nextArgRequired();
             } else {
                 System.err.println("Error: Unknown option: " + opt);
-                showUsage();
                 return;
             }
         }
@@ -1062,7 +1170,6 @@
             enabled = false;
         } else {
             System.err.println("Error: enabled mode must be 'on' or 'off' at " + mode);
-            showUsage();
             return;
         }
 
@@ -1080,34 +1187,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 +1215,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 +1421,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 +1454,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 +1486,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" +
@@ -1353,10 +1514,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/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..2934261 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,15 @@
 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];
 
     if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
         ALOGE("invalid uid/gid: %d %d\n", uid, gid);
@@ -43,64 +47,49 @@
         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));
+    if (symlink(applibdir, libsymlink) < 0) {
+        ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, applibdir,
+                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;
-    }
-
-#ifdef HAVE_SELINUX
-    if (selinux_android_setfilecon(libdir, pkgname, AID_SYSTEM) < 0) {
-        ALOGE("cannot setfilecon dir '%s': %s\n", libdir, strerror(errno));
-        unlink(libdir);
-        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;
 }
 
@@ -183,7 +172,6 @@
 int make_user_data(const char *pkgname, uid_t uid, uid_t persona)
 {
     char pkgdir[PKG_PATH_MAX];
-    char real_libdir[PKG_PATH_MAX];
 
     // Create the data dir for the package
     if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona)) {
@@ -193,6 +181,11 @@
         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 (chown(pkgdir, uid, uid) < 0) {
         ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
         unlink(pkgdir);
@@ -212,12 +205,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)
@@ -259,6 +263,11 @@
         }
         closedir(d);
     }
+
+    if (ensure_media_user_dirs((userid_t) target_persona) == -1) {
+        return -1;
+    }
+
     return 0;
 }
 
@@ -273,17 +282,6 @@
     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 +291,66 @@
  */
 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 (if it is mounted as part
+    // of the internal storage).
+    strcpy(tmpdir, android_media_dir.path);
+    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");
+    }
+
+    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 +389,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)
@@ -460,7 +436,7 @@
         }
     }
 
-    if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, 0)) {
+    if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, persona)) {
         goto done;
     }
 
@@ -645,16 +621,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 +646,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) {
@@ -983,13 +969,13 @@
 
     if (stat(dataDir, &s) < 0) return -1;
 
-    if (chown(dataDir, 0, 0) < 0) {
+    if (chown(dataDir, AID_INSTALL, AID_INSTALL) < 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));
+        ALOGE("linklib() 1: failed to chmod '%s': %s\n", dataDir, strerror(errno));
         rc = -1;
         goto out;
     }
@@ -1027,7 +1013,7 @@
 
 out:
     if (chmod(dataDir, s.st_mode) < 0) {
-        ALOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno));
+        ALOGE("linklib() 2: failed to chmod '%s': %s\n", dataDir, strerror(errno));
         rc = -errno;
     }
 
@@ -1038,85 +1024,3 @@
 
     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..a099537 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"
 
 
@@ -72,11 +75,6 @@
     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 */
-}
-
 static int do_get_size(char **arg, char reply[REPLY_MAX])
 {
     int64_t codesize = 0;
@@ -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
@@ -127,11 +126,6 @@
     return linklib(arg[0], arg[1]);
 }
 
-static int do_unlinklib(char **arg, char reply[REPLY_MAX])
-{
-    return unlinklib(arg[0]);
-}
-
 struct cmdinfo {
     const char *name;
     unsigned numargs;
@@ -149,12 +143,10 @@
     { "fixuid",               3, do_fixuid },
     { "freecache",            1, do_free_cache },
     { "rmcache",              1, do_rm_cache },
-    { "protect",              2, do_protect },
-    { "getsize",              4, do_get_size },
+    { "getsize",              5, do_get_size },
     { "rmuserdata",           2, do_rm_user_data },
     { "movefiles",            0, do_movefiles },
     { "linklib",              2, do_linklib },
-    { "unlinklib",            1, do_unlinklib },
     { "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..a229b970 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,8 @@
 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);
+
 /* commands.c */
 
 int install(const char *pkgname, uid_t uid, gid_t gid);
@@ -152,11 +203,10 @@
 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);
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..e0f54fb 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -35,13 +35,14 @@
 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 java.io.File;
 import java.lang.reflect.Field;
@@ -59,6 +60,7 @@
 
 public final class Pm {
     IPackageManager mPm;
+    IUserManager mUm;
 
     private WeakHashMap<String, Resources> mResourceCache
             = new WeakHashMap<String, Resources>();
@@ -69,7 +71,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 +83,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 +159,11 @@
             return;
         }
 
+        if ("trim-caches".equals(op)) {
+            runTrimCaches();
+            return;
+        }
+
         if ("create-user".equals(op)) {
             runCreateUser();
             return;
@@ -167,11 +174,6 @@
             return;
         }
 
-        if ("list-users".equals(op)) {
-            runListUsers();
-            return;
-        }
-
         try {
             if (args.length == 1) {
                 if (args[0].equalsIgnoreCase("-l")) {
@@ -211,7 +213,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 +231,6 @@
             runListUsers();
         } else {
             System.err.println("Error: unknown list type '" + type + "'");
-            showUsage();
         }
     }
 
@@ -242,6 +242,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 +262,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 +313,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 +321,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 +421,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 +517,6 @@
                     dangerousOnly = true;
                 } else {
                     System.err.println("Error: Unknown option: " + opt);
-                    showUsage();
                     return;
                 }
             }
@@ -667,7 +665,6 @@
         String pkg = nextArg();
         if (pkg == null) {
             System.err.println("Error: no package specified");
-            showUsage();
             return;
         }
         displayPackageFilePath(pkg);
@@ -725,20 +722,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 +759,7 @@
     }
 
     private void runInstall() {
-        int installFlags = 0;
+        int installFlags = PackageManager.INSTALL_ALL_USERS;
         String installerPackageName = null;
 
         String opt;
@@ -777,6 +771,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 +783,6 @@
                 installerPackageName = nextOptionData();
                 if (installerPackageName == null) {
                     System.err.println("Error: no value specified for -i");
-                    showUsage();
                     return;
                 }
             } else if (opt.equals("-t")) {
@@ -798,51 +793,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 +854,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 +861,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 +887,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 +909,6 @@
             apkURI = Uri.fromFile(new File(apkFilePath));
         } else {
             System.err.println("Error: no package specified");
-            showUsage();
             return;
         }
 
@@ -910,8 +923,11 @@
 
         PackageInstallObserver obs = new PackageInstallObserver();
         try {
-            mPm.installPackageWithVerification(apkURI, obs, installFlags, installerPackageName,
-                    verificationURI, null, encryptionParams);
+            VerificationParams verificationParams = new VerificationParams(verificationURI,
+                    originatingURI, referrerURI, null);
+
+            mPm.installPackageWithVerificationAndEncryption(apkURI, obs, installFlags,
+                    installerPackageName, verificationParams, encryptionParams);
 
             synchronized (obs) {
                 while (!obs.finished) {
@@ -966,23 +982,16 @@
     }
 
     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) {
+            if (mUm.createUser(name, 0) == null) {
                 System.err.println("Error: couldn't create User.");
-                showUsage();
             }
         } catch (RemoteException e) {
             System.err.println(e.toString());
@@ -992,29 +1001,21 @@
     }
 
     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.err.println("Error: couldn't remove user #" + userId + ".");
             }
         } catch (RemoteException e) {
             System.err.println(e.toString());
@@ -1023,13 +1024,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();
             if (users == null) {
                 System.err.println("Error: couldn't get users");
             } else {
@@ -1057,11 +1053,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 +1099,7 @@
         return obs.result;
     }
 
-    class ClearDataObserver extends IPackageDataObserver.Stub {
+    static class ClearDataObserver extends IPackageDataObserver.Stub {
         boolean finished;
         boolean result;
 
@@ -1123,8 +1124,8 @@
 
         ClearDataObserver obs = new ClearDataObserver();
         try {
-            if (!ActivityManagerNative.getDefault().clearApplicationUserData(pkg, obs,
-                    Binder.getOrigCallingUser())) {
+            // XXX TO DO: add user arg
+            if (!ActivityManagerNative.getDefault().clearApplicationUserData(pkg, obs, 0)) {
                 System.err.println("Failed");
             }
 
@@ -1272,6 +1273,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 +1424,30 @@
     }
 
     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 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("");
         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 +1476,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 +1487,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 +1512,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/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/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/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 22e454f..9caf84f 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -50,7 +50,8 @@
 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;
@@ -92,6 +93,7 @@
     private final Context mContext;
 
     private final PackageManager mPackageManager;
+    private UserManager mUserManager;
 
     private HandlerThread mMessageThread;
     private final MessageHandler mMessageHandler;
@@ -245,6 +247,13 @@
         initUser(0);
     }
 
+    private UserManager getUserManager() {
+        if (mUserManager == null) {
+            mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        }
+        return mUserManager;
+    }
+
     private UserAccounts initUser(int userId) {
         synchronized (mUsers) {
             UserAccounts accounts = mUsers.get(userId);
@@ -345,7 +354,7 @@
     }
 
     private UserAccounts getUserAccountsForCaller() {
-        return getUserAccounts(UserId.getCallingUserId());
+        return getUserAccounts(UserHandle.getCallingUserId());
     }
 
     protected UserAccounts getUserAccounts(int userId) {
@@ -360,7 +369,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;
@@ -382,12 +391,7 @@
     }
 
     private List<UserInfo> getAllUsers() {
-        try {
-            return AppGlobals.getPackageManager().getUsers();
-        } catch (RemoteException re) {
-            // Local to system process, shouldn't happen
-        }
-        return null;
+        return getUserManager().getUsers();
     }
 
     public void onServiceChanged(AuthenticatorDescription desc, boolean removed) {
@@ -896,7 +900,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 +1004,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,7 +1052,7 @@
         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();
+        final UserAccounts accounts = getUserAccountsForCaller();
         AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo =
             mAuthenticatorCache.getServiceInfo(
                     AuthenticatorDescription.newKey(account.type));
@@ -1137,7 +1141,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 +1152,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,9 +1173,10 @@
             title = titleAndSubtitle.substring(0, index);
             subtitle = titleAndSubtitle.substring(index + 1);            
         }
-        n.setLatestEventInfo(mContext,
-                title, subtitle,
-                PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT));
+        n.setLatestEventInfo(mContext, title, subtitle,
+                PendingIntent.getActivityAsUser(mContext, 0, intent,
+                        PendingIntent.FLAG_CANCEL_CURRENT,
+                        null, new UserHandle(userId)));
         installNotification(getCredentialPermissionNotificationId(account, authTokenType, uid), n);
     }
 
@@ -1218,7 +1224,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>(
@@ -1875,7 +1881,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 +1890,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);
@@ -2079,7 +2085,7 @@
     }
 
     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,7 +2095,7 @@
             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));
@@ -2099,8 +2105,9 @@
                         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));
+                        message, PendingIntent.getActivityAsUser(
+                        mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT,
+                        null, new UserHandle(userId)));
                 installNotification(notificationId, n);
             }
         } finally {
@@ -2265,7 +2272,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();
@@ -2299,7 +2306,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();
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/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..2337790 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..7606d5e3 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_";
@@ -696,7 +698,7 @@
         Object activity;
         HashMap<String, Object> children;
         ArrayList<Fragment> fragments;
-        SparseArray<LoaderManagerImpl> loaders;
+        HashMap<String, LoaderManagerImpl> loaders;
     }
     /* package */ NonConfigurationInstances mLastNonConfigurationInstances;
     
@@ -714,8 +716,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 +751,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 +816,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 +1033,7 @@
             if (mLoaderManager != null) {
                 mLoaderManager.doStart();
             } else if (!mCheckedForLoaderManager) {
-                mLoaderManager = getLoaderManager(-1, mLoadersStarted, false);
+                mLoaderManager = getLoaderManager(null, mLoadersStarted, false);
             }
             mCheckedForLoaderManager = true;
         }
@@ -1600,13 +1609,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 +1655,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 +2721,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 +3397,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.
      *
@@ -4247,7 +4290,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 +4751,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 +4776,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 +5010,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 +5049,7 @@
             Configuration config) {
         attachBaseContext(context);
 
-        mFragments.attachActivity(this);
+        mFragments.attachActivity(this, mContainer, null);
         
         mWindow = PolicyManager.makeNewWindow(this);
         mWindow.setCallback(this);
@@ -4990,7 +5075,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 +5110,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 +5128,7 @@
         if (mStopped) {
             mStopped = false;
             if (mToken != null && mParent == null) {
-                WindowManagerImpl.getDefault().setStoppedState(mToken, false);
+                WindowManagerGlobal.getInstance().setStoppedState(mToken, false);
             }
 
             synchronized (mManagedCursors) {
@@ -5137,7 +5228,7 @@
             }
 
             if (mToken != null && mParent == null) {
-                WindowManagerImpl.getDefault().setStoppedState(mToken, true);
+                WindowManagerGlobal.getInstance().setStoppedState(mToken, true);
             }
             
             mFragments.dispatchStop();
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 92b6f72..06f79e7 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;
@@ -1182,7 +1226,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 +1390,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 +1693,8 @@
      */
     public void killBackgroundProcesses(String packageName) {
         try {
-            ActivityManagerNative.getDefault().killBackgroundProcesses(packageName);
+            ActivityManagerNative.getDefault().killBackgroundProcesses(packageName,
+                    UserHandle.myUserId());
         } catch (RemoteException e) {
         }
     }
@@ -1667,7 +1719,8 @@
      */
     public void forceStopPackage(String packageName) {
         try {
-            ActivityManagerNative.getDefault().forceStopPackage(packageName);
+            ActivityManagerNative.getDefault().forceStopPackage(packageName,
+                    UserHandle.myUserId());
         } catch (RemoteException e) {
         }
     }
@@ -1814,12 +1867,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 +1893,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 +1959,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);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
 }
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index e12fa19..773f73c 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,8 +491,9 @@
             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;
@@ -670,7 +708,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 +721,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 +820,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 +909,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 +947,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 +1222,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 +1238,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 +1265,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 +1336,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 +1437,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;
@@ -1452,30 +1495,15 @@
             String process = data.readString();
             boolean managed = data.readInt() != 0;
             String path = data.readString();
+            int userId = data.readInt();
             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);
@@ -1541,6 +1569,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 +1588,15 @@
             return true;
         }
 
+        case IS_USER_RUNNING_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            int userid = data.readInt();
+            boolean result = isUserRunning(userid);
+            reply.writeNoException();
+            reply.writeInt(result ? 1 : 0);
+            return true;
+        }
+
         case REMOVE_SUB_TASK_TRANSACTION:
         {
             data.enforceInterface(IActivityManager.descriptor);
@@ -1694,6 +1742,22 @@
             return true;
         }
 
+        case REGISTER_USER_SWITCH_OBSERVER_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IUserSwitchObserver observer = IUserSwitchObserver.Stub.asInterface(
+                    data.readStrongBinder());
+            registerUserSwitchObserver(observer);
+            return true;
+        }
+
+        case UNREGISTER_USER_SWITCH_OBSERVER_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IUserSwitchObserver observer = IUserSwitchObserver.Stub.asInterface(
+                    data.readStrongBinder());
+            unregisterUserSwitchObserver(observer);
+            return true;
+        }
+
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -1764,10 +1828,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 +1856,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 +1902,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 +1920,7 @@
         } else {
             data.writeInt(0);
         }
+        data.writeInt(userId);
         mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
         reply.readException();
         int result = reply.readInt();
@@ -1939,7 +2041,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 +2051,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 +2160,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 +2277,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
@@ -2459,7 +2574,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 +2582,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 +2591,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 +2599,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();
@@ -2654,7 +2771,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 +2781,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 +2879,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 +2902,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 +2945,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 +3303,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 +3325,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 +3363,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 +3422,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 +3563,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 +3643,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) {
@@ -3576,30 +3690,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 +3778,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 +3804,19 @@
         return userInfo;
     }
 
+    public boolean isUserRunning(int userid) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeInt(userid);
+        mRemote.transact(IS_USER_RUNNING_TRANSACTION, data, reply, 0);
+        reply.readException();
+        boolean result = reply.readInt() != 0;
+        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 +3990,27 @@
         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();
+    }
+
     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 b7e0683..9b82f2a 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -42,6 +42,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 +52,7 @@
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Debug;
+import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -62,7 +65,7 @@
 import android.os.StrictMode;
 import android.os.SystemClock;
 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 +73,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,7 +82,7 @@
 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;
@@ -94,6 +98,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 +108,7 @@
 import java.util.TimeZone;
 import java.util.regex.Pattern;
 
+import libcore.io.EventLogger;
 import libcore.io.IoUtils;
 
 import dalvik.system.CloseGuard;
@@ -165,6 +171,8 @@
             = new HashMap<IBinder, Service>();
     AppBindData mBoundApplication;
     Profiler mProfiler;
+    int mCurDefaultDisplayDpi;
+    boolean mDensityCompatMode;
     Configuration mConfiguration;
     Configuration mCompatConfiguration;
     Configuration mResConfiguration;
@@ -196,7 +204,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> >();
@@ -313,8 +321,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 +615,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 +776,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 +1062,7 @@
         @Override
         public void dumpGfxInfo(FileDescriptor fd, String[] args) {
             dumpGraphicsInfo(fd);
-            WindowManagerImpl.getDefault().dumpGfxInfo(fd);
+            WindowManagerGlobal.getInstance().dumpGfxInfo(fd);
         }
 
         @Override
@@ -1235,7 +1245,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 +1315,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 +1478,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 +1513,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 +1561,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 +1603,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 +1623,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 +1659,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 +1699,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() {
@@ -1652,7 +1740,7 @@
         ApplicationInfo ai = null;
         try {
             ai = getPackageManager().getApplicationInfo(packageName,
-                    PackageManager.GET_SHARED_LIBRARY_FILES, UserId.myUserId());
+                    PackageManager.GET_SHARED_LIBRARY_FILES, UserHandle.myUserId());
         } catch (RemoteException e) {
             // Ignore
         }
@@ -1669,7 +1757,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 +1874,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());
@@ -2086,7 +2175,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
@@ -2587,7 +2677,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 +2685,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 +2783,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 +2826,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 +2875,7 @@
             if (r.isPreHoneycomb()) {
                 QueuedWork.waitToFinish();
             }
-            
+
             // Tell the activity manager we have paused.
             try {
                 ActivityManagerNative.getDefault().activityPaused(token);
@@ -3121,7 +3221,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) {
@@ -3310,7 +3410,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 +3422,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 +3561,8 @@
         
         // If there was a pending configuration change, execute it first.
         if (changedConfig != null) {
+            mCurDefaultDisplayDpi = changedConfig.densityDpi;
+            updateDefaultDensity();
             handleConfigurationChanged(changedConfig, null);
         }
 
@@ -3543,8 +3645,8 @@
             for (ActivityClientRecord ar : mActivities.values()) {
                 Activity a = ar.activity;
                 if (a != null) {
-                    Configuration thisConfig = applyConfigCompatMainThread(newConfig,
-                            ar.packageInfo.mCompatibilityInfo.getIfNeeded());
+                    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.
@@ -3646,7 +3748,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 +3765,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 +3811,30 @@
         return changes != 0;
     }
 
-    final Configuration applyCompatConfiguration() {
+    final void applyNonDefaultDisplayMetricsToConfigurationLocked(
+            DisplayMetrics dm, Configuration config) {
+        config.screenLayout = Configuration.SCREENLAYOUT_SIZE_XLARGE
+                | Configuration.SCREENLAYOUT_LONG_NO;
+        config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
+        config.orientation = (dm.widthPixels >= dm.heightPixels) ?
+                Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT;
+        config.densityDpi = dm.densityDpi;
+        config.screenWidthDp = (int)(dm.widthPixels / dm.density);
+        config.screenHeightDp = (int)(dm.heightPixels / dm.density);
+        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;
@@ -3710,6 +3849,8 @@
             if (mPendingConfiguration != null) {
                 if (!mPendingConfiguration.isOtherSeqNewer(config)) {
                     config = mPendingConfiguration;
+                    mCurDefaultDisplayDpi = config.densityDpi;
+                    updateDefaultDensity();
                 }
                 mPendingConfiguration = null;
             }
@@ -3731,12 +3872,12 @@
             }
             configDiff = mConfiguration.diff(config);
             mConfiguration.updateFrom(config);
-            config = applyCompatConfiguration();
+            config = applyCompatConfiguration(mCurDefaultDisplayDpi);
             callbacks = collectComponentCallbacksLocked(false, config);
         }
         
         // Cleanup hardware accelerated stuff
-        WindowManagerImpl.getDefault().trimLocalMemory();
+        WindowManagerGlobal.getInstance().trimLocalMemory();
 
         freeTextLayoutCachesIfNeeded(configDiff);
 
@@ -3876,7 +4017,7 @@
     final void handleTrimMemory(int level) {
         if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Trimming memory to level: " + level);
 
-        final WindowManagerImpl windowManager = WindowManagerImpl.getDefault();
+        final WindowManagerGlobal windowManager = WindowManagerGlobal.getInstance();
         windowManager.startTrimMemory(level);
 
         ArrayList<ComponentCallbacks2> callbacks;
@@ -3889,7 +4030,7 @@
             callbacks.get(i).onTrimMemory(level);
         }
 
-        windowManager.endTrimMemory();        
+        windowManager.endTrimMemory();
     }
 
     private void setupGraphicsSupport(LoadedApk info, File cacheDir) {
@@ -3910,8 +4051,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 +4077,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 +4120,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 +4170,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);
@@ -4643,7 +4804,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 +4816,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();
@@ -4717,6 +4880,13 @@
         }
     }
 
+    private static class EventLoggingReporter implements EventLogger.Reporter {
+        @Override
+        public void report (int code, Object... list) {
+            EventLog.writeEvent(code, list);
+        }
+    }
+
     public static void main(String[] args) {
         SamplingProfilerIntegration.start();
 
@@ -4725,6 +4895,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/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 191a696..7870031 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -41,17 +41,20 @@
 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.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;
 import android.net.Uri;
 import android.os.Process;
 import android.os.RemoteException;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.util.Log;
+import android.view.Display;
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -69,7 +72,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, UserHandle.myUserId());
             if (pi != null) {
                 return pi;
             }
@@ -199,7 +202,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, UserHandle.myUserId());
             if (ai != null) {
                 return ai;
             }
@@ -214,7 +217,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, UserHandle.myUserId());
             if (ai != null) {
                 return ai;
             }
@@ -229,7 +232,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, UserHandle.myUserId());
             if (ai != null) {
                 return ai;
             }
@@ -244,7 +247,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, UserHandle.myUserId());
             if (si != null) {
                 return si;
             }
@@ -259,7 +262,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, UserHandle.myUserId());
             if (pi != null) {
                 return pi;
             }
@@ -404,6 +407,12 @@
     @SuppressWarnings("unchecked")
     @Override
     public List<PackageInfo> getInstalledPackages(int flags) {
+        return getInstalledPackages(flags, UserHandle.myUserId());
+    }
+
+    /** @hide */
+    @Override
+    public List<PackageInfo> getInstalledPackages(int flags, int userId) {
         try {
             final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>();
             PackageInfo lastItem = null;
@@ -411,7 +420,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 +433,7 @@
     @SuppressWarnings("unchecked")
     @Override
     public List<ApplicationInfo> getInstalledApplications(int flags) {
-        int userId = UserId.getUserId(Process.myUid());
+        int userId = UserHandle.getUserId(Process.myUid());
         try {
             final List<ApplicationInfo> applicationInfos = new ArrayList<ApplicationInfo>();
             ApplicationInfo lastItem = null;
@@ -448,7 +457,7 @@
             return mPM.resolveIntent(
                 intent,
                 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                    flags, UserId.myUserId());
+                    flags, UserHandle.myUserId());
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -457,12 +466,19 @@
     @Override
     public List<ResolveInfo> queryIntentActivities(Intent intent,
                                                    int flags) {
+        return queryIntentActivitiesForUser(intent, flags, UserHandle.myUserId());
+    }
+
+    /** @hide Same as above but for a specific user */
+    @Override
+    public List<ResolveInfo> queryIntentActivitiesForUser(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 +510,23 @@
         try {
             return mPM.queryIntentActivityOptions(caller, specifics,
                                                   specificTypes, intent, intent.resolveTypeIfNeeded(resolver),
-                                                  flags, UserId.myUserId());
+                                                  flags, UserHandle.myUserId());
+        } 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 +534,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, UserHandle.myUserId());
     }
 
     @Override
@@ -520,7 +544,7 @@
                 intent,
                 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                 flags,
-                UserId.myUserId());
+                UserHandle.myUserId());
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -533,7 +557,7 @@
                 intent,
                 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                 flags,
-                UserId.myUserId());
+                UserHandle.myUserId());
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -543,7 +567,7 @@
     public ProviderInfo resolveContentProvider(String name,
                                                int flags) {
         try {
-            return mPM.resolveContentProvider(name, flags, UserId.myUserId());
+            return mPM.resolveContentProvider(name, flags, UserHandle.myUserId());
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -712,8 +736,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;
         }
@@ -984,6 +1008,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 +1044,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 +1094,7 @@
     public void clearApplicationUserData(String packageName,
                                          IPackageDataObserver observer) {
         try {
-            mPM.clearApplicationUserData(packageName, observer, UserId.myUserId());
+            mPM.clearApplicationUserData(packageName, observer, UserHandle.myUserId());
         } catch (RemoteException e) {
             // Should never happen!
         }
@@ -1066,10 +1127,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 +1167,17 @@
     public void addPreferredActivity(IntentFilter filter,
                                      int match, ComponentName[] set, ComponentName activity) {
         try {
-            mPM.addPreferredActivity(filter, match, set, activity);
+            mPM.addPreferredActivity(filter, match, set, activity, UserHandle.myUserId());
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+
+    @Override
+    public void addPreferredActivity(IntentFilter filter, int match,
+            ComponentName[] set, ComponentName activity, int userId) {
+        try {
+            mPM.addPreferredActivity(filter, match, set, activity, userId);
         } catch (RemoteException e) {
             // Should never happen!
         }
@@ -1146,7 +1217,7 @@
     public void setComponentEnabledSetting(ComponentName componentName,
                                            int newState, int flags) {
         try {
-            mPM.setComponentEnabledSetting(componentName, newState, flags, UserId.myUserId());
+            mPM.setComponentEnabledSetting(componentName, newState, flags, UserHandle.myUserId());
         } catch (RemoteException e) {
             // Should never happen!
         }
@@ -1155,7 +1226,7 @@
     @Override
     public int getComponentEnabledSetting(ComponentName componentName) {
         try {
-            return mPM.getComponentEnabledSetting(componentName, UserId.myUserId());
+            return mPM.getComponentEnabledSetting(componentName, UserHandle.myUserId());
         } catch (RemoteException e) {
             // Should never happen!
         }
@@ -1166,7 +1237,7 @@
     public void setApplicationEnabledSetting(String packageName,
                                              int newState, int flags) {
         try {
-            mPM.setApplicationEnabledSetting(packageName, newState, flags, UserId.myUserId());
+            mPM.setApplicationEnabledSetting(packageName, newState, flags, UserHandle.myUserId());
         } catch (RemoteException e) {
             // Should never happen!
         }
@@ -1175,86 +1246,13 @@
     @Override
     public int getApplicationEnabledSetting(String packageName) {
         try {
-            return mPM.getApplicationEnabledSetting(packageName, UserId.myUserId());
+            return mPM.getApplicationEnabledSetting(packageName, UserHandle.myUserId());
         } 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/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 411f6d0..92104fa 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -18,6 +18,7 @@
 
 import com.android.internal.policy.PolicyManager;
 
+import android.bluetooth.BluetoothAdapter;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -36,6 +37,7 @@
 import android.content.pm.PackageManager;
 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 +48,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;
@@ -78,19 +81,23 @@
 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.view.CompatibilityInfoHolder;
 import android.view.ContextThemeWrapper;
+import android.view.Display;
 import android.view.WindowManagerImpl;
 import android.view.accessibility.AccessibilityManager;
 import android.view.inputmethod.InputMethodManager;
@@ -131,6 +138,17 @@
     }
 
     @Override
+    public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
+            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);
+    }
+
+    @Override
     public boolean bindService(Intent service, ServiceConnection conn, int flags) {
         throw new ReceiverCallNotAllowedException(
                 "IntentReceiver components are not allowed to bind to services");
@@ -161,6 +179,7 @@
     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;
 
@@ -294,6 +313,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 +361,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 +433,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 +502,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 +514,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 +547,7 @@
 
     @Override
     public AssetManager getAssets() {
-        return mResources.getAssets();
+        return getResources().getAssets();
     }
 
     @Override
@@ -743,7 +787,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(
@@ -880,6 +924,12 @@
         startActivity(intent, null);
     }
 
+    /** @hide */
+    @Override
+    public void startActivityAsUser(Intent intent, UserHandle user) {
+        startActivityAsUser(intent, null, user);
+    }
+
     @Override
     public void startActivity(Intent intent, Bundle options) {
         if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
@@ -893,6 +943,19 @@
             (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) {
         startActivities(intents, null);
@@ -948,20 +1011,7 @@
             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);
+                UserHandle.myUserId());
         } catch (RemoteException e) {
         }
     }
@@ -974,7 +1024,7 @@
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, null,
                 Activity.RESULT_OK, null, null, receiverPermission, false, false,
-                Binder.getOrigCallingUser());
+                UserHandle.myUserId());
         } catch (RemoteException e) {
         }
     }
@@ -988,7 +1038,7 @@
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, null,
                 Activity.RESULT_OK, null, null, receiverPermission, true, false,
-                Binder.getOrigCallingUser());
+                UserHandle.myUserId());
         } catch (RemoteException e) {
         }
     }
@@ -1021,7 +1071,65 @@
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, rd,
                 initialCode, initialData, initialExtras, receiverPermission,
-                true, false, Binder.getOrigCallingUser());
+                true, false, UserHandle.myUserId());
+        } 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) {
         }
     }
@@ -1034,7 +1142,7 @@
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, null,
                 Activity.RESULT_OK, null, null, null, false, true,
-                Binder.getOrigCallingUser());
+                UserHandle.myUserId());
         } catch (RemoteException e) {
         }
     }
@@ -1067,7 +1175,7 @@
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, rd,
                 initialCode, initialData, initialExtras, null,
-                true, true, Binder.getOrigCallingUser());
+                true, true, UserHandle.myUserId());
         } catch (RemoteException e) {
         }
     }
@@ -1082,7 +1190,67 @@
         try {
             intent.setAllowFds(false);
             ActivityManagerNative.getDefault().unbroadcastIntent(
-                    mMainThread.getApplicationThread(), intent, Binder.getOrigCallingUser());
+                    mMainThread.getApplicationThread(), intent, UserHandle.myUserId());
+        } 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) {
+                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, user.getIdentifier());
+        } catch (RemoteException e) {
+        }
+    }
+
+    @Override
+    public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) {
+        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, user.getIdentifier());
         } catch (RemoteException e) {
         }
     }
@@ -1095,11 +1263,18 @@
     @Override
     public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
             String broadcastPermission, Handler scheduler) {
-        return registerReceiverInternal(receiver, filter, broadcastPermission,
-                scheduler, getOuterContext());
+        return registerReceiverInternal(receiver, UserHandle.myUserId(),
+                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 +1297,7 @@
         try {
             return ActivityManagerNative.getDefault().registerReceiver(
                     mMainThread.getApplicationThread(), mBasePackageName,
-                    rd, filter, broadcastPermission);
+                    rd, filter, broadcastPermission, userId);
         } catch (RemoteException e) {
             return null;
         }
@@ -1144,11 +1319,21 @@
 
     @Override
     public ComponentName startService(Intent service) {
+        return startServiceAsUser(service, Process.myUserHandle());
+    }
+
+    @Override
+    public boolean stopService(Intent service) {
+        return stopServiceAsUser(service, Process.myUserHandle());
+    }
+
+    @Override
+    public ComponentName startServiceAsUser(Intent service, UserHandle user) {
         try {
             service.setAllowFds(false);
             ComponentName cn = ActivityManagerNative.getDefault().startService(
                 mMainThread.getApplicationThread(), service,
-                service.resolveTypeIfNeeded(getContentResolver()));
+                service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
             if (cn != null && cn.getPackageName().equals("!")) {
                 throw new SecurityException(
                         "Not allowed to start service " + service
@@ -1161,12 +1346,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 +1365,16 @@
     @Override
     public boolean bindService(Intent service, ServiceConnection conn,
             int flags) {
-        return bindService(service, conn, flags, UserId.getUserId(Process.myUid()));
+        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 +1392,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 +1405,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 +1428,7 @@
                 arguments.setAllowFds(false);
             }
             return ActivityManagerNative.getDefault().startInstrumentation(
-                    className, profileFile, 0, arguments, null);
+                    className, profileFile, 0, arguments, null, UserHandle.myUserId());
         } catch (RemoteException e) {
             // System has crashed, nothing we can do.
         }
@@ -1312,7 +1503,7 @@
                     (message != null ? (message + ": ") : "") +
                     (selfToo
                      ? "Neither user " + uid + " nor current process has "
-                     : "User " + uid + " does not have ") +
+                     : "uid " + uid + " does not have ") +
                     permission +
                     ".");
         }
@@ -1508,10 +1699,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();
@@ -1553,6 +1789,7 @@
         mResources = context.mResources;
         mMainThread = context.mMainThread;
         mContentResolver = context.mContentResolver;
+        mDisplay = context.mDisplay;
         mOuterContext = this;
     }
 
@@ -1576,12 +1813,12 @@
                         " 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;
     }
 
     final void init(Resources resources, ActivityThread mainThread) {
@@ -1608,10 +1845,6 @@
         return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext());
     }
 
-    final void setActivityToken(IBinder token) {
-        mActivityToken = token;
-    }
-
     final void setOuterContext(Context context) {
         mOuterContext = context;
     }
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/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/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 39e2423..7f11437 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -29,7 +29,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;
@@ -380,6 +379,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 +415,8 @@
 
     int mCurState = Fragment.INITIALIZING;
     Activity mActivity;
+    FragmentContainer mContainer;
+    Fragment mParent;
     
     boolean mNeedMenuInvalidate;
     boolean mStateSaved;
@@ -427,6 +435,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 +549,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 +562,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 +576,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);
@@ -562,7 +592,11 @@
         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 +692,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,6 +771,10 @@
 
     void moveToState(Fragment f, int newState, int transit, int transitionStyle,
             boolean keepActive) {
+        //if (DEBUG) 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) {
             newState = Fragment.CREATED;
@@ -782,30 +825,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 +860,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 +887,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 +898,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 +915,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 +934,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 +993,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 +1007,7 @@
                                     makeInactive(f);
                                 } else {
                                     f.mActivity = null;
+                                    f.mParentFragment = null;
                                     f.mFragmentManager = null;
                                 }
                             }
@@ -1021,11 +1031,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 +1080,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 +1101,7 @@
             mAvailIndices = new ArrayList<Integer>();
         }
         mAvailIndices.add(f.mIndex);
-        mActivity.invalidateFragmentIndex(f.mIndex);
+        mActivity.invalidateFragment(f.mWho);
         f.initState();
     }
     
@@ -1267,7 +1277,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 +1547,7 @@
         if (mStateBundle == null) {
             mStateBundle = new Bundle();
         }
-        f.onSaveInstanceState(mStateBundle);
+        f.performSaveInstanceState(mStateBundle);
         if (!mStateBundle.isEmpty()) {
             result = mStateBundle;
             mStateBundle = null;
@@ -1583,12 +1593,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 +1608,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 +1649,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,7 +1716,7 @@
         for (int i=0; i<fms.mActive.length; i++) {
             FragmentState fs = fms.mActive[i];
             if (fs != null) {
-                Fragment f = fs.instantiate(mActivity);
+                Fragment f = fs.instantiate(mActivity, mParent);
                 if (DEBUG) Log.v(TAG, "restoreAllState: adding #" + i + ": " + f);
                 mActive.add(f);
                 // Now that the fragment is instantiated (or came from being
@@ -1755,8 +1756,8 @@
             for (int i=0; i<fms.mAdded.length; i++) {
                 Fragment f = mActive.get(fms.mAdded[i]);
                 if (f == null) {
-                    throw new IllegalStateException(
-                            "No instantiated fragment for index #" + fms.mAdded[i]);
+                    throwException(new IllegalStateException(
+                            "No instantiated fragment for index #" + fms.mAdded[i]));
                 }
                 f.mAdded = true;
                 if (DEBUG) Log.v(TAG, "restoreAllState: making added #" + i + ": " + f);
@@ -1783,9 +1784,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 +1823,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 +1841,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 +1852,7 @@
             for (int i=0; i<mAdded.size(); i++) {
                 Fragment f = mAdded.get(i);
                 if (f != null) {
-                    f.onLowMemory();
+                    f.performLowMemory();
                 }
             }
         }
@@ -1854,7 +1863,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 +1875,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 +1906,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 +1920,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 +1934,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 +1948,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..2fb17b6 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,33 +80,29 @@
     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 List getServices(int maxNum, int flags) throws RemoteException;
     public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState()
@@ -129,9 +129,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,
@@ -156,7 +156,7 @@
     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 +173,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 +204,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 +264,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 +272,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 +293,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 +305,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;
 
     public int getFrontActivityScreenCompatMode() throws RemoteException;
     public void setFrontActivityScreenCompatMode(int mode) throws RemoteException;
@@ -327,7 +323,9 @@
 
     // 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) throws RemoteException;
 
     public boolean removeSubTask(int taskId, int subTaskIndex) throws RemoteException;
 
@@ -358,6 +356,9 @@
     // 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;
+
     /*
      * Private non-Binder interfaces
      */
@@ -491,7 +492,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 +547,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 HANDLE_INCOMING_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+93;
 
-
-    int START_ACTIVITY_IN_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+94;
-    int KILL_APPLICATION_WITH_UID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+95;
+    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 +575,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 +606,8 @@
     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;
 }
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..ee4e964 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;
@@ -1518,6 +1519,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/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..cfc8bbd 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,7 @@
     private Drawable mRemoteIndicator;
     private boolean mRemoteActive;
     private boolean mToggleMode;
+    private boolean mCheatSheetEnabled;
 
     private int mMinWidth;
     private int mMinHeight;
@@ -82,6 +88,7 @@
         a.recycle();
 
         setClickable(true);
+        setLongClickable(true);
 
         setRouteTypes(routeTypes);
     }
@@ -129,6 +136,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.
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/NotificationManager.java b/core/java/android/app/NotificationManager.java
index bf83f5e..c095280 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
@@ -121,7 +126,27 @@
         String pkg = mContext.getPackageName();
         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 (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 +175,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 +204,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..e7cea57 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,29 @@
                     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
+     */
+    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 +384,8 @@
             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) {
         }
@@ -371,7 +423,7 @@
                     ActivityManager.INTENT_SENDER_BROADCAST, 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) {
         }
@@ -410,7 +462,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 +650,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 +672,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 +683,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..eb5a652
--- /dev/null
+++ b/core/java/android/app/Presentation.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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 resume.
+ *
+ * @see {@link DisplayManager} for information on how to enumerate displays.
+ */
+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, null);
+
+        // 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();
+    }
+
+    /**
+     * 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/TaskStackBuilder.java b/core/java/android/app/TaskStackBuilder.java
index f21b3fd..cadf5e4 100644
--- a/core/java/android/app/TaskStackBuilder.java
+++ b/core/java/android/app/TaskStackBuilder.java
@@ -124,24 +124,12 @@
      * @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.
+            addParentStack(parent.getComponent());
+            addNextIntent(parent);
         }
         return this;
     }
@@ -155,24 +143,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 +162,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");
@@ -243,11 +216,7 @@
                     "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);
+        mSourceContext.startActivities(getIntents(), options);
     }
 
     /**
@@ -287,11 +256,8 @@
                     "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);
     }
 
     /**
@@ -302,6 +268,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..c8062ca 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_WIDGETS = 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_WIDGETS, "disable-keyguard-widgets",
+                com.android.internal.R.string.policylab_disableKeyguardWidgets,
+                com.android.internal.R.string.policydesc_disableKeyguardWidgets));
 
         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..4c55bb3 100755
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1155,6 +1155,16 @@
             = "android.app.action.START_ENCRYPTION";
 
     /**
+     * Widgets are enabled in keyguard
+     */
+    public static final int KEYGUARD_DISABLE_WIDGETS_NONE = 0;
+
+    /**
+     * Disable all keyguard widgets
+     */
+    public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 0x7fffffff;
+
+    /**
      * Called by an application that is administering the device to
      * request that the storage system be encrypted.
      *
@@ -1284,6 +1294,46 @@
     }
 
     /**
+     * Called by an application that is administering the device to disable adding widgets to
+     * keyguard.  After setting this, keyguard widgets will be disabled according to the state
+     * provided.
+     *
+     * <p>The calling device admin must have requested
+     * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_WIDGETS} 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 DevicePolicyManager#KEYGUARD_DISABLE_WIDGETS_ALL} or
+     * {@link DevicePolicyManager#KEYGUARD_DISABLE_WIDGETS_NONE} (the default).
+     */
+    public void setKeyguardWidgetsDisabled(ComponentName admin, int which) {
+        if (mService != null) {
+            try {
+                mService.setKeyguardWidgetsDisabled(admin, which);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+    }
+
+    /**
+     * Determine whether or not widgets 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 widgets in keyguard.
+     */
+    public int getKeyguardWidgetsDisabled(ComponentName admin) {
+        if (mService != null) {
+            try {
+                return mService.getKeyguardWidgetsDisabled(admin);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+        return KEYGUARD_DISABLE_WIDGETS_NONE;
+    }
+
+    /**
      * @hide
      */
     public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing) {
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 9419a62..0b7ec122 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -48,7 +48,7 @@
 
     void setPasswordMinimumNonLetter(in ComponentName who, int length);
     int getPasswordMinimumNonLetter(in ComponentName who);
-    
+
     void setPasswordHistoryLength(in ComponentName who, int length);
     int getPasswordHistoryLength(in ComponentName who);
 
@@ -59,17 +59,17 @@
 
     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);
-    
+
     void lockNow();
-    
+
     void wipeData(int flags);
 
     ComponentName setGlobalProxy(in ComponentName admin, String proxySpec, String exclusionList);
@@ -82,6 +82,9 @@
     void setCameraDisabled(in ComponentName who, boolean disabled);
     boolean getCameraDisabled(in ComponentName who);
 
+    void setKeyguardWidgetsDisabled(in ComponentName who, int which);
+    int getKeyguardWidgetsDisabled(in ComponentName who);
+
     void setActiveAdmin(in ComponentName policyReceiver, boolean refreshing);
     boolean isAdminActive(in ComponentName policyReceiver);
     List<ComponentName> getActiveAdmins();
@@ -89,7 +92,7 @@
     void getRemoveWarning(in ComponentName policyReceiver, in RemoteCallback result);
     void removeActiveAdmin(in ComponentName policyReceiver);
     boolean hasGrantedPolicy(in ComponentName policyReceiver, int usesPolicy);
-    
+
     void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase,
         int numbers, int symbols, int nonletter);
     void reportFailedPasswordAttempt();
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..84a447f 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -24,11 +24,14 @@
 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 +44,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;
@@ -65,6 +69,11 @@
             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 +86,7 @@
         public UpdateHandler(Looper looper) {
             super(looper);
         }
-        
+
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case HANDLE_UPDATE: {
@@ -88,6 +97,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 +108,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 +148,7 @@
     public void startListening() {
         int[] updatedIds;
         ArrayList<RemoteViews> updatedViews = new ArrayList<RemoteViews>();
-        
+
         try {
             if (mPackageName == null) {
                 mPackageName = mContext.getPackageName();
@@ -170,7 +196,33 @@
     }
 
     /**
-     * Stop listening to changes for this AppWidget.  
+     * Get a appWidgetId for a host in the calling process.
+     *
+     * @return a appWidgetId
+     * @hide
+     */
+    public static int allocateAppWidgetIdForHost(String packageName, int hostId) {
+        checkCallerIsSystem();
+        try {
+            if (sService == null) {
+                bindService();
+            }
+            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);
+    }
+
+    /**
+     * Stop listening to changes for this AppWidget.
      */
     public void deleteAppWidgetId(int appWidgetId) {
         synchronized (mViews) {
@@ -185,6 +237,22 @@
     }
 
     /**
+     * Stop listening to changes for this AppWidget.
+     * @hide
+     */
+    public static void deleteAppWidgetIdForHost(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 +293,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 +305,7 @@
             throw new RuntimeException("system server dead?", e);
         }
         view.updateAppWidget(views);
+
         return view;
     }
 
@@ -245,7 +315,7 @@
      */
     protected AppWidgetHostView onCreateView(Context context, int appWidgetId,
             AppWidgetProviderInfo appWidget) {
-        return new AppWidgetHostView(context);
+        return new AppWidgetHostView(context, mOnClickHandler);
     }
 
     /**
@@ -255,7 +325,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 +344,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..c86826f 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -44,6 +44,7 @@
 import android.widget.BaseAdapter;
 import android.widget.FrameLayout;
 import android.widget.RemoteViews;
+import android.widget.RemoteViews.OnClickHandler;
 import android.widget.RemoteViewsAdapter.RemoteAdapterConnectionCallback;
 import android.widget.TextView;
 
@@ -83,7 +84,8 @@
     long mFadeStartTime = -1;
     Bitmap mOld;
     Paint mOldPaint = new Paint();
-    
+    private OnClickHandler mOnClickHandler;
+
     /**
      * Create a host view.  Uses default fade animations.
      */
@@ -92,9 +94,17 @@
     }
 
     /**
+     * @hide
+     */
+    public AppWidgetHostView(Context context, OnClickHandler handler) {
+        this(context, android.R.anim.fade_in, android.R.anim.fade_out);
+        mOnClickHandler = handler;
+    }
+
+    /**
      * Create a host view. Uses specified animations when pushing
      * {@link #updateAppWidget(RemoteViews)}.
-     * 
+     *
      * @param animationIn Resource ID of in animation to use
      * @param animationOut Resource ID of out animation to use
      */
@@ -109,6 +119,17 @@
     }
 
     /**
+     * Pass the given handler to RemoteViews when updating this widget. Unless this
+     * is done immediatly after construction, a call to {@link #updateAppWidget(RemoteViews)}
+     * should be made.
+     * @param handler
+     * @hide
+     */
+    public void setOnClickHandler(OnClickHandler handler) {
+        mOnClickHandler = handler;
+    }
+
+    /**
      * Set the AppWidget that will be displayed by this view. This method also adds default padding
      * to widgets, as described in {@link #getDefaultPaddingForWidget(Context, ComponentName, Rect)}
      * and can be overridden in order to add custom padding.
@@ -177,7 +198,7 @@
     public int getAppWidgetId() {
         return mAppWidgetId;
     }
-    
+
     public AppWidgetProviderInfo getAppWidgetInfo() {
         return mInfo;
     }
@@ -281,12 +302,13 @@
      * AppWidget provider. Will animate into these new views as needed
      */
     public void updateAppWidget(RemoteViews remoteViews) {
+
         if (LOGD) Log.d(TAG, "updateAppWidget called mOld=" + mOld);
 
         boolean recycled = false;
         View content = null;
         Exception exception = null;
-        
+
         // Capture the old view into a bitmap so we can do the crossfade.
         if (CROSSFADE) {
             if (mFadeStartTime < 0) {
@@ -305,7 +327,7 @@
                 }
             }
         }
-        
+
         if (remoteViews == null) {
             if (mViewMode == VIEW_MODE_DEFAULT) {
                 // We've already done this -- nothing to do.
@@ -324,7 +346,7 @@
             // layout matches, try recycling it
             if (content == null && layoutId == mLayoutId) {
                 try {
-                    remoteViews.reapply(mContext, mView);
+                    remoteViews.reapply(mContext, mView, mOnClickHandler);
                     content = mView;
                     recycled = true;
                     if (LOGD) Log.d(TAG, "was able to recycled existing layout");
@@ -332,11 +354,11 @@
                     exception = e;
                 }
             }
-            
+
             // Try normal RemoteView inflation
             if (content == null) {
                 try {
-                    content = remoteViews.apply(mContext, this);
+                    content = remoteViews.apply(mContext, this, mOnClickHandler);
                     if (LOGD) Log.d(TAG, "had to inflate new layout");
                 } catch (RuntimeException e) {
                     exception = e;
@@ -346,7 +368,7 @@
             mLayoutId = layoutId;
             mViewMode = VIEW_MODE_CONTENT;
         }
-        
+
         if (content == null) {
             if (mViewMode == VIEW_MODE_ERROR) {
                 // We've already done this -- nothing to do.
@@ -356,7 +378,7 @@
             content = getErrorView();
             mViewMode = VIEW_MODE_ERROR;
         }
-        
+
         if (!recycled) {
             prepareView(content);
             addView(content);
@@ -455,7 +477,7 @@
             return super.drawChild(canvas, child, drawingTime);
         }
     }
-    
+
     /**
      * Prepare the given view to be shown. This might include adjusting
      * {@link FrameLayout.LayoutParams} before inserting.
@@ -471,7 +493,7 @@
         requested.gravity = Gravity.CENTER;
         view.setLayoutParams(requested);
     }
-    
+
     /**
      * Inflate and return the default layout requested by AppWidget provider.
      */
@@ -481,7 +503,7 @@
         }
         View defaultView = null;
         Exception exception = null;
-        
+
         try {
             if (mInfo != null) {
                 Context theirContext = mContext.createPackageContext(
@@ -491,7 +513,17 @@
                         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) {
+                        layoutId = mInfo.initialKeyguardLayout;
+                    }
+                }
+                defaultView = inflater.inflate(layoutId, this, false);
             } else {
                 Log.w(TAG, "can't inflate defaultView because mInfo is missing");
             }
@@ -500,19 +532,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..6fb6dc4 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -150,26 +150,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 +216,28 @@
     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 which allows the picker to filter
+     * the list based on the {@link AppWidgetProviderInfo#widgetFeatures}.
+     * @hide
+     */
+    public static final String EXTRA_FEATURES_FILTER = "featuresFilter";
+
+    /**
+     * 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;
@@ -568,7 +598,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 +648,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..5ef3d39 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -44,6 +44,34 @@
     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;
+
+    /**
+     * Indicates that the widget supports no special features.
+     */
+    public static final int WIDGET_FEATURES_NONE = 0;
+
+    /**
+     * Indicates that the widget displays the current time. The host may use this as a hint to not
+     * display the time in other places.
+     */
+    public static final int WIDGET_FEATURES_CLOCK = 1;
+
+    /**
+     * Indicates that the widget is output only, ie. has nothing clickable. This may be enforced by
+     * the host. Presently, this flag is used by the keyguard to indicate that it can be placed
+     * in the first position.
+     */
+    public static final int WIDGET_FEATURES_STATUS = 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 +139,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 +202,27 @@
      */
     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;
+
+    /**
+     * A field which specifies any special features that this widget supports. See
+     * {@link #WIDGET_FEATURES_NONE}, {@link #WIDGET_FEATURES_CLOCK},
+     * {@link #WIDGET_FEATURES_STATUS}.
+     *
+     * <p>This field corresponds to the <code>widgetFeatures</code> attribute in
+     * the AppWidget meta-data file.
+     */
+    public int widgetFeatures;
+
     public AppWidgetProviderInfo() {
     }
 
@@ -180,6 +239,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 +248,8 @@
         this.previewImage = in.readInt();
         this.autoAdvanceViewId = in.readInt();
         this.resizeMode = in.readInt();
+        this.widgetCategory = in.readInt();
+        this.widgetFeatures = in.readInt();
     }
 
     public void writeToParcel(android.os.Parcel out, int flags) {
@@ -203,6 +265,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 +277,8 @@
         out.writeInt(this.previewImage);
         out.writeInt(this.autoAdvanceViewId);
         out.writeInt(this.resizeMode);
+        out.writeInt(this.widgetCategory);
+        out.writeInt(this.widgetFeatures);
     }
 
     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..6e2278d
--- 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,7 @@
  */
 public final class BluetoothA2dp implements BluetoothProfile {
     private static final String TAG = "BluetoothA2dp";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
 
     /**
      * Intent used to broadcast the change in connection state of the A2DP
@@ -102,37 +103,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 (DBG) 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 (DBG) 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.
      *
@@ -267,7 +321,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 +337,7 @@
         if (mService != null && isEnabled()
             && isValidDevice(device)) {
             if (priority != BluetoothProfile.PRIORITY_OFF &&
-                priority != BluetoothProfile.PRIORITY_ON) {
+                priority != BluetoothProfile.PRIORITY_ON){
               return false;
             }
             try {
@@ -347,67 +401,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 +421,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 +445,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..541b69f
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -45,7 +45,7 @@
  */
 public final class BluetoothHeadset implements BluetoothProfile {
     private static final String TAG = "BluetoothHeadset";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
 
     /**
      * Intent used to broadcast the change in connection state of the Headset
@@ -219,7 +219,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 (DBG) 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 (DBG) 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 +259,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 +280,27 @@
      * results once close() has been called. Multiple invocations of close()
      * are ok.
      */
-    /*package*/ synchronized void close() {
+    /*package*/ void close() {
         if (DBG) log("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);
+                } catch (Exception re) {
+                    Log.e(TAG,"",re);
+                }
+            }
         }
         mServiceListener = null;
     }
@@ -562,25 +619,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 +638,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,63 +655,6 @@
     }
 
     /**
-     * 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
      *
@@ -712,6 +674,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 (DBG) 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 +791,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..4a0bc7e 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,7 @@
  */
 public final class BluetoothHealth implements BluetoothProfile {
     private static final String TAG = "BluetoothHealth";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
 
     /**
      * Health Profile Source Role - the health device.
@@ -94,6 +97,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 (DBG) 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 (DBG) 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.
@@ -427,35 +461,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 (DBG) 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..bff966d
--- 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,7 @@
  */
 public final class BluetoothInputDevice implements BluetoothProfile {
     private static final String TAG = "BluetoothInputDevice";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
 
     /**
      * Intent used to broadcast the change in connection state of the Input
@@ -66,6 +69,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 +110,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 (DBG) 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 (DBG) 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 (DBG) 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 +288,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 +328,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;
@@ -205,7 +347,7 @@
         if (DBG) 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>();
@@ -222,7 +364,7 @@
         if (DBG) 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>();
@@ -237,10 +379,9 @@
      */
     public int getConnectionState(BluetoothDevice device) {
         if (DBG) log("getState(" + device + ")");
-        if (mService != null && isEnabled()
-            && isValidDevice(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 +408,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;
@@ -299,10 +439,9 @@
      */
     public int getPriority(BluetoothDevice device) {
         if (DBG) log("getPriority(" + device + ")");
-        if (mService != null && isEnabled()
-            && isValidDevice(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 +451,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 +481,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 (DBG) 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 (DBG) 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..cae7a73 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,7 @@
  */
 public final class BluetoothPan implements BluetoothProfile {
     private static final String TAG = "BluetoothPan";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
 
     /**
      * Intent used to broadcast the change in connection state of the Pan
@@ -76,15 +78,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 +117,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 (DBG) 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 (DBG) 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 +208,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 +249,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;
     }
 
@@ -222,15 +267,15 @@
      */
     public List<BluetoothDevice> getConnectedDevices() {
         if (DBG) log("getConnectedDevices()");
-        if (mService != null && isEnabled()) {
+        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>();
     }
 
@@ -239,15 +284,15 @@
      */
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
         if (DBG) log("getDevicesMatchingStates()");
-        if (mService != null && isEnabled()) {
+        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>();
     }
 
@@ -256,23 +301,23 @@
      */
     public int getConnectionState(BluetoothDevice device) {
         if (DBG) log("getState(" + device + ")");
-        if (mService != null && isEnabled()
+        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()));
         }
@@ -281,13 +326,32 @@
     public boolean isTetheringOn() {
         if (DBG) 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..7de2ef6
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -70,6 +70,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 +97,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 +109,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 (DBG) 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 (DBG) 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 +177,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;
     }
@@ -240,7 +299,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..1bc640f 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -1,32 +1,27 @@
 /*
- * 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.
+ * Copyright (C) 2012 Google Inc.
  */
 
 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 android.net.LocalSocket;
+import java.nio.ByteOrder;
+import java.nio.ByteBuffer;
 /**
  * A connected or connecting Bluetooth socket.
  *
@@ -89,31 +84,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 +138,52 @@
                 throw new IOException("Invalid RFCOMM channel: " + port);
             }
         }
-        if (uuid == null) {
-            mPort = port;
-            mSdp = null;
-        } else {
-            mSdp = new SdpHelper(device, uuid);
-            mPort = -1;
-        }
+        mUuid = uuid;
         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();
+        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 +209,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 +255,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)
+            {
+                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 +320,170 @@
      * 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) {
+                Log.d(TAG, "bindListen(), SocketState: " + mSocketState + ", mPfd: " + mPfd);
+                if(mSocketState != SocketState.INIT) return EBADFD;
+                if(mPfd == null) return -1;
+                FileDescriptor fd = mPfd.getFileDescriptor();
+                Log.d(TAG, "bindListen(), new LocalSocket ");
+                mSocket = new LocalSocket(fd);
+                Log.d(TAG, "bindListen(), new LocalSocket.getInputStream() ");
+                mSocketIS = mSocket.getInputStream();
+                mSocketOS = mSocket.getOutputStream();
+            }
+            Log.d(TAG, "bindListen(), readInt mSocketIS: " + mSocketIS);
+            int channel = readInt(mSocketIS);
+            synchronized(this) {
+                if(mSocketState == SocketState.INIT)
+                    mSocketState = SocketState.LISTENING;
+            }
+            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();
-        }
+        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();
-        }
+
+            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);
+            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();
-        }
+
+            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
+            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;
+                 Log.d(TAG, "close() this: " + this + ", channel: " + mPort + ", mSocketIS: " + mSocketIS +
+                        ", mSocketOS: " + mSocketOS + "mSocket: " + mSocket);
+                 if(mSocket != null) {
+                    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);
+        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);
+        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);
+        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..30406e9 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;
@@ -54,9 +62,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 +99,10 @@
      * Begin monitoring connectivity
      */
     public void startMonitoring(Context context, Handler target) {
+        Log.d(TAG, "startMonitoring: target: " + target);
         mContext = context;
         mCsHandler = target;
+        Log.d(TAG, "startMonitoring: mCsHandler: " + mCsHandler);
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
         if (adapter != null) {
             adapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.PAN);
@@ -124,6 +133,11 @@
         return true;
     }
 
+    @Override
+    public void captivePortalCheckComplete() {
+        // not implemented
+    }
+
     /**
      * Re-enable connectivity to a network after a {@link #teardown()}.
      */
@@ -259,38 +273,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() {
+        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;
+                Log.d(TAG, "startReverseTether mCsHandler: " + mCsHandler);
+                String DhcpResultName = "dhcp." + mIface + ".result";;
+                String result = "";
+                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);
+                    Log.d(TAG, "read " + DhcpResultName + ": " + result);
+                    if(result.equals("failed")) {
+                        Log.e(TAG, "startReverseTether, failed to start dhcp service");
+                        return;
+                    }
+                    if(result.equals("ok")) {
+                        Log.d(TAG, "startReverseTether, dhcp resut: " + result);
+                        if(readLinkProperty(mIface)) {
+
+                            mNetworkInfo.setIsAvailable(true);
+                            mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
+
+                            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.d(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..163e4e2
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothHeadsetPhone.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2012 Google Inc.
+ */
+
+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..e741da4
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothHealth.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 Google Inc.
+ */
+
+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..23e6d50
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothInputDevice.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 Google Inc.
+ */
+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..de8fe91
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothManager.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012 Google Inc.
+ */
+
+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..3e795ea
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothManagerCallback.aidl
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2012 Google Inc.
+ */
+
+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..b91bd7d
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothPan.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 Google Inc.
+ */
+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..cd1e882 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.myUserId());
+    }
+
+    /**
+     * 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..0f6488a 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.
@@ -294,7 +357,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 +375,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 +393,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 +407,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 +421,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 +435,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 +453,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 +470,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 +487,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 +503,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 +521,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 +534,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 +552,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 +606,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 +636,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 +705,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 +732,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 +741,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 +775,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 +826,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..161670f 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,11 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.UserHandle;
 import android.util.AttributeSet;
+import android.view.CompatibilityInfoHolder;
+import android.view.Display;
+import android.view.WindowManager;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -851,6 +856,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 +897,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.
      *
@@ -988,16 +1025,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 +1122,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 +1250,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 +1265,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 +1411,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 +1530,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 +1568,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 +1590,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 +1604,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 +2096,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 +2144,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 +2163,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 +2574,54 @@
             int flags) 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..6101f4e 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);
@@ -312,12 +332,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 +354,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 +393,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 +425,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 +449,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 +469,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
@@ -514,7 +587,23 @@
     }
 
     @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..e8507bc 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}
@@ -1286,6 +1287,22 @@
             = "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 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 +1345,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
@@ -1456,7 +1480,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 +1496,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 +1648,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 +2294,98 @@
             "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.
+     */
+    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.
+     */
+    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.
+     */
+    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 to 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.
+     * @hide
+     */
+    public static final String ACTION_USER_STARTED =
+            "android.intent.action.USER_STARTED";
+
+    /**
+     * 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.  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";
+
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Standard intent categories (see addCategory()).
@@ -2834,12 +2936,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/SyncManager.java b/core/java/android/content/SyncManager.java
index badcb03..6b5e6e2 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -52,7 +52,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;
@@ -173,7 +174,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,7 +195,7 @@
     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 */);
             }
@@ -206,16 +207,20 @@
     // Use this as a random offset to seed all periodic syncs
     private int mSyncRandomOffsetMillis;
 
+    private 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
+    private UserManager getUserManager() {
+        if (mUserManager == null) {
+            mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
         }
-        return null;
+        return mUserManager;
+    }
+
+    private List<UserInfo> getAllUsers() {
+        return getUserManager().getUsers();
     }
 
     private boolean containsAccountAndUser(AccountAndUser[] accounts, Account account, int userId) {
@@ -282,7 +287,7 @@
             // a chance to set their syncable state.
 
             boolean onlyThoseWithUnkownSyncableState = justBootedUp;
-            scheduleSync(null, UserId.USER_ALL, null, null, 0 /* no delay */,
+            scheduleSync(null, UserHandle.USER_ALL, null, null, 0 /* no delay */,
                     onlyThoseWithUnkownSyncableState);
         }
     }
@@ -366,7 +371,7 @@
         mSyncAdapters.setListener(new RegisteredServicesCacheListener<SyncAdapterType>() {
             public void onServiceChanged(SyncAdapterType type, 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 */);
                 }
             }
@@ -512,7 +517,7 @@
         }
 
         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
@@ -890,7 +895,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;
 
         // Clean up the storage engine database
@@ -975,7 +980,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 +989,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
@@ -2127,7 +2133,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;
@@ -2175,7 +2181,7 @@
                         }
                     }
                     // check if the userid matches
-                    if (userId != UserId.USER_ALL
+                    if (userId != UserHandle.USER_ALL
                             && userId != activeSyncContext.mSyncOperation.userId) {
                         continue;
                     }
@@ -2250,10 +2256,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) {
@@ -2466,7 +2474,7 @@
         }
 
         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 +2496,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 +2511,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/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index 7a9fc65..de97481 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;
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 6b16e74..0b320f0 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -172,6 +172,14 @@
      */
     public static final int FLAG_IMMERSIVE = 0x0400;
     /**
+     * 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 relevent for ActivityInfo structures that are describiner 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.
      * These include:
@@ -181,7 +189,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 +366,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 +403,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 +441,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..a0283d3 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;
     
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..eea3b9c
--- /dev/null
+++ b/core/java/android/content/pm/PackageCleanItem.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.content.pm;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/** @hide */
+public class PackageCleanItem {
+    public final String packageName;
+    public final boolean andCode;
+
+    public PackageCleanItem(String packageName, boolean andCode) {
+        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 packageName.equals(other.packageName) && andCode == other.andCode;
+            }
+        } catch (ClassCastException e) {
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = 17;
+        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.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) {
+        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/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 7e96ae6..fd488ae 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.
@@ -1109,6 +1151,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 +1493,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.
      *
@@ -1705,6 +1818,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> queryIntentActivitiesForUser(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 +1890,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
@@ -2166,8 +2322,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 +2383,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 +2433,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 +2502,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 +2609,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 +2620,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 +2704,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 +2871,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..0a22fca 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(
@@ -2166,6 +2189,21 @@
             a.info.configChanges = 0;
         }
 
+        if (receiver) {
+            if (sa.getBoolean(
+                    com.android.internal.R.styleable.AndroidManifestActivity_singleUser,
+                    false)) {
+                a.info.flags |= ServiceInfo.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;
+            }
+        }
+
         sa.recycle();
 
         if (receiver && (owner.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
@@ -2428,8 +2466,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 +2523,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 +2549,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 +2765,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 +2791,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 +3481,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 +3511,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 +3557,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 +3620,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 +3657,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 +3702,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 +3719,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..7642670 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -26,6 +26,7 @@
 import android.content.res.XmlResourceParser;
 import android.os.Environment;
 import android.os.Handler;
+import android.util.AtomicFile;
 import android.util.Log;
 import android.util.AttributeSet;
 import android.util.Xml;
@@ -44,7 +45,6 @@
 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;
@@ -331,12 +331,16 @@
                 notifyListener(v1, 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;
         }
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..a06aba9 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,32 @@
      */
     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 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 +97,14 @@
 
     public UserInfo(UserInfo orig) {
         name = orig.name;
+        iconPath = orig.iconPath;
         id = orig.id;
         flags = orig.flags;
+        serialNumber = orig.serialNumber;
+    }
+
+    public UserHandle getUserHandle() {
+        return new UserHandle(id);
     }
 
     @Override
@@ -84,7 +119,9 @@
     public void writeToParcel(Parcel dest, int parcelableFlags) {
         dest.writeInt(id);
         dest.writeString(name);
+        dest.writeString(iconPath);
         dest.writeInt(flags);
+        dest.writeInt(serialNumber);
     }
 
     public static final Parcelable.Creator<UserInfo> CREATOR
@@ -100,6 +137,8 @@
     private UserInfo(Parcel source) {
         id = source.readInt();
         name = source.readString();
+        iconPath = source.readString();
         flags = source.readInt();
+        serialNumber = source.readInt();
     }
 }
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..6454de0
--- /dev/null
+++ b/core/java/android/content/pm/VerificationParams.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.content.pm;
+
+import android.content.pm.ManifestDigest;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents verification parameters used to verify packages to be installed.
+ *
+ * @hide
+ */
+public class VerificationParams implements Parcelable {
+    /** What we print out first when toString() is called. */
+    private static final String TO_STRING_PREFIX = "VerificationParams{";
+
+    /** The location of the supplementary verification file. */
+    private final Uri mVerificationURI;
+
+    /** URI referencing where the package was downloaded from. */
+    private final Uri mOriginatingURI;
+
+    /** HTTP referrer URI associated with the originatingURI. */
+    private final Uri mReferrer;
+
+    /** 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 manifestDigest an object that holds the digest of the package
+     *            which can be used to verify ownership. May be {@code null}.
+     */
+    public VerificationParams(Uri verificationURI, Uri originatingURI, Uri referrer,
+            ManifestDigest manifestDigest) {
+        mVerificationURI = verificationURI;
+        mOriginatingURI = originatingURI;
+        mReferrer = referrer;
+        mManifestDigest = manifestDigest;
+        mInstallerUid = -1;
+    }
+
+    public Uri getVerificationURI() {
+        return mVerificationURI;
+    }
+
+    public Uri getOriginatingURI() {
+        return mOriginatingURI;
+    }
+
+    public Uri getReferrer() {
+        return mReferrer;
+    }
+
+    public ManifestDigest getManifestDigest() {
+        return mManifestDigest;
+    }
+
+    /** @return -1 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 && other.mVerificationURI != null) {
+            return false;
+        }
+        if (!mVerificationURI.equals(other.mVerificationURI)) {
+            return false;
+        }
+
+        if (mOriginatingURI == null && other.mOriginatingURI != null) {
+            return false;
+        }
+        if (!mOriginatingURI.equals(other.mOriginatingURI)) {
+            return false;
+        }
+
+        if (mReferrer == null && other.mReferrer != null) {
+            return false;
+        }
+        if (!mReferrer.equals(other.mReferrer)) {
+            return false;
+        }
+
+        if (mManifestDigest == null && other.mManifestDigest != null) {
+            return false;
+        }
+        if (mManifestDigest != null && !mManifestDigest.equals(other.mManifestDigest)) {
+            return false;
+        }
+
+        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 * (mManifestDigest==null?1:mManifestDigest.hashCode());
+        hash += 17 * 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(",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.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());
+        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..7164713 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -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,6 +164,10 @@
      * 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.
      */
@@ -369,26 +394,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 +436,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 +464,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 +489,6 @@
         mnc = o.mnc;
         if (o.locale != null) {
             locale = (Locale) o.locale.clone();
-            layoutDirection = o.layoutDirection;
         }
         userSetLocale = o.userSetLocale;
         touchscreen = o.touchscreen;
@@ -454,6 +503,7 @@
         screenWidthDp = o.screenWidthDp;
         screenHeightDp = o.screenHeightDp;
         smallestScreenWidthDp = o.smallestScreenWidthDp;
+        densityDpi = o.densityDpi;
         compatScreenWidthDp = o.compatScreenWidthDp;
         compatScreenHeightDp = o.compatScreenHeightDp;
         compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp;
@@ -465,20 +515,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 +556,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 +662,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 +703,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 +749,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 +784,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 +800,6 @@
         if (delta.compatSmallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
             compatSmallestScreenWidthDp = delta.compatSmallestScreenWidthDp;
         }
-        
         if (delta.seq != 0) {
             seq = delta.seq;
         }
@@ -754,6 +835,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 +852,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 +882,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 +904,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 +992,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 +1020,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 +1090,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 +1128,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 + LocaleUtil.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/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 2968fbb..7f3b6b9 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -469,13 +469,20 @@
      * {@link android.view.ViewGroup}'s layout_width and layout_height
      * attributes.  This is only here for performance reasons; applications
      * should use {@link #getDimensionPixelSize}.
-     * 
+     *
      * @param index Index of the attribute to retrieve.
      * @param name Textual name of attribute for error reporting.
      * 
      * @return Attribute dimension value multiplied by the appropriate 
      * metric and truncated to integer pixels.
+     *
+     * @throws RuntimeException
+     *             if this TypedArray does not contain an entry for <code>index</code>
+     *
+     * @deprecated Use {@link #getLayoutDimension(int, int)} instead.
+     *
      */
+    @Deprecated
     public int getLayoutDimension(int index, String name) {
         index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
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..7b3a8af 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -1146,6 +1146,30 @@
     public native final void setDisplayOrientation(int degrees);
 
     /**
+     * Enable or disable the default shutter sound when taking a picture.
+     *
+     * 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.
+     *
+     * Note that devices may not always allow control of the camera shutter
+     * sound. If the shutter sound cannot be controlled, this method will return
+     * false.
+     *
+     * @param enabled whether the camera should play the system shutter sound
+     *                when {@link #takePicture takePicture} is called.
+     * @return true if the shutter sound state was successfully changed. False
+     *         if the shutter sound cannot be controlled; in this case, the
+     *         application should not play its own shutter sound since the
+     *         system shutter sound will play when a picture is taken.
+     * @see #takePicture
+     * @see ShutterCallback
+     */
+    public native final boolean enableShutterSound(boolean enabled);
+
+    /**
      * Callback interface for zoom changes during a smooth zoom operation.
      *
      * @see #setZoomChangeListener(OnZoomChangeListener)
@@ -1308,8 +1332,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 +1812,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 +2822,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);
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..4347e75
--- /dev/null
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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;
+
+/**
+ * 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>();
+
+    /**
+     * 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 with the
+     * {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY} permission 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";
+
+    /** @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() {
+        int[] displayIds = mGlobal.getDisplayIds();
+        int expectedCount = displayIds.length;
+        Display[] displays = new Display[expectedCount];
+        synchronized (mLock) {
+            int actualCount = 0;
+            for (int i = 0; i < expectedCount; i++) {
+                Display display = getOrCreateDisplayLocked(displayIds[i], true /*assumeValid*/);
+                if (display != null) {
+                    displays[actualCount++] = display;
+                }
+            }
+            if (actualCount != expectedCount) {
+                Display[] oldDisplays = displays;
+                displays = new Display[actualCount];
+                System.arraycopy(oldDisplays, 0, displays, 0, actualCount);
+            }
+        }
+        return displays;
+    }
+
+    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.
+     *
+     * @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();
+    }
+
+    /**
+     * 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..14b5440
--- /dev/null
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.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.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 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..36a9a7f
--- /dev/null
+++ b/core/java/android/hardware/display/IDisplayManager.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.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);
+
+    // Requires CONFIGURE_WIFI_DISPLAY permission.
+    void scanWifiDisplays();
+
+    // Requires CONFIGURE_WIFI_DISPLAY permission.
+    void connectWifiDisplay(String address);
+
+    // Requires CONFIGURE_WIFI_DISPLAY permission.
+    void disconnectWifiDisplay();
+
+    // Requires CONFIGURE_WIFI_DISPLAY permission.
+    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..e51e97e
--- /dev/null
+++ b/core/java/android/hardware/display/WifiDisplay.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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;
+
+/**
+ * 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;
+
+    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();
+            return new WifiDisplay(deviceAddress, deviceName);
+        }
+
+        public WifiDisplay[] newArray(int size) {
+            return size == 0 ? EMPTY_ARRAY : new WifiDisplay[size];
+        }
+    };
+
+    public WifiDisplay(String deviceAddress, String deviceName) {
+        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;
+    }
+
+    /**
+     * 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;
+    }
+
+    @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);
+    }
+
+    @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);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    // For debugging purposes only.
+    @Override
+    public String toString() {
+        return mDeviceName + " (" + mDeviceAddress + ")";
+    }
+}
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..d5fe45d
--- /dev/null
+++ b/core/java/android/hardware/display/WifiDisplayStatus.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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 known displays.
+ * <p>
+ * This object is immutable.
+ * </p>
+ *
+ * @hide
+ */
+public final class WifiDisplayStatus implements Parcelable {
+    private final boolean mEnabled;
+    private final int mScanState;
+    private final int mActiveDisplayState;
+    private final WifiDisplay mActiveDisplay;
+    private final WifiDisplay[] mKnownDisplays;
+
+    public static final int SCAN_STATE_NOT_SCANNING = 0;
+    public static final int SCAN_STATE_SCANNING = 1;
+
+    public static final int DISPLAY_STATE_NOT_CONNECTED = 0;
+    public static final int DISPLAY_STATE_CONNECTING = 1;
+    public static final int DISPLAY_STATE_CONNECTED = 2;
+
+    public static final Creator<WifiDisplayStatus> CREATOR = new Creator<WifiDisplayStatus>() {
+        public WifiDisplayStatus createFromParcel(Parcel in) {
+            boolean enabled = (in.readInt() != 0);
+            int scanState = in.readInt();
+            int activeDisplayState= in.readInt();
+
+            WifiDisplay activeDisplay = null;
+            if (in.readInt() != 0) {
+                activeDisplay = WifiDisplay.CREATOR.createFromParcel(in);
+            }
+
+            WifiDisplay[] knownDisplays = WifiDisplay.CREATOR.newArray(in.readInt());
+            for (int i = 0; i < knownDisplays.length; i++) {
+                knownDisplays[i] = WifiDisplay.CREATOR.createFromParcel(in);
+            }
+
+            return new WifiDisplayStatus(enabled, scanState, activeDisplayState,
+                    activeDisplay, knownDisplays);
+        }
+
+        public WifiDisplayStatus[] newArray(int size) {
+            return new WifiDisplayStatus[size];
+        }
+    };
+
+    public WifiDisplayStatus() {
+        this(false, SCAN_STATE_NOT_SCANNING, DISPLAY_STATE_NOT_CONNECTED,
+                null, WifiDisplay.EMPTY_ARRAY);
+    }
+
+    public WifiDisplayStatus(boolean enabled, int scanState, int activeDisplayState,
+            WifiDisplay activeDisplay, WifiDisplay[] knownDisplays) {
+        if (knownDisplays == null) {
+            throw new IllegalArgumentException("knownDisplays must not be null");
+        }
+
+        mEnabled = enabled;
+        mScanState = scanState;
+        mActiveDisplayState = activeDisplayState;
+        mActiveDisplay = activeDisplay;
+        mKnownDisplays = knownDisplays;
+    }
+
+    /**
+     * Returns true if the Wifi display feature is enabled and available for use.
+     * <p>
+     * The value of this property reflects whether Wifi and Wifi P2P functions
+     * are enabled.  Enablement is not directly controllable by the user at this
+     * time, except indirectly such as by turning off Wifi altogether.
+     * </p>
+     */
+    public boolean isEnabled() {
+        return mEnabled;
+    }
+
+    /**
+     * 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 known Wifi displays, never null.
+     */
+    public WifiDisplay[] getKnownDisplays() {
+        return mKnownDisplays;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mEnabled ? 1 : 0);
+        dest.writeInt(mScanState);
+        dest.writeInt(mActiveDisplayState);
+
+        if (mActiveDisplay != null) {
+            dest.writeInt(1);
+            mActiveDisplay.writeToParcel(dest, flags);
+        } else {
+            dest.writeInt(0);
+        }
+
+        dest.writeInt(mKnownDisplays.length);
+        for (WifiDisplay display : mKnownDisplays) {
+            display.writeToParcel(dest, flags);
+        }
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    // For debugging purposes only.
+    @Override
+    public String toString() {
+        return "WifiDisplayStatus{enabled=" + mEnabled
+                + ", scanState=" + mScanState
+                + ", activeDisplayState=" + mActiveDisplayState
+                + ", activeDisplay=" + mActiveDisplay
+                + ", knownDisplays=" + Arrays.toString(mKnownDisplays)
+                + "}";
+    }
+}
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index 9bab797..98bd4f5 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -87,4 +87,12 @@
 
     /* Sets the file path for USB mass storage backing file. */
     void setMassStorageBackingFile(String path);
+
+    /* Allow USB debugging from the attached host. If alwaysAllow is true, add the
+     * the public key to list of host keys that the user has approved.
+     */
+    void allowUsbDebugging(boolean alwaysAllow, String publicKey);
+
+    /* Deny USB debugging from the attached host */
+    void denyUsbDebugging();
 }
diff --git a/core/java/android/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..cf3b802 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);
     }
@@ -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..aa392d0
--- /dev/null
+++ b/core/java/android/net/CaptivePortalTracker.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 android.net;
+
+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.database.ContentObserver;
+import android.net.ConnectivityManager;
+import android.net.IConnectivityManager;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.util.Log;
+
+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 java.util.concurrent.atomic.AtomicBoolean;
+
+import com.android.internal.R;
+
+/**
+ * This class allows captive portal detection
+ * @hide
+ */
+public class CaptivePortalTracker {
+    private static final boolean DBG = true;
+    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 InternalHandler mHandler;
+    private IConnectivityManager mConnService;
+    private Context mContext;
+    private NetworkInfo mNetworkInfo;
+    private boolean mIsCaptivePortal = false;
+
+    private static final int DETECT_PORTAL = 0;
+    private static final int HANDLE_CONNECT = 1;
+
+    /**
+     * Activity Action: Switch to the captive portal network
+     * <p>Input: Nothing.
+     * <p>Output: Nothing.
+     */
+    public static final String ACTION_SWITCH_TO_CAPTIVE_PORTAL
+            = "android.net.SWITCH_TO_CAPTIVE_PORTAL";
+
+    private CaptivePortalTracker(Context context, NetworkInfo info, IConnectivityManager cs) {
+        mContext = context;
+        mNetworkInfo = info;
+        mConnService = cs;
+
+        HandlerThread handlerThread = new HandlerThread("CaptivePortalThread");
+        handlerThread.start();
+        mHandler = new InternalHandler(handlerThread.getLooper());
+        mHandler.obtainMessage(DETECT_PORTAL).sendToTarget();
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(ACTION_SWITCH_TO_CAPTIVE_PORTAL);
+        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+
+        mContext.registerReceiver(mReceiver, filter);
+
+        mServer = Settings.Secure.getString(mContext.getContentResolver(),
+                Settings.Secure.CAPTIVE_PORTAL_SERVER);
+        if (mServer == null) mServer = DEFAULT_SERVER;
+
+        mIsCaptivePortalCheckEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.CAPTIVE_PORTAL_DETECTION_ENABLED, 1) == 1;
+    }
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (action.equals(ACTION_SWITCH_TO_CAPTIVE_PORTAL)) {
+                notifyPortalCheckComplete();
+            } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
+                NetworkInfo info = intent.getParcelableExtra(
+                        ConnectivityManager.EXTRA_NETWORK_INFO);
+                mHandler.obtainMessage(HANDLE_CONNECT, info).sendToTarget();
+            }
+        }
+    };
+
+    public static CaptivePortalTracker detect(Context context, NetworkInfo info,
+            IConnectivityManager cs) {
+        CaptivePortalTracker captivePortal = new CaptivePortalTracker(context, info, cs);
+        return captivePortal;
+    }
+
+    private class InternalHandler extends Handler {
+        public InternalHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case DETECT_PORTAL:
+                    InetAddress server = lookupHost(mServer);
+                    if (server != null) {
+                        requestRouteToHost(server);
+                        if (isCaptivePortal(server)) {
+                            if (DBG) log("Captive portal " + mNetworkInfo);
+                            setNotificationVisible(true);
+                            mIsCaptivePortal = true;
+                            break;
+                        }
+                    }
+                    notifyPortalCheckComplete();
+                    quit();
+                    break;
+                case HANDLE_CONNECT:
+                    NetworkInfo info = (NetworkInfo) msg.obj;
+                    if (info.getType() != mNetworkInfo.getType()) break;
+
+                    if (info.getState() == NetworkInfo.State.CONNECTED ||
+                            info.getState() == NetworkInfo.State.DISCONNECTED) {
+                        setNotificationVisible(false);
+                    }
+
+                    /* Connected to a captive portal */
+                    if (info.getState() == NetworkInfo.State.CONNECTED &&
+                            mIsCaptivePortal) {
+                        launchBrowser();
+                        quit();
+                    }
+                    break;
+                default:
+                    loge("Unhandled message " + msg);
+                    break;
+            }
+        }
+
+        private void quit() {
+            mIsCaptivePortal = false;
+            getLooper().quit();
+            mContext.unregisterReceiver(mReceiver);
+        }
+    }
+
+    private void launchBrowser() {
+        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(mUrl));
+        intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(intent);
+    }
+
+    private void notifyPortalCheckComplete() {
+        try {
+            mConnService.captivePortalCheckComplete(mNetworkInfo);
+        } catch(RemoteException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void requestRouteToHost(InetAddress server) {
+        try {
+            mConnService.requestRouteToHostAddress(mNetworkInfo.getType(),
+                    server.getAddress());
+        } catch (RemoteException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 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";
+        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 = r.getString(R.string.wifi_available_sign_in, 0);
+            CharSequence details = r.getString(R.string.wifi_available_sign_in_detailed,
+                    mNetworkInfo.getExtraInfo());
+
+            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.getBroadcast(mContext, 0,
+                    new Intent(CaptivePortalTracker.ACTION_SWITCH_TO_CAPTIVE_PORTAL), 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..a570473 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>
@@ -880,4 +912,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/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/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/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..f66075d 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/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/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index c62715b..7b16f4d 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -115,4 +115,6 @@
     public static final int BATTERY_PLUGGED_AC = 1;
     /** Power source is a USB port. */
     public static final int BATTERY_PLUGGED_USB = 2;
+    /** Power source is wireless. */
+    public static final int BATTERY_PLUGGED_WIRELESS = 4;
 }
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 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..8860e0a 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,20 @@
          * </ul>
          */
         public static final int JELLY_BEAN = 16;
+
+        /**
+         * 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>
+         * </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..c08bfeb 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 =
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 679cf1a..1607b96 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,128 @@
 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_TARGET = "EMULATED_STORAGE_TARGET";
+
+    /** {@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;
+
+        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);
+
+            if (!TextUtils.isEmpty(rawEmulatedStorageTarget)) {
+                // Device has emulated storage; external storage paths should have
+                // userId burned into them.
+                final File emulatedBase = new File(rawEmulatedStorageTarget);
+
+                // /storage/emulated/0
+                mExternalStorage = buildPath(emulatedBase, Integer.toString(userId));
+                // /storage/emulated/obb
+                mExternalStorageAndroidObb = buildPath(emulatedBase, "obb");
+
+            } 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);
+                // /storage/sdcard0/Android/obb
+                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 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");
+        }
     }
 
     /**
@@ -104,6 +202,17 @@
     }
 
     /**
+     * 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));
+    }
+
+    /**
      * Returns whether the Encrypted File System feature is enabled on the device or not.
      * @return <code>true</code> if Encrypted File System feature is enabled, <code>false</code>
      * if disabled.
@@ -126,20 +235,7 @@
     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.
@@ -187,7 +283,13 @@
      * @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));
     }
 
     /**
@@ -307,7 +409,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 +418,8 @@
      * @hide
      */
     public static File getExternalStorageAndroidDataDir() {
-        return EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY;
+        throwIfSystem();
+        return sCurrentUser.getExternalStorageAndroidDataDir();
     }
     
     /**
@@ -323,7 +427,8 @@
      * @hide
      */
     public static File getExternalStorageAppDataDirectory(String packageName) {
-        return new File(EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY, packageName);
+        throwIfSystem();
+        return sCurrentUser.getExternalStorageAppDataDirectory(packageName);
     }
     
     /**
@@ -331,7 +436,8 @@
      * @hide
      */
     public static File getExternalStorageAppMediaDirectory(String packageName) {
-        return new File(EXTERNAL_STORAGE_ANDROID_MEDIA_DIRECTORY, packageName);
+        throwIfSystem();
+        return sCurrentUser.getExternalStorageAppMediaDirectory(packageName);
     }
     
     /**
@@ -339,7 +445,8 @@
      * @hide
      */
     public static File getExternalStorageAppObbDirectory(String packageName) {
-        return new File(EXTERNAL_STORAGE_ANDROID_OBB_DIRECTORY, packageName);
+        throwIfSystem();
+        return sCurrentUser.getExternalStorageAppObbDirectory(packageName);
     }
     
     /**
@@ -347,17 +454,17 @@
      * @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);
     }
     
     /**
@@ -430,9 +537,10 @@
         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 +554,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 +572,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/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..7aee644 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -23,27 +23,33 @@
 
 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);
+
     boolean isScreenOn();
     void reboot(String reason);
     void crash(String message);
 
-    // sets the brightness of the backlights (screen, keyboard, button) 0-255
-    void setBacklightBrightness(int brightness);
+    void clearUserActivityTimeout(long now, long timeout);
+    void setPokeLock(int pokey, IBinder lock, String tag);
+    void setStayOnSetting(int val);
+    void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs);
+    void preventScreenOn(boolean prevent);
+
+    // 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..0798913
--- /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();
+    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
index 52df1f8..519315c 100644
--- a/core/java/android/os/LocalPowerManager.java
+++ b/core/java/android/os/LocalPowerManager.java
@@ -18,31 +18,11 @@
 
 /** @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;
+    // FIXME: Replace poke locks with something else.
 
     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..cc2c002 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,11 +42,11 @@
  *   ..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>
  *
+ * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
  *     <thead>
  *     <tr><th>Flag Value</th> 
  *     <th>CPU</th> <th>Screen</th> <th>Keyboard</th></tr>
@@ -67,15 +70,16 @@
  *     </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>
  *
+ * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
  *     <thead>
  *     <tr><th>Flag Value</th> <th>Description</th></tr>
  *     </thead>
@@ -96,81 +100,127 @@
  *     </tr>
  *     </tbody>
  * </table>
- * 
+ * </p><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>
+     * 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 +228,178 @@
     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);
+    }
+
+    /**
+     * 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 +407,202 @@
             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 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 user activity 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 user activity 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) {
+        }
+    }
+
+    /**
+     * 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(reason);
+        } 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 +613,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..a54c25b 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 #elapsedRealtimeNano}
+ *     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 elapsedRealtimeNano();
+
     /**
      * 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..59d0f7a 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -39,11 +39,12 @@
     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";
diff --git a/core/java/android/os/UEventObserver.java b/core/java/android/os/UEventObserver.java
index b924e84..d33382b 100644
--- a/core/java/android/os/UEventObserver.java
+++ b/core/java/android/os/UEventObserver.java
@@ -37,14 +37,79 @@
  * @hide
 */
 public abstract class UEventObserver {
-    private static final String TAG = UEventObserver.class.getSimpleName();
+    private static UEventThread sThread;
+
+    private static native void native_setup();
+    private static native int next_event(byte[] buffer);
+
+    public UEventObserver() {
+    }
+
+    protected void finalize() throws Throwable {
+        try {
+            stopObserving();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    private static UEventThread getThread() {
+        synchronized (UEventObserver.class) {
+            if (sThread == null) {
+                sThread = new UEventThread();
+                sThread.start();
+            }
+            return sThread;
+        }
+    }
+
+    private static UEventThread peekThread() {
+        synchronized (UEventObserver.class) {
+            return sThread;
+        }
+    }
+
+    /**
+     * Begin observation of UEvent's.<p>
+     * This method will cause the UEvent thread to start if this is the first
+     * invocation of startObserving in this process.<p>
+     * Once called, the UEvent thread will call onUEvent() when an incoming
+     * UEvent matches the specified string.<p>
+     * This method can be called multiple times to register multiple matches.
+     * Only one call to stopObserving is required even with multiple registered
+     * matches.
+     * @param match A substring of the UEvent to match. Use "" to match all
+     *              UEvent's
+     */
+    public final void startObserving(String match) {
+        final UEventThread t = getThread();
+        t.addObserver(match, this);
+    }
+
+    /**
+     * End observation of UEvent's.<p>
+     * This process's UEvent thread will never call onUEvent() on this
+     * UEventObserver after this call. Repeated calls have no effect.
+     */
+    public final void stopObserving() {
+        final UEventThread t = getThread();
+        if (t != null) {
+            t.removeObserver(this);
+        }
+    }
+
+    /**
+     * Subclasses of UEventObserver should override this method to handle
+     * UEvents.
+     */
+    public abstract void onUEvent(UEvent event);
 
     /**
      * Representation of a UEvent.
      */
-    static public class UEvent {
+    public static final class UEvent {
         // collection of key=value pairs parsed from the uevent message
-        public HashMap<String,String> mMap = new HashMap<String,String>();
+        private final HashMap<String,String> mMap = new HashMap<String,String>();
 
         public UEvent(String message) {
             int offset = 0;
@@ -79,20 +144,20 @@
         }
     }
 
-    private static UEventThread sThread;
-    private static boolean sThreadStarted = false;
-
-    private static class UEventThread extends Thread {
+    private static final class UEventThread extends Thread {
         /** Many to many mapping of string match to observer.
          *  Multimap would be better, but not available in android, so use
          *  an ArrayList where even elements are the String match and odd
          *  elements the corresponding UEventObserver observer */
-        private ArrayList<Object> mObservers = new ArrayList<Object>();
-        
-        UEventThread() {
+        private final ArrayList<Object> mKeysAndObservers = new ArrayList<Object>();
+
+        private final ArrayList<UEventObserver> mTempObserversToSignal =
+                new ArrayList<UEventObserver>();
+
+        public UEventThread() {
             super("UEventObserver");
         }
-        
+
         public void run() {
             native_setup();
 
@@ -101,91 +166,54 @@
             while (true) {
                 len = next_event(buffer);
                 if (len > 0) {
-                    String bufferStr = new String(buffer, 0, len);  // easier to search a String
-                    synchronized (mObservers) {
-                        for (int i = 0; i < mObservers.size(); i += 2) {
-                            if (bufferStr.indexOf((String)mObservers.get(i)) != -1) {
-                                ((UEventObserver)mObservers.get(i+1))
-                                        .onUEvent(new UEvent(bufferStr));
-                            }
-                        }
-                    }
+                    sendEvent(new String(buffer, 0, len));
                 }
             }
         }
-        public void addObserver(String match, UEventObserver observer) {
-            synchronized(mObservers) {
-                mObservers.add(match);
-                mObservers.add(observer);
+
+        private void sendEvent(String message) {
+            synchronized (mKeysAndObservers) {
+                final int N = mKeysAndObservers.size();
+                for (int i = 0; i < N; i += 2) {
+                    final String key = (String)mKeysAndObservers.get(i);
+                    if (message.indexOf(key) != -1) {
+                        final UEventObserver observer =
+                                (UEventObserver)mKeysAndObservers.get(i + 1);
+                        mTempObserversToSignal.add(observer);
+                    }
+                }
+            }
+
+            if (!mTempObserversToSignal.isEmpty()) {
+                final UEvent event = new UEvent(message);
+                final int N = mTempObserversToSignal.size();
+                for (int i = 0; i < N; i++) {
+                    final UEventObserver observer = mTempObserversToSignal.get(i);
+                    observer.onUEvent(event);
+                }
+                mTempObserversToSignal.clear();
             }
         }
+
+        public void addObserver(String match, UEventObserver observer) {
+            synchronized (mKeysAndObservers) {
+                mKeysAndObservers.add(match);
+                mKeysAndObservers.add(observer);
+            }
+        }
+
         /** Removes every key/value pair where value=observer from mObservers */
         public void removeObserver(UEventObserver observer) {
-            synchronized(mObservers) {
-                boolean found = true;
-                while (found) {
-                    found = false;
-                    for (int i = 0; i < mObservers.size(); i += 2) {
-                        if (mObservers.get(i+1) == observer) {
-                            mObservers.remove(i+1);
-                            mObservers.remove(i);
-                            found = true;
-                            break;
-                        }
+            synchronized (mKeysAndObservers) {
+                for (int i = 0; i < mKeysAndObservers.size(); ) {
+                    if (mKeysAndObservers.get(i + 1) == observer) {
+                        mKeysAndObservers.remove(i + 1);
+                        mKeysAndObservers.remove(i);
+                    } else {
+                        i += 2;
                     }
                 }
             }
         }
     }
-
-    private static native void native_setup();
-    private static native int next_event(byte[] buffer);
-
-    private static final synchronized void ensureThreadStarted() {
-        if (sThreadStarted == false) {
-            sThread = new UEventThread();
-            sThread.start();
-            sThreadStarted = true;
-        }
-    }
-
-    /**
-     * Begin observation of UEvent's.<p>
-     * This method will cause the UEvent thread to start if this is the first
-     * invocation of startObserving in this process.<p>
-     * Once called, the UEvent thread will call onUEvent() when an incoming
-     * UEvent matches the specified string.<p>
-     * This method can be called multiple times to register multiple matches.
-     * Only one call to stopObserving is required even with multiple registered
-     * matches.
-     * @param match A substring of the UEvent to match. Use "" to match all
-     *              UEvent's
-     */
-    public final synchronized void startObserving(String match) {
-        ensureThreadStarted();
-        sThread.addObserver(match, this);
-    }
-
-    /**
-     * End observation of UEvent's.<p>
-     * This process's UEvent thread will never call onUEvent() on this
-     * UEventObserver after this call. Repeated calls have no effect.
-     */
-    public final synchronized void stopObserving() {
-        sThread.removeObserver(this);
-    }
-
-    /**
-     * Subclasses of UEventObserver should override this method to handle
-     * UEvents.
-     */
-    public abstract void onUEvent(UEvent event);
-
-    protected void finalize() throws Throwable {
-        try {
-            stopObserving();
-        } finally {
-            super.finalize();
-        }
-    }
 }
diff --git a/core/java/android/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..392aff7
--- /dev/null
+++ b/core/java/android/os/UserManager.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.content.Context;
+import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
+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 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 "";
+        }
+    }
+
+    /**
+     * 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;
+        }
+    }
+
+    /**
+     * 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;
+        }
+    }
+
+    /**
+     * 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();
+        } 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 int getMaxSupportedUsers() {
+        return mContext.getResources().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..0b16316 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -677,15 +677,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();
@@ -1119,9 +1119,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: {
@@ -1358,7 +1358,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..54c8709d 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;
@@ -285,6 +287,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.
@@ -594,4 +601,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/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/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..54a2273 100755
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -345,10 +345,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();
@@ -7900,6 +7900,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..3c2d164 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -120,7 +120,7 @@
      */
     public static final String INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH =
             "android.media.action.MEDIA_PLAY_FROM_SEARCH";
-    
+
     /**
      * The name of the Intent-extra used to define the artist
      */
@@ -173,6 +173,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";
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 74c0a97..68ce72f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -41,7 +41,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.speech.tts.TextToSpeech;
 import android.text.TextUtils;
 import android.util.AndroidException;
@@ -621,6 +621,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 +659,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 +712,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 +731,79 @@
                     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 boolean putString(ContentResolver cr, String name, String value) {
+            return putStringForUser(cr, name, value, UserHandle.myUserId());
+        }
+
+        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 (userHandle != UserHandle.myUserId()) {
+                        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;
                     }
@@ -775,6 +840,10 @@
                 if (c != null) c.close();
             }
         }
+
+        public String getString(ContentResolver cr, String name) {
+            return getStringForUser(cr, name, UserHandle.myUserId());
+        }
     }
 
     /**
@@ -791,13 +860,8 @@
         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 +872,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,6 +890,47 @@
             MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS);
         }
 
+        private static final HashSet<String> MOVED_TO_GLOBAL;
+        static {
+            MOVED_TO_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_GLOBAL.add(Global.ADB_ENABLED);
+            MOVED_TO_GLOBAL.add(Global.BLUETOOTH_ON);
+            MOVED_TO_GLOBAL.add(Global.DATA_ROAMING);
+            MOVED_TO_GLOBAL.add(Global.DEVICE_PROVISIONED);
+            MOVED_TO_GLOBAL.add(Global.INSTALL_NON_MARKET_APPS);
+            MOVED_TO_GLOBAL.add(Global.USB_MASS_STORAGE_ENABLED);
+
+            // 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);
+        }
+
+        private static void lazyInitCache() {
+            if (sNameValueCache == null) {
+                sNameValueCache = new NameValueCache(
+                        SYS_PROP_SETTING_VERSION + '_' + UserHandle.myUserId(),
+                        CONTENT_URI,
+                        CALL_METHOD_GET_SYSTEM,
+                        CALL_METHOD_PUT_SYSTEM);
+            }
+        }
+
         /**
          * Look up a name in the database.
          * @param resolver to access the database with
@@ -834,16 +938,24 @@
          * @return the corresponding value, or null if not present
          */
         public synchronized static String getString(ContentResolver resolver, String name) {
+            return getStringForUser(resolver, name, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public synchronized 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)) {
+                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);
+            lazyInitCache();
+            return sNameValueCache.getStringForUser(resolver, name, userHandle);
         }
 
         /**
@@ -854,12 +966,24 @@
          * @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)) {
+                Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
+                        + " to android.provider.Settings.Global, value is unchanged.");
+                return false;
+            }
+            lazyInitCache();
+            return sNameValueCache.putStringForUser(resolver, name, value, userHandle);
         }
 
         /**
@@ -874,6 +998,11 @@
                     + " to android.provider.Settings.Secure, returning Secure URI.");
                 return Secure.getUriFor(Secure.CONTENT_URI, name);
             }
+            if (MOVED_TO_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 +1021,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 +1054,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 +1082,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 +1106,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 +1141,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 +1169,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 +1193,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 +1227,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 +1258,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 +1276,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 +1306,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,12 +1320,35 @@
             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);
+            /* intentionally empty */
+        }
+
+        /**
+         * @hide
+         * @deprecated - Do not use
+         */
+        @Deprecated
+        public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean flag,
+                int userHandle) {
+            putIntForUser(cr, SHOW_GTALK_SERVICE_STATUS, flag ? 1 : 0, userHandle);
         }
 
         /**
@@ -1141,16 +1358,10 @@
             Uri.parse("content://" + AUTHORITY + "/system");
 
         /**
-         * 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,80 +1406,81 @@
         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
         /**
@@ -1381,7 +1593,9 @@
 
         /**
          * 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";
 
         /**
@@ -1670,16 +1884,18 @@
         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
@@ -1880,16 +2096,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 +2124,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?
@@ -2063,11 +2297,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,22 +2310,22 @@
         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
@@ -2100,10 +2334,10 @@
         public static final String HTTP_PROXY = Secure.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 +2353,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 +2387,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 +2498,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
@@ -2307,11 +2541,112 @@
 
         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_NUM_ARP_PINGS);
+            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.WIFI_WATCHDOG_RSSI_FETCH_INTERVAL_MS);
+            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);
+        }
+
+        private static void lazyInitCache() {
+            if (sNameValueCache == null) {
+                sNameValueCache = new NameValueCache(
+                        SYS_PROP_SETTING_VERSION + '_' + UserHandle.myUserId(),
+                        CONTENT_URI,
+                        CALL_METHOD_GET_SECURE,
+                        CALL_METHOD_PUT_SECURE);
+            }
         }
 
         /**
@@ -2321,9 +2656,16 @@
          * @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);
+            return getStringForUser(resolver, name, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public synchronized 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) {
@@ -2334,13 +2676,14 @@
             if (sLockSettings != null && !sIsSystemProcess
                     && MOVED_TO_LOCK_SETTINGS.contains(name)) {
                 try {
-                    return sLockSettings.getString(name, "0", UserId.getCallingUserId());
+                    return sLockSettings.getString(name, "0", userHandle);
                 } catch (RemoteException re) {
                     // Fall through
                 }
             }
 
-            return sNameValueCache.getString(resolver, name);
+            lazyInitCache();
+            return sNameValueCache.getStringForUser(resolver, name, userHandle);
         }
 
         /**
@@ -2350,9 +2693,20 @@
          * @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);
+            }
+            lazyInitCache();
+            return sNameValueCache.putStringForUser(resolver, name, value, userHandle);
         }
 
         /**
@@ -2362,6 +2716,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 +2739,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 +2772,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 +2800,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 +2824,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 +2859,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 +2887,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 +2911,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 +2945,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,7 +2976,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);
         }
 
         /**
@@ -2580,14 +2992,25 @@
             Uri.parse("content://" + AUTHORITY + "/secure");
 
         /**
-         * Whether user has enabled development settings.
+         * @deprecated Use {@link android.provider.Settings.Global#DEVELOPMENT_SETTINGS_ENABLED}
+         * instead
          */
-        public static final String DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled";
+        @Deprecated
+        public static final String DEVELOPMENT_SETTINGS_ENABLED =
+                Global.DEVELOPMENT_SETTINGS_ENABLED;
 
         /**
-         * Whether ADB is enabled.
+         * When the user has enable the option to have a "bug report" command
+         * in the power menu.
+         * @hide
          */
-        public static final String ADB_ENABLED = "adb_enabled";
+        public static final String BUGREPORT_IN_POWER_MENU = "bugreport_in_power_menu";
+
+        /**
+         * @deprecated Use {@link android.provider.Settings.Global#ADB_ENABLED} instead
+         */
+        @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,10 +3029,10 @@
         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.
@@ -2636,9 +3059,9 @@
         }
 
         /**
-         * Whether or not data roaming is enabled. (0 = false, 1 = true)
+         * @deprecated Use {@link android.provider.Settings.Global#DATA_ROAMING} instead
          */
-        public static final String DATA_ROAMING = "data_roaming";
+        public static final String DATA_ROAMING = Global.DATA_ROAMING;
 
         /**
          * Setting to record the input method used by default, holding the ID
@@ -2668,9 +3091,10 @@
                 "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;
 
         /**
          * List of input methods that are currently enabled.  This is a string
@@ -2729,13 +3153,10 @@
         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.
-         *
-         * 1 = allow installing from other sources
-         * 0 = only allow installing from Google Play
+         * @deprecated Use {@link android.provider.Settings.Global#INSTALL_NON_MARKET_APPS} instead
          */
-        public static final String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
+        @Deprecated
+        public static final String INSTALL_NON_MARKET_APPS = Global.INSTALL_NON_MARKET_APPS;
 
         /**
          * Comma-separated list of location providers that activities may access.
@@ -2780,6 +3201,20 @@
         public static final String LOCK_SCREEN_OWNER_INFO = "lock_screen_owner_info";
 
         /**
+         * Id of the time appwidget on the lockscreen, or -1 if none
+         * @hide
+         */
+        public static final String LOCK_SCREEN_CLOCK_APPWIDGET_ID =
+            "lock_screen_clock_appwidget_id";
+
+        /**
+         * Id of the user-selected appwidget on the lockscreen, or -1 if none
+         * @hide
+         */
+        public static final String LOCK_SCREEN_USER_SELECTED_APPWIDGET_ID =
+            "lock_screen_user_selected_appwidget_id";
+
+        /**
          * This preference enables showing the owner info on LockScren.
          * @hide
          */
@@ -2787,17 +3222,25 @@
             "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.
+         * @deprecated Use {@link android.provider.Settings.Global#DISPLAY_SIZE_FORCED} instead
          * @hide
          */
-        public static final String DISPLAY_SIZE_FORCED = "display_size_forced";
+        @Deprecated
+        public static final String DISPLAY_SIZE_FORCED = Global.DISPLAY_SIZE_FORCED;
 
         /**
-         * Whether assisted GPS should be enabled or not.
+         * @deprecated Use {@link android.provider.Settings.Global#DISPLAY_DENSITY_FORCED} instead
          * @hide
          */
-        public static final String ASSISTED_GPS_ENABLED = "assisted_gps_enabled";
+        @Deprecated
+        public static final String DISPLAY_DENSITY_FORCED = Global.DISPLAY_DENSITY_FORCED;
+
+        /**
+         * @deprecated Use {@link android.provider.Settings.Global#ASSISTED_GPS_ENABLED} instead
+         * @hide
+         */
+        @Deprecated
+        public static final String ASSISTED_GPS_ENABLED = Global.ASSISTED_GPS_ENABLED;
 
         /**
          * The Logging ID (a unique 64-bit value) as a hex string.
@@ -2809,34 +3252,48 @@
         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";
+        @Deprecated
+        public static final String NETWORK_PREFERENCE = Global.NETWORK_PREFERENCE;
 
         /**
-         * Used to disable Tethering on a device - defaults to true
+         * @deprecated Use {@link android.provider.Settings.Global#TETHER_SUPPORTED} instead
          * @hide
          */
-        public static final String TETHER_SUPPORTED = "tether_supported";
+        @Deprecated
+        public static final String TETHER_SUPPORTED = Global.TETHER_SUPPORTED;
 
         /**
-         * Used to require DUN APN on the device or not - defaults to a build config value
-         * which defaults to false
+         * @deprecated Use {@link android.provider.Settings.Global#TETHER_DUN_REQUIRED} instead
          * @hide
          */
-        public static final String TETHER_DUN_REQUIRED = "tether_dun_required";
+        @Deprecated
+        public static final String TETHER_DUN_REQUIRED = Global.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"
+         * @deprecated Use {@link android.provider.Settings.Global#TETHER_DUN_REQUIRED} instead
          * @hide
          */
-        public static final String TETHER_DUN_APN = "tether_dun_apn";
+        @Deprecated
+        public static final String TETHER_DUN_APN = Global.TETHER_DUN_APN;
+
+        /**
+         * @deprecated Use {@link android.provider.Settings.Global#DATA_ACTIVITY_TIMEOUT_MOBILE}
+         * instead
+         * @hide
+         */
+        @Deprecated
+        public static final String DATA_ACTIVITY_TIMEOUT_MOBILE =
+            Global.DATA_ACTIVITY_TIMEOUT_MOBILE;
+
+        /**
+         * @deprecated Use {@link android.provider.Settings.Global#DATA_ACTIVITY_TIMEOUT_MOBILE}
+         * instead
+         * @hide
+         */
+        @Deprecated
+        public static final String DATA_ACTIVITY_TIMEOUT_WIFI = Global.DATA_ACTIVITY_TIMEOUT_WIFI;
 
         /**
          * No longer supported.
@@ -2854,13 +3311,11 @@
         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.
-         *
+         * @deprecated Use {@link android.provider.Settings.Global#SAMPLING_PROFILER_MS} instead
          * @hide
          */
-        public static final String SAMPLING_PROFILER_MS = "sampling_profiler_ms";
+        @Deprecated
+        public static final String SAMPLING_PROFILER_MS = Global.SAMPLING_PROFILER_MS;
 
         /**
          * Settings classname to launch when Settings is clicked from All
@@ -2871,15 +3326,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.
@@ -2982,6 +3438,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,46 +3563,51 @@
         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";
+                Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON;
         /**
+         * @deprecated Moved to Global namespace
          * {@hide}
          */
+        @Deprecated
         public static final String WIMAX_NETWORKS_AVAILABLE_NOTIFICATION_ON =
-                "wimax_networks_available_notification_on";
+                Global.WIMAX_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
+         * @deprecated Use {@link android.provider.Settings.Global#WIFI_COUNTRY_CODE}
+         * instead.
          * @hide
          */
-        public static final String WIFI_COUNTRY_CODE = "wifi_country_code";
+        @Deprecated
+        public static final String WIFI_COUNTRY_CODE = Global.WIFI_COUNTRY_CODE;
 
 
         /**
-         * 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_NUM_OPEN_NETWORKS_KEPT}
+         * instead.
          */
-        public static final String WIFI_NUM_OPEN_NETWORKS_KEPT = "wifi_num_open_networks_kept";
+        @Deprecated
+        public static final String WIFI_NUM_OPEN_NETWORKS_KEPT =
+                Global.WIFI_NUM_OPEN_NETWORKS_KEPT;
 
         /**
-         * Whether the Wi-Fi should be on.  Only the Wi-Fi service should touch this.
+         * @deprecated Use {@link android.provider.Settings.Global#WIFI_ON}
+         * instead.
          */
-        public static final String WIFI_ON = "wifi_on";
+        @Deprecated
+        public static final String WIFI_ON = Global.WIFI_ON;
 
         /**
          * Used to save the Wifi_ON state prior to tethering.
@@ -3114,8 +3615,10 @@
          * the user turns off tethering.
          *
          * @hide
+         * @deprecated moved to Global
          */
-        public static final String WIFI_SAVED_STATE = "wifi_saved_state";
+        @Deprecated
+        public static final String WIFI_SAVED_STATE = Global.WIFI_SAVED_STATE;
 
         /**
          * AP SSID
@@ -3239,13 +3742,6 @@
 
 
         /**
-         * 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
          */
@@ -3274,28 +3770,19 @@
                 "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.
+         * 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_WATCHDOG_WALLED_GARDEN_TEST_ENABLED =
-                "wifi_watchdog_walled_garden_test_enabled";
+        public static final String WIFI_SUSPEND_OPTIMIZATIONS_ENABLED =
+                "wifi_suspend_optimizations_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
+         * @deprecated Use
+         * {@link android.provider.Settings.Global#WIFI_MAX_DHCP_RETRY_COUNT} instead
          */
-        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";
+        @Deprecated
+        public static final String WIFI_MAX_DHCP_RETRY_COUNT = Global.WIFI_MAX_DHCP_RETRY_COUNT;
 
         /**
          * The operational wifi frequency band
@@ -3314,6 +3801,21 @@
         public static final String WIFI_P2P_DEVICE_NAME = "wifi_p2p_device_name";
 
         /**
+         * 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";
+
+        /**
          * 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.
          */
@@ -3341,26 +3843,25 @@
                 = "allowed_geolocation_origins";
 
         /**
-         * Whether mobile data connections are allowed by the user.  See
-         * ConnectivityManager for more info.
+         * @deprecated Use {@link android.provider.Settings.Global#MOBILE_DATA} instead
          * @hide
          */
-        public static final String MOBILE_DATA = "mobile_data";
+        @Deprecated
+        public static final String MOBILE_DATA = Global.MOBILE_DATA;
 
         /**
-         * The CDMA roaming mode 0 = Home Networks, CDMA default
-         *                       1 = Roaming on Affiliated networks
-         *                       2 = Roaming on any networks
+         * @deprecated Use {@link android.provider.Settings.Global#CDMA_ROAMING_MODE} instead
          * @hide
          */
-        public static final String CDMA_ROAMING_MODE = "roaming_settings";
+        @Deprecated
+        public static final String CDMA_ROAMING_MODE = Global.CDMA_ROAMING_MODE;
 
         /**
-         * The CDMA subscription mode 0 = RUIM/SIM (default)
-         *                                1 = NV
+         * @deprecated Use {@link android.provider.Settings.Global#CDMA_ROAMING_MODE} instead
          * @hide
          */
-        public static final String CDMA_SUBSCRIPTION_MODE = "subscription_mode";
+        @Deprecated
+        public static final String CDMA_SUBSCRIPTION_MODE = Global.CDMA_SUBSCRIPTION_MODE;
 
         /**
          * The preferred network mode   7 = Global
@@ -3388,13 +3889,11 @@
 
 
         /**
-         * CDMA Cell Broadcast SMS
-         *                            0 = CDMA Cell Broadcast SMS disabled
-         *                            1 = CDMA Cell Broadcast SMS enabled
+         * @deprecated Use {@link android.provider.Settings.Global#CDMA_CELL_BROADCAST_SMS} instead
          * @hide
          */
-        public static final String CDMA_CELL_BROADCAST_SMS =
-                "cdma_cell_broadcast_sms";
+        @Deprecated
+        public static final String CDMA_CELL_BROADCAST_SMS = Global.CDMA_CELL_BROADCAST_SMS;
 
         /**
          * The cdma subscription 0 = Subscription from RUIM, when available
@@ -3614,10 +4113,11 @@
         public static final String SEND_ACTION_APP_ERROR = "send_action_app_error";
 
         /**
-         * Nonzero causes Log.wtf() to crash.
+         * @deprecated Use {@link android.provider.Settings.Global#WTF_IS_FATAL} instead
          * @hide
          */
-        public static final String WTF_IS_FATAL = "wtf_is_fatal";
+        @Deprecated
+        public static final String WTF_IS_FATAL = Global.WTF_IS_FATAL;
 
         /**
          * Maximum age of entries kept by {@link com.android.internal.os.IDropBoxManagerService}.
@@ -3727,118 +4227,114 @@
          * When idle, it is possible for the device to be switched from Wi-Fi to
          * the mobile data network.
          * @hide
+         * @deprecated Moved to Global
          */
-        public static final String WIFI_IDLE_MS = "wifi_idle_ms";
+        @Deprecated
+        public static final String WIFI_IDLE_MS = Global.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
+         * @deprecated Moved to Global
          */
+        @Deprecated
         public static final String WIFI_FRAMEWORK_SCAN_INTERVAL_MS =
-                "wifi_framework_scan_interval_ms";
+                Global.WIFI_FRAMEWORK_SCAN_INTERVAL_MS;
 
         /**
          * The interval in milliseconds to scan as used by the wifi supplicant
          * @hide
+         * @deprecated Moved to Global
          */
+        @Deprecated
         public static final String WIFI_SUPPLICANT_SCAN_INTERVAL_MS =
-                "wifi_supplicant_scan_interval_ms";
+                Global.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.
+         * @deprecated Moved to Settings.Global
          * @hide
          */
+        @Deprecated
         public static final String PDP_WATCHDOG_POLL_INTERVAL_MS =
-                "pdp_watchdog_poll_interval_ms";
+                Global.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.
+         * @deprecated Moved to Settings.Global
          * @hide
          */
+        @Deprecated
         public static final String PDP_WATCHDOG_LONG_POLL_INTERVAL_MS =
-                "pdp_watchdog_long_poll_interval_ms";
+                Global.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.
+         * @deprecated Moved to Settings.Global
          * @hide
          */
+        @Deprecated
         public static final String PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS =
-                "pdp_watchdog_error_poll_interval_ms";
+                Global.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
+         * @deprecated Moved to Settings.Global
          * @hide
          */
+        @Deprecated
         public static final String PDP_WATCHDOG_TRIGGER_PACKET_COUNT =
-                "pdp_watchdog_trigger_packet_count";
+                Global.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.
+         * @deprecated Moved to Settings.Global
          * @hide
          */
+        @Deprecated
         public static final String PDP_WATCHDOG_ERROR_POLL_COUNT =
-                "pdp_watchdog_error_poll_count";
+                Global.PDP_WATCHDOG_ERROR_POLL_COUNT;
 
         /**
-         * The number of failed PDP reset attempts before moving to something more
-         * drastic: re-registering to the network.
+         * @deprecated Moved to Settings.Global
          * @hide
          */
+        @Deprecated
         public static final String PDP_WATCHDOG_MAX_PDP_RESET_FAIL_COUNT =
-                "pdp_watchdog_max_pdp_reset_fail_count";
+                Global.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.)
+         * @deprecated Moved to Settings.Global
          * @hide
          */
+        @Deprecated
         public static final String DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS =
-                "data_stall_alarm_non_aggressive_delay_in_ms";
+                Global.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)
+         * @deprecated Moved to Settings.Global
          * @hide
          */
+        @Deprecated
         public static final String DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS =
-                "data_stall_alarm_aggressive_delay_in_ms";
+                Global.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.
-         *
+         * @deprecated Moved to Settings.Global
          * @hide
          */
+        @Deprecated
         public static final String GPRS_REGISTER_CHECK_PERIOD_MS =
-                "gprs_register_check_period_ms";
+                Global.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.
+         * @deprecated Use {@link android.provider.Settings.Global#NITZ_UPDATE_SPACING} instead
          * @hide
          */
-        public static final String NITZ_UPDATE_SPACING = "nitz_update_spacing";
+        public static final String NITZ_UPDATE_SPACING = Global.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.
+         * @deprecated Use {@link android.provider.Settings.Global#NITZ_UPDATE_SPACING} instead
          * @hide
          */
-        public static final String NITZ_UPDATE_DIFF = "nitz_update_diff";
+        public static final String NITZ_UPDATE_DIFF = Global.NITZ_UPDATE_DIFF;
 
         /**
          * The maximum reconnect delay for short network outages or when the network is suspended
@@ -3849,21 +4345,18 @@
                 "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.
+         * @deprecated Use {@link Settings.Global#SMS_OUTGOING_CHECK_INTERVAL_MS} instead.
          * @hide
          */
         public static final String SMS_OUTGOING_CHECK_INTERVAL_MS =
-                "sms_outgoing_check_interval_ms";
+                Global.SMS_OUTGOING_CHECK_INTERVAL_MS;
 
         /**
-         * The number of outgoing SMS sent without asking for user permit
-         * (of {@link #SMS_OUTGOING_CHECK_INTERVAL_MS}
+         * @deprecated Use {@link Settings.Global#SMS_OUTGOING_CHECK_MAX_COUNT} instead.
          * @hide
          */
         public static final String SMS_OUTGOING_CHECK_MAX_COUNT =
-                "sms_outgoing_check_max_count";
+                Global.SMS_OUTGOING_CHECK_MAX_COUNT;
 
         /**
          * The global search provider chosen by the user (if multiple global
@@ -4100,65 +4593,70 @@
         public static final String DEFAULT_INSTALL_LOCATION = "default_install_location";
 
         /**
-         * The bandwidth throttle polling freqency in seconds
+         * @deprecated Use {@link android.provider.Settings.Global#THROTTLE_POLLING_SEC} instead
          * @hide
          */
-        public static final String THROTTLE_POLLING_SEC = "throttle_polling_sec";
+        @Deprecated
+        public static final String THROTTLE_POLLING_SEC = Global.THROTTLE_POLLING_SEC;
 
         /**
-         * The bandwidth throttle threshold (long)
+         * @deprecated Use {@link android.provider.Settings.Global#THROTTLE_THRESHOLD_BYTES} instead
          * @hide
          */
-        public static final String THROTTLE_THRESHOLD_BYTES = "throttle_threshold_bytes";
+        @Deprecated
+        public static final String THROTTLE_THRESHOLD_BYTES = Global.THROTTLE_THRESHOLD_BYTES;
 
         /**
-         * The bandwidth throttle value (kbps)
+         * @deprecated Use {@link android.provider.Settings.Global#THROTTLE_VALUE_KBITSPS} instead
          * @hide
          */
-        public static final String THROTTLE_VALUE_KBITSPS = "throttle_value_kbitsps";
+        @Deprecated
+        public static final String THROTTLE_VALUE_KBITSPS = Global.THROTTLE_VALUE_KBITSPS;
 
         /**
-         * The bandwidth throttle reset calendar day (1-28)
+         * @deprecated Use {@link android.provider.Settings.Global#THROTTLE_VALUE_KBITSPS} instead
          * @hide
          */
-        public static final String THROTTLE_RESET_DAY = "throttle_reset_day";
+        @Deprecated
+        public static final String THROTTLE_RESET_DAY = Global.THROTTLE_RESET_DAY;
 
         /**
-         * The throttling notifications we should send
+         * @deprecated Use {@link android.provider.Settings.Global#THROTTLE_NOTIFICATION_TYPE} instead
          * @hide
          */
-        public static final String THROTTLE_NOTIFICATION_TYPE = "throttle_notification_type";
+        @Deprecated
+        public static final String THROTTLE_NOTIFICATION_TYPE = Global.THROTTLE_NOTIFICATION_TYPE;
 
         /**
-         * Help URI for data throttling policy
+         * @deprecated Use {@link android.provider.Settings.Global#THROTTLE_HELP_URI} instead
          * @hide
          */
-        public static final String THROTTLE_HELP_URI = "throttle_help_uri";
+        @Deprecated
+        public static final String THROTTLE_HELP_URI = Global.THROTTLE_HELP_URI;
 
         /**
-         * The length of time in Sec that we allow our notion of NTP time
-         * to be cached before we refresh it
+         * @deprecated Use {@link android.provider.Settings.Global#THROTTLE_MAX_NTP_CACHE_AGE_SEC} instead
          * @hide
          */
+        @Deprecated
         public static final String THROTTLE_MAX_NTP_CACHE_AGE_SEC =
-                "throttle_max_ntp_cache_age_sec";
+                Global.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.
+         * @deprecated Use {@link android.provider.Settings.Global#DOWNLOAD_MAX_BYTES_OVER_MOBILE} instead
          * @hide
          */
+        @Deprecated
         public static final String DOWNLOAD_MAX_BYTES_OVER_MOBILE =
-                "download_manager_max_bytes_over_mobile";
+                Global.DOWNLOAD_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.
+         * @deprecated Use {@link android.provider.Settings.Global#DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE} instead
          * @hide
          */
+        @Deprecated
         public static final String DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE =
-                "download_manager_recommended_max_bytes_over_mobile";
+                Global.DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE;
 
         /**
          * ms during which to consume extra events related to Inet connection condition
@@ -4177,105 +4675,176 @@
                 "inet_condition_debounce_down_delay";
 
         /**
-         * URL to open browser on to allow user to manage a prepay account
+         * @deprecated Use {@link android.provider.Settings.Global#SETUP_PREPAID_DATA_SERVICE_URL} instead
          * @hide
          */
+        @Deprecated
         public static final String SETUP_PREPAID_DATA_SERVICE_URL =
-                "setup_prepaid_data_service_url";
+                Global.SETUP_PREPAID_DATA_SERVICE_URL;
 
         /**
-         * URL to attempt a GET on to see if this is a prepay device
+         * @deprecated Use {@link android.provider.Settings.Global#SETUP_PREPAID_DETECTION_TARGET_URL} instead
          * @hide
          */
+        @Deprecated
         public static final String SETUP_PREPAID_DETECTION_TARGET_URL =
-                "setup_prepaid_detection_target_url";
+                Global.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.)
+         * @deprecated Use {@link android.provider.Settings.Global#SETUP_PREPAID_DETECTION_REDIR_HOST} instead
          * @hide
          */
+        @Deprecated
         public static final String SETUP_PREPAID_DETECTION_REDIR_HOST =
-                "setup_prepaid_detection_redir_host";
+                Global.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";
+        /**
+         * 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 SCREENSAVER_ACTIVATE_ON_SLEEP = "screensaver_activate_on_sleep";
 
-        /** {@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";
+        /**
+         * If screensavers are enabled, the default screensaver component.
+         * @hide
+         */
+        public static final String SCREENSAVER_DEFAULT_COMPONENT = "screensaver_default_component";
 
-        /** {@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";
+        /** @deprecated The NETSTATS_* symbols live in Settings.Global.* now
+         * {@hide} */
+        @Deprecated
+        public static final String NETSTATS_ENABLED = Global.NETSTATS_ENABLED;
+        /** @deprecated The NETSTATS_* symbols live in Settings.Global.* now
+         * {@hide} */
+        @Deprecated
+        public static final String NETSTATS_POLL_INTERVAL = Global.NETSTATS_POLL_INTERVAL;
+        /** @deprecated The NETSTATS_* symbols live in Settings.Global.* now
+         * {@hide} */
+        @Deprecated
+        public static final String NETSTATS_TIME_CACHE_MAX_AGE = Global.NETSTATS_TIME_CACHE_MAX_AGE;
+        /** @deprecated The NETSTATS_* symbols live in Settings.Global.* now
+         * {@hide} */
+        @Deprecated
+        public static final String NETSTATS_GLOBAL_ALERT_BYTES = Global.NETSTATS_GLOBAL_ALERT_BYTES;
+        /** @deprecated The NETSTATS_* symbols live in Settings.Global.* now
+         * {@hide} */
+        @Deprecated
+        public static final String NETSTATS_SAMPLE_ENABLED = Global.NETSTATS_SAMPLE_ENABLED;
+        /** @deprecated The NETSTATS_* symbols live in Settings.Global.* now
+         * {@hide} */
+        @Deprecated
+        public static final String NETSTATS_REPORT_XT_OVER_DEV = Global.NETSTATS_REPORT_XT_OVER_DEV;
 
-        /** {@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";
+        /** @deprecated The NETSTATS_* symbols live in Settings.Global.* now
+         * {@hide} */
+        @Deprecated
+        public static final String NETSTATS_DEV_BUCKET_DURATION = Global.NETSTATS_DEV_BUCKET_DURATION;
+        /** @deprecated The NETSTATS_* symbols live in Settings.Global.* now
+         * {@hide} */
+        @Deprecated
+        public static final String NETSTATS_DEV_PERSIST_BYTES = Global.NETSTATS_DEV_PERSIST_BYTES;
+        /** @deprecated The NETSTATS_* symbols live in Settings.Global.* now
+         * {@hide} */
+        @Deprecated
+        public static final String NETSTATS_DEV_ROTATE_AGE = Global.NETSTATS_DEV_ROTATE_AGE;
+        /** @deprecated The NETSTATS_* symbols live in Settings.Global.* now
+         * {@hide} */
+        @Deprecated
+        public static final String NETSTATS_DEV_DELETE_AGE = Global.NETSTATS_DEV_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";
+        /** @deprecated The NETSTATS_* symbols live in Settings.Global.* now
+         * {@hide} */
+        @Deprecated
+        public static final String NETSTATS_UID_BUCKET_DURATION = Global.NETSTATS_UID_BUCKET_DURATION;
+        /** @deprecated The NETSTATS_* symbols live in Settings.Global.* now
+         * {@hide} */
+        @Deprecated
+        public static final String NETSTATS_UID_PERSIST_BYTES = Global.NETSTATS_UID_PERSIST_BYTES;
+        /** @deprecated The NETSTATS_* symbols live in Settings.Global.* now
+         * {@hide} */
+        @Deprecated
+        public static final String NETSTATS_UID_ROTATE_AGE = Global.NETSTATS_UID_ROTATE_AGE;
+        /** @deprecated The NETSTATS_* symbols live in Settings.Global.* now
+         * {@hide} */
+        @Deprecated
+        public static final String NETSTATS_UID_DELETE_AGE = Global.NETSTATS_UID_DELETE_AGE;
 
-        /** Autofill server address (Used in WebView/browser). {@hide} */
-        public static final String WEB_AUTOFILL_QUERY_URL =
-            "web_autofill_query_url";
+        /** @deprecated The NETSTATS_* symbols live in Settings.Global.* now
+         * {@hide} */
+        @Deprecated
+        public static final String NETSTATS_UID_TAG_BUCKET_DURATION = Global.NETSTATS_UID_TAG_BUCKET_DURATION;
+        /** @deprecated The NETSTATS_* symbols live in Settings.Global.* now
+         * {@hide} */
+        @Deprecated
+        public static final String NETSTATS_UID_TAG_PERSIST_BYTES = Global.NETSTATS_UID_TAG_PERSIST_BYTES;
+        /** @deprecated The NETSTATS_* symbols live in Settings.Global.* now
+         * {@hide} */
+        @Deprecated
+        public static final String NETSTATS_UID_TAG_ROTATE_AGE = Global.NETSTATS_UID_TAG_ROTATE_AGE;
+        /** @deprecated The NETSTATS_* symbols live in Settings.Global.* now
+         * {@hide} */
+        @Deprecated
+        public static final String NETSTATS_UID_TAG_DELETE_AGE = Global.NETSTATS_UID_TAG_DELETE_AGE;
 
-        /** Whether package verification is enabled. {@hide} */
-        public static final String PACKAGE_VERIFIER_ENABLE = "verifier_enable";
+        /** Preferred NTP server. {@hide}
+         * @deprecated moved to Settings.Global */
+        public static final String NTP_SERVER = Global.NTP_SERVER;
 
-        /** Timeout for package verification. {@hide} */
+        /** Timeout in milliseconds to wait for NTP server. {@hide}
+         * @deprecated moved to Settings.Global */
+        public static final String NTP_TIMEOUT = Global.NTP_TIMEOUT;
+
+        /** Autofill server address (Used in WebView/browser).
+         * @deprecated moved to Settings.Global
+         * {@hide} */
+        public static final String WEB_AUTOFILL_QUERY_URL = Global.WEB_AUTOFILL_QUERY_URL;
+
+        /**
+         * Whether the package manager should send package verification broadcasts for verifiers to
+         * review apps prior to installation.
+         * @deprecated moved to Settings.Global
+         * 1 = request apps to be verified prior to installation, if a verifier exists.
+         * 0 = do not verify apps before installation
+         * {@hide}
+         */
+        @Deprecated
+        public static final String PACKAGE_VERIFIER_ENABLE = "package_verifier_enable";
+
+        /** Timeout for package verification.
+         * @deprecated moved to Settings.Global
+         * {@hide} */
+        @Deprecated
         public static final String PACKAGE_VERIFIER_TIMEOUT = "verifier_timeout";
 
+        /** Default response code for package verification.
+         * @deprecated moved to Settings.Global
+         * {@hide} */
+        @Deprecated
+        public static final String PACKAGE_VERIFIER_DEFAULT_RESPONSE = "verifier_default_response";
+
         /** {@hide} */
         public static final String
                 READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT = "read_external_storage_enforced_default";
@@ -4289,11 +4858,23 @@
                 "contacts_preauth_uri_expiration";
 
         /**
-         * Prefix for SMS short code regex patterns (country code is appended).
-         * @see com.android.internal.telephony.SmsUsageMonitor
+         * 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 SMS_SHORT_CODES_PREFIX = "sms_short_codes_";
+        public static final String OVERLAY_DISPLAY_DEVICES = "overlay_display_devices";
 
         /**
          * This are the settings to be backed up.
@@ -4306,10 +4887,14 @@
          */
         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,
+            ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
+            ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
+            ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE,
             ACCESSIBILITY_SCRIPT_INJECTION,
             BACKUP_AUTO_RESTORE,
             ENABLED_ACCESSIBILITY_SERVICES,
@@ -4369,6 +4954,1044 @@
     }
 
     /**
+     * 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");
+
+        /**
+         * 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";
+
+       /**
+        * 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.
+        * @see com.android.internal.telephony.SmsUsageMonitor
+        * @hide
+        */
+       public static final String SMS_SHORT_CODE_CONFIRMATION = "sms_short_code_confirmation";
+
+       /**
+        * Prefix for SMS short code regex patterns (country code is appended).
+        * @see com.android.internal.telephony.SmsUsageMonitor
+        * @hide
+        */
+       public static final String SMS_SHORT_CODES_PREFIX = "sms_short_codes_";
+
+       /**
+        * 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 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";
+
+       /**
+        * ms delay interval between rssi polling when the signal is known to be weak
+        * @hide
+        */
+       public static final String WIFI_WATCHDOG_RSSI_FETCH_INTERVAL_MS =
+               "wifi_watchdog_rssi_fetch_interval_ms";
+
+       /**
+        * Number of ARP pings per check.
+        * @hide
+        */
+       public static final String WIFI_WATCHDOG_NUM_ARP_PINGS = "wifi_watchdog_num_arp_pings";
+
+       /**
+        * 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";
+
+
+
+
+        // Populated lazily, guarded by class object:
+        private static NameValueCache sNameValueCache = null;
+
+        private static void lazyInitCache() {
+            if (sNameValueCache == null) {
+                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 synchronized static String getString(ContentResolver resolver, String name) {
+            return getStringForUser(resolver, name, UserHandle.myUserId());
+        }
+
+        /** @hide */
+        public synchronized static String getStringForUser(ContentResolver resolver, String name,
+                int userHandle) {
+            lazyInitCache();
+            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) {
+            lazyInitCache();
+            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));
+        }
+    }
+
+    /**
      * User-defined bookmarks and shortcuts.  The target of each bookmark is an
      * Intent URL, allowing it to be either a web page or a particular
      * application activity.
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..bc3efdd 100644
--- a/core/java/android/server/search/SearchManagerService.java
+++ b/core/java/android/server/search/SearchManagerService.java
@@ -18,6 +18,9 @@
 
 import com.android.internal.content.PackageMonitor;
 
+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,11 +30,19 @@
 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.util.List;
 
@@ -48,7 +59,7 @@
     private final Context mContext;
 
     // This field is initialized lazily in getSearchables(), and then never modified.
-    private Searchables mSearchables;
+    private SparseArray<Searchables> mSearchables;
 
     private ContentObserver mGlobalSearchObserver;
 
@@ -66,14 +77,25 @@
                 mContext.getContentResolver());
     }
 
-    private synchronized Searchables getSearchables() {
+    private synchronized Searchables getSearchables(int userId) {
         if (mSearchables == null) {
-            Log.i(TAG, "Building list of searchable activities");
             new MyPackageMonitor().register(mContext, null, true);
-            mSearchables = new Searchables(mContext);
-            mSearchables.buildSearchableList();
+            mSearchables = new SparseArray<Searchables>();
         }
-        return mSearchables;
+        Searchables searchables = mSearchables.get(userId);
+
+        long origId = Binder.clearCallingIdentity();
+        boolean userExists = ((UserManager) mContext.getSystemService(Context.USER_SERVICE))
+                .getUserInfo(userId) != null;
+        Binder.restoreCallingIdentity(origId);
+
+        if (searchables == null && userExists) {
+            Log.i(TAG, "Building list of searchable activities for userId=" + userId);
+            searchables = new Searchables(mContext, userId);
+            searchables.buildSearchableList();
+            mSearchables.append(userId, searchables);
+        }
+        return searchables;
     }
 
     /**
@@ -87,7 +109,7 @@
                 public void run() {
                     Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                     mContext.unregisterReceiver(BootCompletedReceiver.this);
-                    getSearchables();
+                    getSearchables(0);
                 }
             }.start();
         }
@@ -109,12 +131,16 @@
         }
 
         private void updateSearchables() {
-            // Update list of searchable activities
-            getSearchables().buildSearchableList();
+            synchronized (SearchManagerService.this) {
+                // Update list of searchable activities
+                for (int i = 0; i < mSearchables.size(); i++) {
+                    getSearchables(mSearchables.keyAt(i)).buildSearchableList();
+                }
+            }
             // 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);
+            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
         }
     }
 
@@ -132,10 +158,14 @@
 
         @Override
         public void onChange(boolean selfChange) {
-            getSearchables().buildSearchableList();
+            synchronized (SearchManagerService.this) {
+                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 +186,76 @@
             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;
+    }
 }
diff --git a/core/java/android/server/search/Searchables.java b/core/java/android/server/search/Searchables.java
index f24d52f..30ca340 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,9 +24,12 @@
 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;
@@ -38,6 +42,7 @@
 
 /**
  * This class maintains the information about all searchable activities.
+ * This is a hidden class.
  */
 public class Searchables {
 
@@ -65,12 +70,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 +127,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,22 +207,22 @@
         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);
+        
+        searchList = 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);
+        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;
+            long token = Binder.clearCallingIdentity();
             for (int ii = 0; ii < count; ii++) {
                 // for each component, try to find metadata
                 ResolveInfo info = (ii < search_count)
@@ -229,6 +241,7 @@
                     }
                 }
             }
+            Binder.restoreCallingIdentity(token);
         }
 
         List<ResolveInfo> newGlobalSearchActivities = findGlobalSearchActivities();
@@ -262,10 +275,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 +312,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 +383,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 +395,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.
      */
diff --git a/core/java/android/service/dreams/Dream.java b/core/java/android/service/dreams/Dream.java
index 83464c9..ba2ac67 100644
--- a/core/java/android/service/dreams/Dream.java
+++ b/core/java/android/service/dreams/Dream.java
@@ -1,26 +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 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;
@@ -28,14 +33,14 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.Window;
+import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
 import android.view.accessibility.AccessibilityEvent;
-import android.view.WindowManager;
-import android.view.WindowManagerImpl;
+
+import com.android.internal.policy.PolicyManager;
 
 /**
- * @hide
- *
+ *  Extend this class to implement a custom screensaver.
  */
 public class Dream extends Service implements Window.Callback {
     private final static boolean DEBUG = true;
@@ -51,6 +56,10 @@
     public static final String SERVICE_INTERFACE =
             "android.service.dreams.Dream";
 
+    /** Service meta-data key for declaring an optional configuration activity. */
+    public static final String METADATA_NAME_CONFIG_ACTIVITY =
+            "android.service.dreams.config_activity";
+
     private Window mWindow;
 
     private WindowManager mWindowManager;
@@ -61,11 +70,17 @@
     final Handler mHandler = new Handler();
     
     boolean mFinished = false;
-    
+
     // begin Window.Callback methods
     @Override
     public boolean dispatchKeyEvent(KeyEvent event) {
-        if (!mInteractive) { 
+        // TODO: create more flexible version of mInteractive that allows use of KEYCODE_BACK
+        if (!mInteractive) {
+            if (DEBUG) Slog.v(TAG, "finishing on keyEvent");
+            finish();
+            return true;
+        } else if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
+            if (DEBUG) Slog.v(TAG, "finishing on back key");
             finish();
             return true;
         }
@@ -75,6 +90,7 @@
     @Override
     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
         if (!mInteractive) { 
+            if (DEBUG) Slog.v(TAG, "finishing on keyShortcutEvent");
             finish();
             return true;
         }
@@ -83,7 +99,10 @@
 
     @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 (DEBUG) Slog.v(TAG, "finishing on touchEvent");
             finish();
             return true;
         }
@@ -92,7 +111,8 @@
 
     @Override
     public boolean dispatchTrackballEvent(MotionEvent event) {
-        if (!mInteractive) { 
+        if (!mInteractive) {
+            if (DEBUG) Slog.v(TAG, "finishing on trackballEvent");
             finish();
             return true;
         }
@@ -102,6 +122,7 @@
     @Override
     public boolean dispatchGenericMotionEvent(MotionEvent event) {
         if (!mInteractive) { 
+            if (DEBUG) Slog.v(TAG, "finishing on genericMotionEvent");
             finish();
             return true;
         }
@@ -155,11 +176,6 @@
 
     @Override
     public void onAttachedToWindow() {
-        mWindow.addFlags(
-                WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
-                | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
-        );
-        lightsOut();
     }
 
     @Override
@@ -210,19 +226,14 @@
 
         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 
+     * Called when this Dream is started.
      */
-    @Override
-    public int onStartCommand(Intent intent, int flags, int startId) {
-        return super.onStartCommand(intent, flags, startId);
+    public void onStart() {
+        // hook for subclasses
     }
-    
+
    /**
      * Inflate a layout resource and set it to be the content view for this Dream.
      * Behaves similarly to {@link android.app.Activity#setContentView(int)}.
@@ -294,7 +305,8 @@
         // turn the lights down low
         final View v = mWindow.getDecorView();
         if (v != null) {
-            v.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
+            v.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE 
+                                  | View.SYSTEM_UI_FLAG_FULLSCREEN);
         }
     }
 
@@ -338,6 +350,11 @@
         lp.type = WindowManager.LayoutParams.TYPE_DREAM;
         lp.token = windowToken;
         lp.windowAnimations = com.android.internal.R.style.Animation_Dream;
+        lp.flags |= ( WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+                    | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
+                    | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON 
+                    );
+        mWindow.setAttributes(lp);
         
         //WindowManagerImpl.getDefault().addView(mWindow.getDecorView(), lp);
         
@@ -351,9 +368,12 @@
             @Override
             public void run() {
                 if (DEBUG) Slog.v(TAG, "Dream window added on thread " + Thread.currentThread().getId());
-                
+
                 getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes());
-            }});        
+
+                // start it up
+                onStart();
+            }});
     }
     
     /**
diff --git a/core/java/android/service/dreams/DreamManagerService.java b/core/java/android/service/dreams/DreamManagerService.java
index 4a14ced..4aa1cbb 100644
--- a/core/java/android/service/dreams/DreamManagerService.java
+++ b/core/java/android/service/dreams/DreamManagerService.java
@@ -1,55 +1,55 @@
 package android.service.dreams;
 
-import static android.provider.Settings.Secure.SCREENSAVER_COMPONENT;
-
+import static android.provider.Settings.Secure.SCREENSAVER_COMPONENTS;
+import static android.provider.Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
-import com.android.internal.view.IInputMethod;
-
+import android.app.ActivityManagerNative;
+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.IBinder;
 import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemClock;
+import android.os.UserHandle;
 import android.provider.Settings;
-import android.util.Log;
 import android.util.Slog;
 import android.view.IWindowManager;
 import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
 
 /**
- * 
+ *
  * @hide
  *
  */
 
-public class DreamManagerService 
-        extends IDreamManager.Stub 
+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; 
+    private Binder mCurrentDreamToken;
+    private int mCurrentUserId;
 
     public DreamManagerService(Context context) {
         if (DEBUG) Slog.v(TAG, "DreamManagerService startup");
         mContext = context;
-        mIWindowManager = IWindowManager.Stub.asInterface(
-                ServiceManager.getService(Context.WINDOW_SERVICE));
+        mIWindowManager = WindowManagerGlobal.getWindowManagerService();
     }
 
     private void checkPermission(String permission) {
@@ -60,8 +60,10 @@
     }
 
     // IDreamManager method
+    @Override
     public void dream() {
-        ComponentName name = getDreamComponent();
+        ComponentName[] dreams = getDreamComponentsForUser(mCurrentUserId);
+        ComponentName name = dreams != null && dreams.length > 0 ? dreams[0] : null;
         if (name != null) {
             synchronized (mLock) {
                 final long ident = Binder.clearCallingIdentity();
@@ -75,26 +77,58 @@
     }
 
     // IDreamManager method
-    public void setDreamComponent(ComponentName name) {
-        Settings.Secure.putString(mContext.getContentResolver(), SCREENSAVER_COMPONENT, name.flattenToString());
+    @Override
+    public void setDreamComponents(ComponentName[] componentNames) {
+        Settings.Secure.putStringForUser(mContext.getContentResolver(),
+                SCREENSAVER_COMPONENTS,
+                componentsToString(componentNames),
+                UserHandle.getCallingUserId());
     }
-    
-    // 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);
+
+    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());
+            }
         }
-        if (component != null) {
-            return ComponentName.unflattenFromString(component);
-        } else {
-            return null;
-        }
+        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;
+    }
+
     // IDreamManager method
+    @Override
+    public ComponentName[] getDreamComponents() {
+        return getDreamComponentsForUser(UserHandle.getCallingUserId());
+    }
+
+    private ComponentName[] getDreamComponentsForUser(int userId) {
+        String names = Settings.Secure.getStringForUser(mContext.getContentResolver(),
+                SCREENSAVER_COMPONENTS,
+                userId);
+        return names == null ? null : componentsFromString(names);
+    }
+
+    // IDreamManager method
+    @Override
+    public ComponentName getDefaultDreamComponent() {
+        String name = Settings.Secure.getStringForUser(mContext.getContentResolver(),
+                SCREENSAVER_DEFAULT_COMPONENT,
+                UserHandle.getCallingUserId());
+        return name == null ? null : ComponentName.unflattenFromString(name);
+    }
+
+    // IDreamManager method
+    @Override
     public void testDream(ComponentName name) {
         if (DEBUG) Slog.v(TAG, "startDream name=" + name
                 + " pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
@@ -110,15 +144,27 @@
     }
 
     // IDreamManager method
+    @Override
     public void awaken() {
         if (DEBUG) Slog.v(TAG, "awaken()");
         synchronized (mLock) {
             if (mCurrentDream != null) {
+                if (DEBUG) Slog.v(TAG, "disconnecting: " +  mCurrentDreamComponent + " service: " + mCurrentDream);
                 mContext.unbindService(this);
+                mCurrentDream = null;
+                mCurrentDreamToken = null;
             }
         }
     }
 
+    // IDreamManager method
+    @Override
+    public boolean isDreaming() {
+        synchronized (mLock) {
+            return mCurrentDreamToken != null;
+        }
+    }
+
     public void bindDreamComponentL(ComponentName componentName, boolean test) {
         if (DEBUG) Slog.v(TAG, "bindDreamComponent: componentName=" + componentName
                 + " pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
@@ -129,22 +175,21 @@
                 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 
+            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.");
         }
-        
+
+        if (!mContext.bindService(intent, this, Context.BIND_AUTO_CREATE)) {
+            Slog.w(TAG, "unable to bind service: " + componentName);
+        }
     }
 
     @Override
@@ -163,10 +208,9 @@
     @Override
     public void onServiceDisconnected(ComponentName name) {
         if (DEBUG) Slog.v(TAG, "disconnected: " + name + " service: " + mCurrentDream);
-        mCurrentDream = null;
-        mCurrentDreamToken = null;
+        // Only happens in exceptional circumstances
     }
-    
+
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
@@ -178,6 +222,25 @@
     }
 
     public void systemReady() {
+
+        // dream settings are kept per user, so keep track of current user
+        try {
+            mCurrentUserId = ActivityManagerNative.getDefault().getCurrentUser().id;
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Couldn't get current user ID; guessing it's 0", e);
+        }
+        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, 0);
+                    if (DEBUG) Slog.v(TAG, "userId " + mCurrentUserId + " is in the house");
+                }
+            }}, filter);
+
         if (DEBUG) Slog.v(TAG, "ready to dream!");
     }
 
diff --git a/core/java/android/service/dreams/IDreamManager.aidl b/core/java/android/service/dreams/IDreamManager.aidl
index 7225013..b6fcdf0 100644
--- a/core/java/android/service/dreams/IDreamManager.aidl
+++ b/core/java/android/service/dreams/IDreamManager.aidl
@@ -24,7 +24,9 @@
 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();
 }
\ No newline at end of file
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..86bbc55 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) {
@@ -599,13 +606,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 +672,8 @@
                             }
                         }
 
-                        redrawNeeded |= creating
-                                || (relayoutResult&WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0;
+                        redrawNeeded |= creating || (relayoutResult
+                                & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0;
 
                         if (forceReport || creating || surfaceCreating
                                 || formatChanged || sizeChanged) {
@@ -753,7 +760,7 @@
             mWindowToken = wrapper.mWindowToken;
             mSurfaceHolder.setSizeFromLayout();
             mInitializing = true;
-            mSession = ViewRootImpl.getWindowSession(getMainLooper());
+            mSession = WindowManagerGlobal.getWindowSession(getMainLooper());
             
             mWindow.setSession(mSession);
 
@@ -1013,6 +1020,12 @@
                     mEngine = engine;
                     mActiveEngines.add(engine);
                     engine.attach(this);
+                    try {
+                        mConnection.engineShown(this);
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "Wallpaper host disappeared", e);
+                        return;
+                    }
                     return;
                 }
                 case DO_DETACH: {
@@ -1044,6 +1057,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/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..bbaa173 100644
--- a/core/java/android/text/TextDirectionHeuristics.java
+++ b/core/java/android/text/TextDirectionHeuristics.java
@@ -22,6 +22,7 @@
 
 /**
  * Some objects that implement TextDirectionHeuristic.
+ *
  * @hide
  */
 public class TextDirectionHeuristics {
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 270624c..987062a 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -27,6 +27,7 @@
 import android.text.style.EasyEditSpan;
 import android.text.style.ForegroundColorSpan;
 import android.text.style.LeadingMarginSpan;
+import android.text.style.LocaleSpan;
 import android.text.style.MetricAffectingSpan;
 import android.text.style.QuoteSpan;
 import android.text.style.RelativeSizeSpan;
@@ -587,6 +588,8 @@
     public static final int SUGGESTION_RANGE_SPAN = 21;
     /** @hide */
     public static final int EASY_EDIT_SPAN = 22;
+    /** @hide */
+    public static final int LOCALE_SPAN = 23;
 
     /**
      * Flatten a CharSequence and whatever styles can be copied across processes
@@ -754,6 +757,10 @@
                     readSpan(p, sp, new EasyEditSpan());
                     break;
 
+                case LOCALE_SPAN:
+                    readSpan(p, sp, new LocaleSpan(p));
+                    break;
+
                 default:
                     throw new RuntimeException("bogus span encoding " + kind);
                 }
@@ -1042,9 +1049,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);
     }
 
     /**
@@ -1700,9 +1712,4 @@
     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);
 }
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
index 524f941..c36273e 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:
@@ -374,7 +391,7 @@
                 index++;
             }
 
-            if (!foundMonth && (c == MONTH)) {
+            if (!foundMonth && (c == MONTH || c == STANDALONE_MONTH)) {
                 foundMonth = true;
                 order[index] = MONTH;
                 index++;
@@ -494,9 +511,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,14 +545,19 @@
             return s.toString();
     }
     
-    private static final String getMonthString(Calendar inDate, int count) {
+    private static final 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);
         }
@@ -574,7 +597,8 @@
     
     private static final 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) {
@@ -615,17 +639,6 @@
     }
 
     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;
+        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..0babcc5 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;
@@ -336,18 +242,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 +264,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 +280,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 +314,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 +552,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;
diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java
index e9b0d32..45d5a70 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
@@ -317,73 +319,21 @@
             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];
+
+                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;
             }
@@ -437,6 +387,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;
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
index 93f5cd3..60526e1 100644
--- a/core/java/android/util/LocaleUtil.java
+++ b/core/java/android/util/LocaleUtil.java
@@ -24,7 +24,6 @@
 /**
  * Various utilities for Locales
  *
- * @hide
  */
 public class LocaleUtil {
 
@@ -41,8 +40,7 @@
      * {@link View#LAYOUT_DIRECTION_LTR} or
      * {@link View#LAYOUT_DIRECTION_RTL}.
      *
-     * Warning: this code does not support vertical scripts.
-     * @hide
+     * 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)) {
@@ -68,7 +66,8 @@
      * {@link View#LAYOUT_DIRECTION_LTR} or
      * {@link View#LAYOUT_DIRECTION_RTL}.
      *
-     * Warning: this code does not support vertical scripts.
+     * Be careful: this code will need to be updated when vertical scripts will be supported
+     *
      * @hide
      */
     private static int getLayoutDirectionFromFirstChar(Locale locale) {
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..6848606 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -16,6 +16,8 @@
 
 package android.view;
 
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerGlobal;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -164,8 +166,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 +175,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.
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..cf58458 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -16,61 +16,213 @@
 
 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 String mName;
+    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 secure video output.
+     * <p>
+     * This flag is used to indicate that the display supports content protection
+     * mechanisms for secure video output at the display interface, such as HDCP.
+     * These mechanisms may be used to protect secure content as it leaves the device.
+     * </p><p>
+     * While mirroring content to multiple displays, it can happen that certain
+     * display devices support secure video output while other display devices do not.
+     * The secure content will be shown only on the display devices that support
+     * secure video output and will be blanked on other display devices that do
+     * not support secure video output.
+     * </p><p>
+     * This flag mainly applies to external display devices such as HDMI or
+     * Wifi display.  Built-in display devices are usually considered secure.
+     * </p>
+     *
+     * @hide pending review
      */
-    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_SECURE_VIDEO_OUTPUT = 1 << 0;
+
+    /**
+     * Display flag: Indicates that the display supports secure in-memory video buffers.
+     * <p>
+     * This flag is used to indicate that the display supports content protection
+     * mechanisms for in-memory video buffers, such as secure memory areas.
+     * These mechanisms may be used to protect secure video buffers in memory from
+     * the video decoder to the display compositor and the video interface.
+     * </p>
+     *
+     * @hide pending review
+     */
+    public static final int FLAG_SUPPORTS_SECURE_VIDEO_BUFFERS = 1 << 1;
+
+    /**
+     * 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;
+        mLayerStack = displayInfo.layerStack; // can never change as long as the display is valid
+        mName = displayInfo.name; // cannot change as long as the display is valid
+        mCompatibilityInfo = compatibilityInfo;
+        mIsValid = true;
     }
 
     /**
-     * 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.
+     *
+     * @hide pending review
+     */
+    public int getFlags() {
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            return mDisplayInfo.flags;
+        }
+    }
+
+    /**
+     * 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.
+     * @return The display's name.
+     */
+    public String getName() {
+        return mName;
+    }
+
     /**
      * Gets the size of the display, in pixels.
      * <p>
@@ -84,7 +236,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 +244,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 +259,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 +297,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 +312,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 +323,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 +334,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 +358,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 +410,93 @@
      * @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;
-
-    /**
-     * 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);
+    // For debugging purposes
+    @Override
+    public String toString() {
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
+            return "Display id " + mDisplayId + ": " + mDisplayInfo
+                    + ", " + mTempMetrics + ", isValid=" + mIsValid;
+        }
     }
 }
 
diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java
index 6c2e540..0b138c2 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;
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..c968ec5
--- /dev/null
+++ b/core/java/android/view/DisplayInfo.java
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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;
+
+    /**
+     * 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>() {
+        public DisplayInfo createFromParcel(Parcel source) {
+            return new DisplayInfo(source);
+        }
+
+        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
+                && 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;
+        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();
+        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(flags);
+        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 + flagsToString(flags) + "}";
+    }
+
+    private static String flagsToString(int flags) {
+        StringBuilder result = new StringBuilder();
+        if ((flags & Display.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT) != 0) {
+            result.append(", FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT");
+        }
+        if ((flags & Display.FLAG_SUPPORTS_SECURE_VIDEO_BUFFERS) != 0) {
+            result.append(", FLAG_SUPPORTS_SECURE_VIDEO_BUFFERS");
+        }
+        return result.toString();
+    }
+}
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index 31a9f05..351c5c3 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)
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 055aee3..032ff7bc 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -150,13 +150,15 @@
     
     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 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);
@@ -394,13 +396,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..3bdd5c0 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,7 @@
     public void clear() {
         if (!mValid) {
             mBitmaps.clear();
+            mChildDisplayLists.clear();
         }
     }
 
diff --git a/core/java/android/view/GLES20Layer.java b/core/java/android/view/GLES20Layer.java
index 4f25792..a462ed6 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,13 +65,6 @@
         }
         mLayer = 0;
     }
-    
-    @Override
-    void flush() {
-        if (mLayer != 0) {
-            GLES20Canvas.nFlushLayer(mLayer);
-        }
-    }
 
     static class Finalizer {
         private int mLayerId;
diff --git a/core/java/android/view/GLES20RecordingCanvas.java b/core/java/android/view/GLES20RecordingCanvas.java
index c9ba65f..ba8be6c 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);
diff --git a/core/java/android/view/GLES20RenderLayer.java b/core/java/android/view/GLES20RenderLayer.java
index c727a36..fcfc8e1 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
diff --git a/core/java/android/view/GLES20TextureLayer.java b/core/java/android/view/GLES20TextureLayer.java
index 16a13cf..b0ee2aa 100644
--- a/core/java/android/view/GLES20TextureLayer.java
+++ b/core/java/android/view/GLES20TextureLayer.java
@@ -42,19 +42,14 @@
         }        
     }
 
-    GLES20TextureLayer(SurfaceTexture surface, boolean isOpaque) {
-        this(isOpaque);
-        mSurface = surface;
-        mSurface.attachToGLContext(mTexture);
-    }
-
     @Override
     boolean isValid() {
         return mLayer != 0 && mTexture != 0;
     }
 
     @Override
-    void resize(int width, int height) {
+    boolean resize(int width, int height) {
+        return isValid();
     }
 
     @Override
@@ -93,6 +88,11 @@
     }
 
     @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);
     }
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..f031fe7 100644
--- a/core/java/android/view/Gravity.java
+++ b/core/java/android/view/Gravity.java
@@ -155,7 +155,6 @@
      *
      * @see {@link View#LAYOUT_DIRECTION_LTR}
      * @see {@link View#LAYOUT_DIRECTION_RTL}
-     * @hide
      */
     public static void apply(int gravity, int w, int h, Rect container,
             Rect outRect, int layoutDirection) {
@@ -293,7 +292,6 @@
      *
      * @see {@link View#LAYOUT_DIRECTION_LTR}
      * @see {@link View#LAYOUT_DIRECTION_RTL}
-     * @hide
      */
     public static void apply(int gravity, int w, int h, Rect container,
                              int xAdj, int yAdj, Rect outRect, int layoutDirection) {
@@ -374,7 +372,6 @@
      *
      * @see {@link View#LAYOUT_DIRECTION_LTR}
      * @see {@link View#LAYOUT_DIRECTION_RTL}
-     * @hide
      */
     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/HardwareLayer.java b/core/java/android/view/HardwareLayer.java
index e73f7bf..d798e73 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
      */
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index dab48b1..446a51e 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -135,7 +135,19 @@
      * @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";
+
     /**
      * A process can set this flag to false to prevent the use of hardware
      * rendering.
@@ -197,18 +209,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 +240,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
@@ -474,14 +486,14 @@
      *
      * @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
      */
-    void initializeIfNeeded(int width, int height, SurfaceHolder holder)
+    void 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);
                 }
             }
@@ -721,13 +733,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 +758,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 +787,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 +816,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
@@ -888,7 +906,7 @@
             Log.d(LOG_TAG, "  SURFACE_TYPE = 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,7 +926,7 @@
             destroySurface();
 
             // Create an EGL surface we can render into.
-            if (!createSurface(holder)) {
+            if (!createSurface(surface)) {
                 return null;
             }
 
@@ -982,7 +1000,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 +1011,8 @@
                 setEnabled(false);
             }
 
-            if (holder.getSurface().isValid()) {
-                if (!createSurface(holder)) {
+            if (surface.isValid()) {
+                if (!createSurface(surface)) {
                     return;
                 }
 
@@ -1006,8 +1024,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();
@@ -1089,7 +1107,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) {
@@ -1123,9 +1141,9 @@
                     callbacks.onHardwarePreDraw(canvas);
 
                     try {
-                        view.mRecreateDisplayList =
-                                (view.mPrivateFlags & View.INVALIDATED) == View.INVALIDATED;
-                        view.mPrivateFlags &= ~View.INVALIDATED;
+                        view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
+                                == View.PFLAG_INVALIDATED;
+                        view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
 
                         long getDisplayListStartTime = 0;
                         if (mProfileEnabled) {
diff --git a/core/java/android/view/IDisplayContentChangeListener.aidl b/core/java/android/view/IDisplayContentChangeListener.aidl
new file mode 100644
index 0000000..8f23ff6
--- /dev/null
+++ b/core/java/android/view/IDisplayContentChangeListener.aidl
@@ -0,0 +1,32 @@
+/*
+** 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 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..a64cbf7 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -23,8 +23,10 @@
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.Point;
+import android.graphics.Rect;
 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 +35,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 +58,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();
@@ -85,7 +86,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,
@@ -106,6 +107,9 @@
             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);
@@ -187,7 +191,7 @@
 	/**
 	 * Create a screenshot of the applications currently displayed.
 	 */
-	Bitmap screenshotApplications(IBinder appToken, int maxWidth, int maxHeight);
+	Bitmap screenshotApplications(IBinder appToken, int displayId, int maxWidth, int maxHeight);
 
     /**
      * Called by the status bar to notify Views of changes to System UI visiblity.
@@ -208,4 +212,44 @@
      * Lock the device immediately.
      */
     void lockNow();
+
+    /**
+     * 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);
 }
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/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 26a5b26..f692e05 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -20,6 +20,7 @@
 import android.os.Handler;
 import android.os.Message;
 import android.widget.FrameLayout;
+import com.android.internal.R;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -43,20 +44,20 @@
  *
  * <pre>LayoutInflater inflater = (LayoutInflater)context.getSystemService
  *      (Context.LAYOUT_INFLATER_SERVICE);</pre>
- * 
+ *
  * <p>
  * To create a new LayoutInflater with an additional {@link Factory} for your
  * own views, you can use {@link #cloneInContext} to clone an existing
  * ViewFactory, and then call {@link #setFactory} on it to include your
  * Factory.
- * 
+ *
  * <p>
  * For performance reasons, view inflation relies heavily on pre-processing of
  * XML files that is done at build time. Therefore, it is not currently possible
  * to use LayoutInflater with an XmlPullParser over a plain XML file at runtime;
  * it only works with an XmlPullParser returned from a compiled resource
  * (R.<em>something</em> file.)
- * 
+ *
  * @see Context#getSystemService
  */
 public abstract class LayoutInflater {
@@ -82,7 +83,7 @@
 
     private static final HashMap<String, Constructor<? extends View>> sConstructorMap =
             new HashMap<String, Constructor<? extends View>>();
-    
+
     private HashMap<String, Boolean> mFilterMap;
 
     private static final String TAG_MERGE = "merge";
@@ -93,36 +94,36 @@
     /**
      * Hook to allow clients of the LayoutInflater to restrict the set of Views that are allowed
      * to be inflated.
-     * 
+     *
      */
     public interface Filter {
         /**
          * Hook to allow clients of the LayoutInflater to restrict the set of Views 
          * that are allowed to be inflated.
-         * 
+         *
          * @param clazz The class object for the View that is about to be inflated
-         * 
+         *
          * @return True if this class is allowed to be inflated, or false otherwise
          */
         @SuppressWarnings("unchecked")
         boolean onLoadClass(Class clazz);
     }
-    
+
     public interface Factory {
         /**
          * Hook you can supply that is called when inflating from a LayoutInflater.
          * You can use this to customize the tag names available in your XML
          * layout files.
-         * 
+         *
          * <p>
          * Note that it is good practice to prefix these custom names with your
          * package (i.e., com.coolcompany.apps) to avoid conflicts with system
          * names.
-         * 
+         *
          * @param name Tag name to be inflated.
          * @param context The context the view is being created in.
          * @param attrs Inflation attributes as specified in XML file.
-         * 
+         *
          * @return View Newly created view. Return null for the default
          *         behavior.
          */
@@ -150,14 +151,14 @@
     private static class FactoryMerger implements Factory2 {
         private final Factory mF1, mF2;
         private final Factory2 mF12, mF22;
-        
+
         FactoryMerger(Factory f1, Factory2 f12, Factory f2, Factory2 f22) {
             mF1 = f1;
             mF2 = f2;
             mF12 = f12;
             mF22 = f22;
         }
-        
+
         public View onCreateView(String name, Context context, AttributeSet attrs) {
             View v = mF1.onCreateView(name, context, attrs);
             if (v != null) return v;
@@ -172,13 +173,13 @@
                     : mF2.onCreateView(name, context, attrs);
         }
     }
-    
+
     /**
      * Create a new LayoutInflater instance associated with a particular Context.
      * Applications will almost always want to use
      * {@link Context#getSystemService Context.getSystemService()} to retrieve
      * the standard {@link Context#LAYOUT_INFLATER_SERVICE Context.INFLATER_SERVICE}.
-     * 
+     *
      * @param context The Context in which this LayoutInflater will create its
      * Views; most importantly, this supplies the theme from which the default
      * values for their attributes are retrieved.
@@ -191,7 +192,7 @@
      * Create a new LayoutInflater instance that is a copy of an existing
      * LayoutInflater, optionally with its Context changed.  For use in
      * implementing {@link #cloneInContext}.
-     * 
+     *
      * @param original The original LayoutInflater to copy.
      * @param newContext The new Context to use.
      */
@@ -202,7 +203,7 @@
         mPrivateFactory = original.mPrivateFactory;
         mFilter = original.mFilter;
     }
-    
+
     /**
      * Obtains the LayoutInflater from the given context.
      */
@@ -220,15 +221,15 @@
      * pointing to a different Context than the original.  This is used by
      * {@link ContextThemeWrapper} to create a new LayoutInflater to go along
      * with the new Context theme.
-     * 
+     *
      * @param newContext The new Context to associate with the new LayoutInflater.
      * May be the same as the original Context if desired.
-     * 
+     *
      * @return Returns a brand spanking new LayoutInflater object associated with
      * the given Context.
      */
     public abstract LayoutInflater cloneInContext(Context newContext);
-    
+
     /**
      * Return the context we are running in, for access to resources, class
      * loader, etc.
@@ -264,7 +265,7 @@
      * called on each element name as the xml is parsed. If the factory returns
      * a View, that is added to the hierarchy. If it returns null, the next
      * factory default {@link #onCreateView} method is called.
-     * 
+     *
      * <p>If you have an existing
      * LayoutInflater and want to add your own factory to it, use
      * {@link #cloneInContext} to clone the existing instance and then you
@@ -320,13 +321,13 @@
     public Filter getFilter() {
         return mFilter;
     }
-    
+
     /**
      * Sets the {@link Filter} to by this LayoutInflater. If a view is attempted to be inflated
      * which is not allowed by the {@link Filter}, the {@link #inflate(int, ViewGroup)} call will
      * throw an {@link InflateException}. This filter will replace any previous filter set on this
      * LayoutInflater.
-     * 
+     *
      * @param filter The Filter which restricts the set of Views that are allowed to be inflated.
      *        This filter will replace any previous filter set on this LayoutInflater.
      */
@@ -340,7 +341,7 @@
     /**
      * Inflate a new view hierarchy from the specified xml resource. Throws
      * {@link InflateException} if there is an error.
-     * 
+     *
      * @param resource ID for an XML layout resource to load (e.g.,
      *        <code>R.layout.main_page</code>)
      * @param root Optional view to be the parent of the generated hierarchy.
@@ -360,7 +361,7 @@
      * reasons, view inflation relies heavily on pre-processing of XML files
      * that is done at build time. Therefore, it is not currently possible to
      * use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
-     * 
+     *
      * @param parser XML dom node containing the description of the view
      *        hierarchy.
      * @param root Optional view to be the parent of the generated hierarchy.
@@ -375,7 +376,7 @@
     /**
      * Inflate a new view hierarchy from the specified xml resource. Throws
      * {@link InflateException} if there is an error.
-     * 
+     *
      * @param resource ID for an XML layout resource to load (e.g.,
      *        <code>R.layout.main_page</code>)
      * @param root Optional view to be the parent of the generated hierarchy (if
@@ -407,7 +408,7 @@
      * reasons, view inflation relies heavily on pre-processing of XML files
      * that is done at build time. Therefore, it is not currently possible to
      * use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
-     * 
+     *
      * @param parser XML dom node containing the description of the view
      *        hierarchy.
      * @param root Optional view to be the parent of the generated hierarchy (if
@@ -442,7 +443,7 @@
                 }
 
                 final String name = parser.getName();
-                
+
                 if (DEBUG) {
                     System.out.println("**************************");
                     System.out.println("Creating root view: "
@@ -528,17 +529,17 @@
      * Low-level function for instantiating a view by name. This attempts to
      * instantiate a view class of the given <var>name</var> found in this
      * LayoutInflater's ClassLoader.
-     * 
+     *
      * <p>
      * There are two things that can happen in an error case: either the
      * exception describing the error will be thrown, or a null will be
      * returned. You must deal with both possibilities -- the former will happen
      * the first time createView() is called for a class of a particular name,
      * the latter every time there-after for that class name.
-     * 
+     *
      * @param name The full name of the class to be instantiated.
      * @param attrs The XML attributes supplied for this instance.
-     * 
+     *
      * @return View The newly instantiated view, or null.
      */
     public final View createView(String name, String prefix, AttributeSet attrs)
@@ -551,7 +552,7 @@
                 // Class not found in the cache, see if it's real, and try to add it
                 clazz = mContext.getClassLoader().loadClass(
                         prefix != null ? (prefix + name) : name).asSubclass(View.class);
-                
+
                 if (mFilter != null && clazz != null) {
                     boolean allowed = mFilter.onLoadClass(clazz);
                     if (!allowed) {
@@ -569,7 +570,7 @@
                         // New class -- remember whether it is allowed
                         clazz = mContext.getClassLoader().loadClass(
                                 prefix != null ? (prefix + name) : name).asSubclass(View.class);
-                        
+
                         boolean allowed = clazz != null && mFilter.onLoadClass(clazz);
                         mFilterMap.put(name, allowed);
                         if (!allowed) {
@@ -632,10 +633,10 @@
      * given the xml element name. Override it to handle custom view objects. If
      * you override this in your subclass be sure to call through to
      * super.onCreateView(name) for names you do not recognize.
-     * 
+     *
      * @param name The fully qualified class name of the View to be create.
      * @param attrs An AttributeSet of attributes to apply to the View.
-     * 
+     *
      * @return View The View created.
      */
     protected View onCreateView(String name, AttributeSet attrs)
@@ -679,7 +680,7 @@
             if (view == null && mPrivateFactory != null) {
                 view = mPrivateFactory.onCreateView(parent, name, mContext, attrs);
             }
-            
+
             if (view == null) {
                 if (-1 == name.indexOf('.')) {
                     view = onCreateView(parent, name, attrs);
@@ -726,7 +727,7 @@
             }
 
             final String name = parser.getName();
-            
+
             if (TAG_REQUEST_FOCUS.equals(name)) {
                 parseRequestFocus(parser, parent);
             } else if (TAG_INCLUDE.equals(name)) {
@@ -741,7 +742,7 @@
                 final ViewGroup viewGroup = (ViewGroup) parent;
                 final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
                 rInflate(parser, view, attrs, true);
-                viewGroup.addView(view, params);                
+                viewGroup.addView(view, params);
             } else {
                 final View view = createViewFromTag(parent, name, attrs);
                 final ViewGroup viewGroup = (ViewGroup) parent;
@@ -810,21 +811,14 @@
                         // We try to load the layout params set in the <include /> tag. If
                         // they don't exist, we will rely on the layout params set in the
                         // included XML file.
-                        // During a layoutparams generation, a runtime exception is thrown
-                        // if either layout_width or layout_height is missing. We catch
-                        // this exception and set localParams accordingly: true means we
-                        // successfully loaded layout params from the <include /> tag,
-                        // false means we need to rely on the included layout params.
-                        ViewGroup.LayoutParams params = null;
-                        try {
-                            params = group.generateLayoutParams(attrs);
-                        } catch (RuntimeException e) {
-                            params = group.generateLayoutParams(childAttrs);
-                        } finally {
-                            if (params != null) {
-                                view.setLayoutParams(params);
-                            }
-                        }
+                        TypedArray ta = getContext().obtainStyledAttributes(attrs,
+                                                            R.styleable.ViewGroup_Layout);
+                        boolean definesBothWidthAndHeight =
+                                ta.hasValue(R.styleable.ViewGroup_Layout_layout_width) &&
+                                ta.hasValue(R.styleable.ViewGroup_Layout_layout_height);
+                        AttributeSet attributes = definesBothWidthAndHeight ? attrs : childAttrs;
+                        view.setLayoutParams(group.generateLayoutParams(attributes));
+                        ta.recycle();
 
                         // Inflate all children.
                         rInflate(childParser, view, childAttrs, true);
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index bcb8800..fa03139 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -137,6 +137,7 @@
     private long mPrevTime;
     private boolean mInProgress;
     private int mSpanSlop;
+    private int mMinSpan;
 
     /**
      * Consistency verifier for debugging purposes.
@@ -149,6 +150,8 @@
         mContext = context;
         mListener = listener;
         mSpanSlop = ViewConfiguration.get(context).getScaledTouchSlop() * 2;
+        mMinSpan = context.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.config_minScalingSpan);
     }
 
     /**
@@ -209,8 +212,11 @@
         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);
+
+            // Average touch major and touch minor and convert the resulting diameter into a radius.
+            final float touchSize = (event.getTouchMajor(i) + event.getTouchMinor(i)) / 4;
+            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 +234,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 +244,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..8f4626f 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,417 @@
     // 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();
 
-    /** 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);
+    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 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();
+    }
+
+    /** @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) {
+        if (name == null) {
+            throw new IllegalArgumentException("name must not be null");
+        }
+        return nativeCreateDisplay(name);
+    }
+
+    /** @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);
     }
 
     /**
@@ -306,35 +647,141 @@
      * 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 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;
+        }
+
+        @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;
+        }
+
+        // For debugging purposes
+        @Override
+        public String toString() {
+            return "PhysicalDisplayInfo{" + width + " x " + height + ", " + refreshRate + " fps, "
+                    + "density " + density + ", " + xDpi + " x " + yDpi + " dpi}";
+        }
+    }
 
     /**
-     * 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 +794,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 +838,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..973c7f6 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -296,7 +296,7 @@
         }
         
         boolean opaque = true;
-        if ((mPrivateFlags & SKIP_DRAW) == 0) {
+        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) {
             // this view draws, remove it from the transparent region
             opaque = super.gatherTransparentRegion(region);
         } else if (region != null) {
@@ -320,7 +320,7 @@
     public void draw(Canvas canvas) {
         if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
             // draw() is not called when SKIP_DRAW is set
-            if ((mPrivateFlags & SKIP_DRAW) == 0) {
+            if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) {
                 // punch a whole in the view-hierarchy below us
                 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
             }
@@ -332,7 +332,7 @@
     protected void dispatchDraw(Canvas canvas) {
         if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
             // if SKIP_DRAW is cleared, draw() has already punched a hole
-            if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
+            if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
                 // punch a whole in the view-hierarchy below us
                 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
             }
@@ -458,9 +458,9 @@
                 if (mWindow == null) {
                     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.DEFAULT_DISPLAY, mContentInsets);
                 }
                 
                 boolean realSizeChanged;
@@ -480,10 +480,10 @@
                     relayoutResult = mSession.relayout(
                         mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
                             visible ? VISIBLE : GONE,
-                            WindowManagerImpl.RELAYOUT_DEFER_SURFACE_DESTROY,
+                            WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY,
                             mWinFrame, mContentInsets,
                             mVisibleInsets, mConfiguration, mNewSurface);
-                    if ((relayoutResult&WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) {
+                    if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
                         mReportDrawNeeded = true;
                     }
 
@@ -516,8 +516,8 @@
 
                     SurfaceHolder.Callback callbacks[] = null;
 
-                    final boolean surfaceChanged =
-                            (relayoutResult&WindowManagerImpl.RELAYOUT_RES_SURFACE_CHANGED) != 0;
+                    final boolean surfaceChanged = (relayoutResult
+                            & WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED) != 0;
                     if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) {
                         mSurfaceCreated = false;
                         if (mSurface.isValid()) {
@@ -615,21 +615,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..7e335f0 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -367,6 +367,7 @@
             if (mListener != null && !mUpdateSurface) {
                 mListener.onSurfaceTextureAvailable(mSurface, getWidth(), getHeight());
             }
+            mLayer.setLayerPaint(mLayerPaint);
         }
 
         if (mUpdateSurface) {
@@ -534,7 +535,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;
     }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f2a80d0..d93c1be1 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;
@@ -90,6 +91,7 @@
 import java.util.Arrays;
 import java.util.Locale;
 import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * <p>
@@ -343,9 +345,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 +630,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 +653,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 +662,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 +1009,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 +1040,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.
@@ -1623,17 +1569,17 @@
 
     // for mPrivateFlags:
     /** {@hide} */
-    static final int WANTS_FOCUS                    = 0x00000001;
+    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
     /** {@hide} */
-    static final int FOCUSED                        = 0x00000002;
+    static final int PFLAG_FOCUSED                     = 0x00000002;
     /** {@hide} */
-    static final int SELECTED                       = 0x00000004;
+    static final int PFLAG_SELECTED                    = 0x00000004;
     /** {@hide} */
-    static final int IS_ROOT_NAMESPACE              = 0x00000008;
+    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
     /** {@hide} */
-    static final int HAS_BOUNDS                     = 0x00000010;
+    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
     /** {@hide} */
-    static final int DRAWN                          = 0x00000020;
+    static final int PFLAG_DRAWN                       = 0x00000020;
     /**
      * When this flag is set, this view is running an animation on behalf of its
      * children and should therefore not cancel invalidate requests, even if they
@@ -1641,58 +1587,58 @@
      *
      * {@hide}
      */
-    static final int DRAW_ANIMATION                 = 0x00000040;
+    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
     /** {@hide} */
-    static final int SKIP_DRAW                      = 0x00000080;
+    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
     /** {@hide} */
-    static final int ONLY_DRAWS_BACKGROUND          = 0x00000100;
+    static final int PFLAG_ONLY_DRAWS_BACKGROUND       = 0x00000100;
     /** {@hide} */
-    static final int REQUEST_TRANSPARENT_REGIONS    = 0x00000200;
+    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
     /** {@hide} */
-    static final int DRAWABLE_STATE_DIRTY           = 0x00000400;
+    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
     /** {@hide} */
-    static final int MEASURED_DIMENSION_SET         = 0x00000800;
+    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
     /** {@hide} */
-    static final int FORCE_LAYOUT                   = 0x00001000;
+    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
     /** {@hide} */
-    static final int LAYOUT_REQUIRED                = 0x00002000;
+    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
 
-    private static final int PRESSED                = 0x00004000;
+    private static final int PFLAG_PRESSED             = 0x00004000;
 
     /** {@hide} */
-    static final int DRAWING_CACHE_VALID            = 0x00008000;
+    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
     /**
      * Flag used to indicate that this view should be drawn once more (and only once
      * more) after its animation has completed.
      * {@hide}
      */
-    static final int ANIMATION_STARTED              = 0x00010000;
+    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
 
-    private static final int SAVE_STATE_CALLED      = 0x00020000;
+    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
 
     /**
      * Indicates that the View returned true when onSetAlpha() was called and that
      * the alpha must be restored.
      * {@hide}
      */
-    static final int ALPHA_SET                      = 0x00040000;
+    static final int PFLAG_ALPHA_SET                   = 0x00040000;
 
     /**
      * Set by {@link #setScrollContainer(boolean)}.
      */
-    static final int SCROLL_CONTAINER               = 0x00080000;
+    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
 
     /**
      * Set by {@link #setScrollContainer(boolean)}.
      */
-    static final int SCROLL_CONTAINER_ADDED         = 0x00100000;
+    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
 
     /**
      * View flag indicating whether this view was invalidated (fully or partially.)
      *
      * @hide
      */
-    static final int DIRTY                          = 0x00200000;
+    static final int PFLAG_DIRTY                       = 0x00200000;
 
     /**
      * View flag indicating whether this view was invalidated by an opaque
@@ -1700,35 +1646,35 @@
      *
      * @hide
      */
-    static final int DIRTY_OPAQUE                   = 0x00400000;
+    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
 
     /**
-     * Mask for {@link #DIRTY} and {@link #DIRTY_OPAQUE}.
+     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
      *
      * @hide
      */
-    static final int DIRTY_MASK                     = 0x00600000;
+    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
 
     /**
      * Indicates whether the background is opaque.
      *
      * @hide
      */
-    static final int OPAQUE_BACKGROUND              = 0x00800000;
+    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
 
     /**
      * Indicates whether the scrollbars are opaque.
      *
      * @hide
      */
-    static final int OPAQUE_SCROLLBARS              = 0x01000000;
+    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
 
     /**
      * Indicates whether the view is opaque.
      *
      * @hide
      */
-    static final int OPAQUE_MASK                    = 0x01800000;
+    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
 
     /**
      * Indicates a prepressed state;
@@ -1738,27 +1684,27 @@
      *
      * @hide
      */
-    private static final int PREPRESSED             = 0x02000000;
+    private static final int PFLAG_PREPRESSED          = 0x02000000;
 
     /**
      * Indicates whether the view is temporarily detached.
      *
      * @hide
      */
-    static final int CANCEL_NEXT_UP_EVENT = 0x04000000;
+    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
 
     /**
      * Indicates that we should awaken scroll bars once attached
      *
      * @hide
      */
-    private static final int AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
+    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
 
     /**
      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
      * @hide
      */
-    private static final int HOVERED              = 0x10000000;
+    private static final int PFLAG_HOVERED             = 0x10000000;
 
     /**
      * Indicates that pivotX or pivotY were explicitly set and we should not assume the center
@@ -1766,10 +1712,10 @@
      *
      * @hide
      */
-    private static final int PIVOT_EXPLICITLY_SET = 0x20000000;
+    private static final int PFLAG_PIVOT_EXPLICITLY_SET = 0x20000000;
 
     /** {@hide} */
-    static final int ACTIVATED                    = 0x40000000;
+    static final int PFLAG_ACTIVATED                   = 0x40000000;
 
     /**
      * Indicates that this view was specifically invalidated, not just dirtied because some
@@ -1779,7 +1725,7 @@
      *
      * @hide
      */
-    static final int INVALIDATED                  = 0x80000000;
+    static final int PFLAG_INVALIDATED                 = 0x80000000;
 
     /* Masks for mPrivateFlags2 */
 
@@ -1788,7 +1734,7 @@
      * Cleared when the drag operation concludes.
      * @hide
      */
-    static final int DRAG_CAN_ACCEPT              = 0x00000001;
+    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
 
     /**
      * Indicates that this view is currently directly under the drag location in a
@@ -1796,33 +1742,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 +1772,33 @@
      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
      * @hide
      */
-    static final int LAYOUT_DIRECTION_MASK_SHIFT = 2;
+    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
 
     /**
      * Mask for use with private flags indicating bits used for horizontal layout direction.
      * @hide
      */
-    static final int LAYOUT_DIRECTION_MASK = 0x00000003 << LAYOUT_DIRECTION_MASK_SHIFT;
+    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
 
     /**
      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
      * right-to-left direction.
      * @hide
      */
-    static final int LAYOUT_DIRECTION_RESOLVED_RTL = 4 << LAYOUT_DIRECTION_MASK_SHIFT;
+    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
 
     /**
      * Indicates whether the view horizontal layout direction has been resolved.
      * @hide
      */
-    static final int LAYOUT_DIRECTION_RESOLVED = 8 << LAYOUT_DIRECTION_MASK_SHIFT;
+    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
 
     /**
      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
      * @hide
      */
-    static final int LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C << LAYOUT_DIRECTION_MASK_SHIFT;
+    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
+            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
 
     /*
      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
@@ -1882,12 +1825,11 @@
      *
      * @hide
      */
-    static final int HAS_TRANSIENT_STATE = 0x00000100;
+    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x00000100;
 
 
     /**
      * Text direction is inherited thru {@link ViewGroup}
-     * @hide
      */
     public static final int TEXT_DIRECTION_INHERIT = 0;
 
@@ -1895,7 +1837,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 +1844,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;
+    public static int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
 
     /**
      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
      * @hide
      */
-    static final int TEXT_DIRECTION_MASK_SHIFT = 6;
+    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
 
     /**
      * Mask for use with private flags indicating bits used for text direction.
      * @hide
      */
-    static final int TEXT_DIRECTION_MASK = 0x00000007 << TEXT_DIRECTION_MASK_SHIFT;
+    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
+            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
 
     /**
      * Array of text direction flags for mapping attribute "textDirection" to correct
      * flag value.
      * @hide
      */
-    private static final int[] TEXT_DIRECTION_FLAGS = {
-            TEXT_DIRECTION_INHERIT << TEXT_DIRECTION_MASK_SHIFT,
-            TEXT_DIRECTION_FIRST_STRONG << TEXT_DIRECTION_MASK_SHIFT,
-            TEXT_DIRECTION_ANY_RTL << TEXT_DIRECTION_MASK_SHIFT,
-            TEXT_DIRECTION_LTR << TEXT_DIRECTION_MASK_SHIFT,
-            TEXT_DIRECTION_RTL << TEXT_DIRECTION_MASK_SHIFT,
-            TEXT_DIRECTION_LOCALE << TEXT_DIRECTION_MASK_SHIFT
+    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
+            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
+            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
+            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
+            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
+            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
+            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
     };
 
     /**
      * Indicates whether the view text direction has been resolved.
      * @hide
      */
-    static final int TEXT_DIRECTION_RESOLVED = 0x00000008 << TEXT_DIRECTION_MASK_SHIFT;
+    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
+            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
 
     /**
      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
      * @hide
      */
-    static final int TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
+    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
 
     /**
      * Mask for use with private flags indicating bits used for resolved text direction.
      * @hide
      */
-    static final int TEXT_DIRECTION_RESOLVED_MASK = 0x00000007 << TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
+    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
+            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
 
     /**
      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
      * @hide
      */
-    static final int TEXT_DIRECTION_RESOLVED_DEFAULT =
-            TEXT_DIRECTION_FIRST_STRONG << TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
+    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
+            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
 
     /*
      * Default text alignment. The text alignment of this View is inherited from its parent.
      * Use with {@link #setTextAlignment(int)}
-     * @hide
      */
     public static final int TEXT_ALIGNMENT_INHERIT = 0;
 
@@ -1994,7 +1932,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 +1939,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 +1946,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 +1953,6 @@
      * Center the paragraph, e.g. ALIGN_CENTER.
      *
      * Use with {@link #setTextAlignment(int)}
-     * @hide
      */
     public static final int TEXT_ALIGNMENT_CENTER = 4;
 
@@ -2027,7 +1961,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 +1969,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;
+    public static int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
 
     /**
       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
       * @hide
       */
-    static final int TEXT_ALIGNMENT_MASK_SHIFT = 13;
+    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
 
     /**
       * Mask for use with private flags indicating bits used for text alignment.
       * @hide
       */
-    static final int TEXT_ALIGNMENT_MASK = 0x00000007 << TEXT_ALIGNMENT_MASK_SHIFT;
+    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
 
     /**
      * Array of text direction flags for mapping attribute "textAlignment" to correct
      * flag value.
      * @hide
      */
-    private static final int[] TEXT_ALIGNMENT_FLAGS = {
-            TEXT_ALIGNMENT_INHERIT << TEXT_ALIGNMENT_MASK_SHIFT,
-            TEXT_ALIGNMENT_GRAVITY << TEXT_ALIGNMENT_MASK_SHIFT,
-            TEXT_ALIGNMENT_TEXT_START << TEXT_ALIGNMENT_MASK_SHIFT,
-            TEXT_ALIGNMENT_TEXT_END << TEXT_ALIGNMENT_MASK_SHIFT,
-            TEXT_ALIGNMENT_CENTER << TEXT_ALIGNMENT_MASK_SHIFT,
-            TEXT_ALIGNMENT_VIEW_START << TEXT_ALIGNMENT_MASK_SHIFT,
-            TEXT_ALIGNMENT_VIEW_END << TEXT_ALIGNMENT_MASK_SHIFT
+    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
+            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
     };
 
     /**
      * Indicates whether the view text alignment has been resolved.
      * @hide
      */
-    static final int TEXT_ALIGNMENT_RESOLVED = 0x00000008 << TEXT_ALIGNMENT_MASK_SHIFT;
+    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
 
     /**
      * Bit shift to get the resolved text alignment.
      * @hide
      */
-    static final int TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
+    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
 
     /**
      * Mask for use with private flags indicating bits used for text alignment.
      * @hide
      */
-    static final int TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007 << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
+    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
+            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
 
     /**
      * Indicates whether if the view text alignment has been resolved to gravity
      */
-    public static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT =
-            TEXT_ALIGNMENT_GRAVITY << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
+    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
+            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
 
     // Accessiblity constants for mPrivateFlags2
 
@@ -2103,7 +2035,7 @@
      * Shift for the bits in {@link #mPrivateFlags2} related to the
      * "importantForAccessibility" attribute.
      */
-    static final int IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
+    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
 
     /**
      * Automatically determine whether a view is important for accessibility.
@@ -2129,92 +2061,38 @@
      * 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
-     */
-    public static final int ACCESSIBILITY_FOCUSABLE_AUTO = 0x00000000;
-
-    /**
-     * 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
-     */
-    public static final int ACCESSIBILITY_FOCUSABLE_YES = 0x00000001;
-
-    /**
-     * 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 +2103,19 @@
      * an animation is cleared between successive frames, in order to tell the associated
      * DisplayList to clear its animation matrix.
      */
-    static final int VIEW_IS_ANIMATING_TRANSFORM = 0x1;
+    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
 
     /**
      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
      * animation is cleared between successive frames, in order to tell the associated
      * DisplayList to restore its alpha value.
      */
-    static final int VIEW_IS_ANIMATING_ALPHA = 0x2;
+    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
 
 
     /* End of masks for mPrivateFlags3 */
 
-    static final int DRAG_MASK = DRAG_CAN_ACCEPT | DRAG_HOVERED;
+    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
 
     /**
      * Always allow a user to over-scroll this view, provided it is a
@@ -2604,16 +2482,16 @@
      * {@hide}
      */
     @ViewDebug.ExportedProperty(flagMapping = {
-        @ViewDebug.FlagToString(mask = FORCE_LAYOUT, equals = FORCE_LAYOUT,
+        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
                 name = "FORCE_LAYOUT"),
-        @ViewDebug.FlagToString(mask = LAYOUT_REQUIRED, equals = LAYOUT_REQUIRED,
+        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
                 name = "LAYOUT_REQUIRED"),
-        @ViewDebug.FlagToString(mask = DRAWING_CACHE_VALID, equals = DRAWING_CACHE_VALID,
+        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
             name = "DRAWING_CACHE_INVALID", outputIf = false),
-        @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "DRAWN", outputIf = true),
-        @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "NOT_DRAWN", outputIf = false),
-        @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
-        @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY, name = "DIRTY")
+        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
+        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
+        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
+        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
     })
     int mPrivateFlags;
     int mPrivateFlags2;
@@ -2881,6 +2759,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 +2800,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 +2814,25 @@
     int mUserPaddingEnd;
 
     /**
+     * Whether a left padding has been defined during layout inflation.
+     *
+     * @hide
+     */
+    boolean mUserPaddingLeftDefined = false;
+
+    /**
+     * Whether a right padding has been defined during layout inflation.
+     *
+     * @hide
+     */
+    boolean mUserPaddingRightDefined = false;
+
+    /**
+     * Default undefined padding
+     */
+    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
+
+    /**
      * @hide
      */
     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
@@ -3218,29 +3125,6 @@
     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.
      */
     AccessibilityDelegate mAccessibilityDelegate;
@@ -3253,6 +3137,29 @@
             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 layout and text direction defaults
+        mPrivateFlags2 = (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
+                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
+                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
+                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
+        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
+        mUserPaddingStart = UNDEFINED_PADDING;
+        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 +3210,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 +3233,11 @@
         boolean transformSet = false;
 
         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
-
         int overScrollMode = mOverScrollMode;
+        boolean initializeScrollbars = 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 +3247,28 @@
                     break;
                 case com.android.internal.R.styleable.View_padding:
                     padding = a.getDimensionPixelSize(attr, -1);
+                    mUserPaddingLeftDefined = true;
+                    mUserPaddingRightDefined = true;
                     break;
                  case com.android.internal.R.styleable.View_paddingLeft:
                     leftPadding = a.getDimensionPixelSize(attr, -1);
+                    mUserPaddingLeftDefined = 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);
+                    mUserPaddingRightDefined = 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);
                     break;
                 case com.android.internal.R.styleable.View_paddingEnd:
-                    endPadding = a.getDimensionPixelSize(attr, -1);
+                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
                     break;
                 case com.android.internal.R.styleable.View_scrollX:
                     x = a.getDimensionPixelOffset(attr, 0);
@@ -3456,12 +3370,12 @@
                     break;
                 case com.android.internal.R.styleable.View_layoutDirection:
                     // Clear any layout direction flags (included resolved bits) already set
-                    mPrivateFlags2 &= ~(LAYOUT_DIRECTION_MASK | LAYOUT_DIRECTION_RESOLVED_MASK);
+                    mPrivateFlags2 &= ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
                     // Set the layout direction flags depending on the value of the attribute
                     final int layoutDirection = a.getInt(attr, -1);
                     final int value = (layoutDirection != -1) ?
                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
-                    mPrivateFlags2 |= (value << LAYOUT_DIRECTION_MASK_SHIFT);
+                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
                     break;
                 case com.android.internal.R.styleable.View_drawingCacheQuality:
                     final int cacheQuality = a.getInt(attr, 0);
@@ -3473,6 +3387,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 +3407,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 +3523,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,21 +3544,18 @@
             }
         }
 
-        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;
@@ -3653,7 +3567,7 @@
         // 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,
+        internalSetPadding(leftPadding >= 0 ? leftPadding : mPaddingLeft,
                 topPadding >= 0 ? topPadding : mPaddingTop,
                 rightPadding >= 0 ? rightPadding : mPaddingRight,
                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
@@ -3662,6 +3576,12 @@
             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 +3608,6 @@
         computeOpaqueFlags();
     }
 
-    private void updateUserPaddingRelative() {
-        mUserPaddingRelative = (mUserPaddingStart >= 0 || mUserPaddingEnd >= 0);
-    }
-
     /**
      * Non-public constructor for use in testing
      */
@@ -3699,6 +3615,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 +3872,15 @@
             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
         }
 
+        // Apply layout direction to the new Drawables if needed
+        final int layoutDirection = getResolvedLayoutDirection();
+        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 +4247,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 +4294,42 @@
      * @return Whether any parent scrolled.
      */
     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
+        if (mAttachInfo == null) {
+            return false;
+        }
+
         View child = this;
+
+        RectF position = mAttachInfo.mTmpTransformRect;
+        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 +4349,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 +4384,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 +4404,7 @@
      */
     @ViewDebug.ExportedProperty(category = "focus")
     public boolean hasFocus() {
-        return (mPrivateFlags & FOCUSED) != 0;
+        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
     }
 
     /**
@@ -4502,11 +4519,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);
         }
     }
 
@@ -4826,6 +4845,7 @@
      */
     void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         Rect bounds = mAttachInfo.mTmpInvalRect;
+
         getDrawingRect(bounds);
         info.setBoundsInParent(bounds);
 
@@ -4837,6 +4857,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());
@@ -4866,10 +4908,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 +4930,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 +4952,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,22 +4969,38 @@
      * @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 (mAttachInfo != null) {
+            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.mWindowVisibility == View.VISIBLE
+                && getAlpha() > 0
+                && isShown()
+                && getGlobalVisibleRect(visibleRect, offset);
             if (isVisible && boundInView != null) {
                 visibleRect.offset(-offset.x, -offset.y);
-                isVisible &= boundInView.intersect(visibleRect);
+                // isVisible is always true here, use a simple assignment
+                isVisible = boundInView.intersect(visibleRect);
             }
             return isVisible;
+        }
+
+        return false;
+    }
+
+    /**
+     * 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;
     }
 
     /**
@@ -5069,6 +5109,32 @@
     }
 
     /**
+     * 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();
+        }
+    }
+
+    /**
      * Invoked whenever this view loses focus, either by losing window focus or by losing
      * focus within its window. This method can be used to clear any state tied to the
      * focus. For instance, if a button is held pressed with the trackball and the window
@@ -5106,7 +5172,7 @@
      */
     @ViewDebug.ExportedProperty(category = "focus")
     public boolean isFocused() {
-        return (mPrivateFlags & FOCUSED) != 0;
+        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
     }
 
     /**
@@ -5117,7 +5183,7 @@
      *         be found.
      */
     public View findFocus() {
-        return (mPrivateFlags & FOCUSED) != 0 ? this : null;
+        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
     }
 
     /**
@@ -5130,7 +5196,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 +5210,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 +5469,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,9 +5717,7 @@
      *   {@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 = {
         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
@@ -5663,7 +5726,7 @@
         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
     })
     public int getLayoutDirection() {
-        return (mPrivateFlags2 & LAYOUT_DIRECTION_MASK) >> LAYOUT_DIRECTION_MASK_SHIFT;
+        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
     }
 
     /**
@@ -5676,17 +5739,20 @@
      *   {@link #LAYOUT_DIRECTION_LOCALE}.
      *
      * @attr ref android.R.styleable#View_layoutDirection
-     * @hide
      */
     @RemotableViewMethod
     public void setLayoutDirection(int layoutDirection) {
         if (getLayoutDirection() != layoutDirection) {
             // Reset the current layout direction and the resolved one
-            mPrivateFlags2 &= ~LAYOUT_DIRECTION_MASK;
+            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
             resetResolvedLayoutDirection();
-            // Set the new layout direction (filtered) and ask for a layout pass
+            // Reset padding resolution
+            mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
+            // Set the new layout direction (filtered)
             mPrivateFlags2 |=
-                    ((layoutDirection << LAYOUT_DIRECTION_MASK_SHIFT) & LAYOUT_DIRECTION_MASK);
+                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
+            resolveRtlProperties();
+            // ... and ask for a layout pass
             requestLayout();
         }
     }
@@ -5696,18 +5762,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
      */
     @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) {
+        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
+        if (targetSdkVersion < JELLY_BEAN_MR1) {
+            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
+            return LAYOUT_DIRECTION_LTR;
+        }
+        // The layout direction will be resolved only if needed
+        if ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) != PFLAG2_LAYOUT_DIRECTION_RESOLVED) {
             resolveLayoutDirection();
         }
-        return ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED_RTL) == LAYOUT_DIRECTION_RESOLVED_RTL) ?
+        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) == PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ?
                 LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
     }
 
@@ -5716,7 +5786,6 @@
      * 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() {
@@ -5737,7 +5806,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 +5833,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 +5957,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 +5993,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 +6186,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 +6243,6 @@
         if (views == null) {
             return;
         }
-        if ((focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
-            if (isAccessibilityFocusable()) {
-                views.add(this);
-                return;
-            }
-        }
         if (!isFocusable()) {
             return;
         }
@@ -6257,7 +6317,7 @@
      * @return True if this View is accessibility focused.
      */
     boolean isAccessibilityFocused() {
-        return (mPrivateFlags2 & ACCESSIBILITY_FOCUSED) != 0;
+        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
     }
 
     /**
@@ -6282,12 +6342,17 @@
         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);
             }
+            if (mAttachInfo != null) {
+                Rect rectangle = mAttachInfo.mTmpInvalRect;
+                getDrawingRect(rectangle);
+                requestRectangleOnScreen(rectangle);
+            }
             invalidate();
             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
             notifyAccessibilityStateChanged();
@@ -6305,8 +6370,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 +6412,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 +6419,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 +6577,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 +6596,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 +6611,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 +6628,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 +6672,7 @@
      */
     public boolean includeForAccessibility() {
         if (mAttachInfo != null) {
-            if (!mAttachInfo.mIncludeNotImportantViews) {
-                return isImportantForAccessibility();
-            }
-            return true;
+            return mAttachInfo.mIncludeNotImportantViews || isImportantForAccessibility();
         }
         return false;
     }
@@ -6748,8 +6721,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);
             }
@@ -6763,7 +6736,7 @@
      * @hide
      */
     public void resetAccessibilityStateChanged() {
-        mPrivateFlags2 &= ~ACCESSIBILITY_STATE_CHANGED;
+        mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_STATE_CHANGED;
     }
 
     /**
@@ -6832,10 +6805,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 +6899,7 @@
      * @hide
      */
     public CharSequence getIterableTextForAccessibility() {
-        return mContentDescription;
+        return getContentDescription();
     }
 
     /**
@@ -7018,7 +6988,7 @@
      */
     public void onStartTemporaryDetach() {
         removeUnsetPressCallback();
-        mPrivateFlags |= CANCEL_NEXT_UP_EVENT;
+        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
     }
 
     /**
@@ -7337,13 +7307,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 +7353,7 @@
             if (mAttachInfo != null) {
                 initialAwakenScrollBars();
             } else {
-                mPrivateFlags |= AWAKEN_SCROLL_BARS_ON_ATTACH;
+                mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
             }
         }
     }
@@ -7484,7 +7454,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 +7509,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 +7955,7 @@
      */
     @ViewDebug.ExportedProperty
     public boolean isHovered() {
-        return (mPrivateFlags & HOVERED) != 0;
+        return (mPrivateFlags & PFLAG_HOVERED) != 0;
     }
 
     /**
@@ -8003,14 +7975,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 +8014,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 +8033,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 +8096,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();
                         }
@@ -8149,7 +8121,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 +8172,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 +8183,7 @@
      */
     private void removeTapCallback() {
         if (mPendingCheckForTap != null) {
-            mPrivateFlags &= ~PREPRESSED;
+            mPrivateFlags &= ~PFLAG_PREPRESSED;
             removeCallbacks(mPendingCheckForTap);
         }
     }
@@ -8276,13 +8248,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 +8273,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 +8303,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 +8317,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 +8348,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);
@@ -8702,7 +8674,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;
@@ -8846,7 +8818,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 +8864,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 +8915,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 +8966,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 +9009,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 +9052,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 +9093,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 +9103,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 +9143,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 +9153,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 +9213,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 +9243,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 +9306,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 +9338,7 @@
      * @return The dirty state of this view.
      */
     public boolean isDirty() {
-        return (mPrivateFlags & DIRTY_MASK) != 0;
+        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
     }
 
     /**
@@ -9407,16 +9379,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 +9446,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 +9510,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 +9607,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 +9648,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();
             }
@@ -9910,6 +9882,7 @@
             throw new NullPointerException("Layout parameters cannot be null");
         }
         mLayoutParams = params;
+        resolveLayoutParams();
         if (mParent instanceof ViewGroup) {
             ((ViewGroup) mParent).onSetLayoutParams(this, params);
         }
@@ -9917,6 +9890,15 @@
     }
 
     /**
+     * Resolve the layout parameters depending on the resolved layout direction
+     */
+    private void resolveLayoutParams() {
+        if (mLayoutParams != null) {
+            mLayoutParams.onResolveLayoutDirection(getResolvedLayoutDirection());
+        }
+    }
+
+    /**
      * 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 +10119,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 +10162,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 +10214,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 +10263,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 +10312,7 @@
      */
     protected void invalidateParentCaches() {
         if (mParent instanceof View) {
-            ((View) mParent).mPrivateFlags |= INVALIDATED;
+            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
         }
     }
 
@@ -10362,9 +10344,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 +10358,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 +10376,7 @@
      * @hide
      */
     protected boolean hasOpaqueScrollbars() {
-        return (mPrivateFlags & OPAQUE_SCROLLBARS) == OPAQUE_SCROLLBARS;
+        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
     }
 
     /**
@@ -10923,7 +10904,7 @@
      * @hide
      */
     protected void recomputePadding() {
-        setPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
+        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
     }
 
     /**
@@ -11331,9 +11312,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,23 +11421,18 @@
      * @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();
+        resolveRtlProperties();
 
         clearAccessibilityFocus();
         if (isFocused()) {
@@ -11465,6 +11445,17 @@
         }
     }
 
+    void resolveRtlProperties() {
+        // Order is important here: LayoutDirection MUST be resolved first...
+        resolveLayoutDirection();
+        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
+        resolvePadding();
+        resolveLayoutParams();
+        resolveTextDirection();
+        resolveTextAlignment();
+        resolveDrawables();
+    }
+
     /**
      * @see #onScreenStateChanged(int)
      */
@@ -11495,33 +11486,35 @@
      * 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.
-     * @hide
      */
     public void resolveLayoutDirection() {
         // Clear any previous layout direction resolution
-        mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED_MASK;
+        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
 
         if (hasRtlSupport()) {
             // Set resolved depending on layout direction
             switch (getLayoutDirection()) {
                 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;
 
-                        if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
-                            mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
-                        }
-                    } else {
-                        // Nothing to do, LTR by default
+                    ViewGroup viewGroup = ((ViewGroup) mParent);
+
+                    // We cannot resolve yet on the parent too. LTR is by default and let the
+                    // resolution happen again later
+                    if (!viewGroup.canResolveLayoutDirection()) return;
+
+                    if (viewGroup.getResolvedLayoutDirection() == 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;
+                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
                     }
                     break;
                 default:
@@ -11530,72 +11523,79 @@
         }
 
         // Set to resolved
-        mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED;
+        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
         onResolvedLayoutDirectionChanged();
-        // Resolve padding
-        resolvePadding();
     }
 
     /**
      * Called when layout direction has been resolved.
      *
      * The default implementation does nothing.
-     * @hide
      */
     public void onResolvedLayoutDirectionChanged() {
     }
 
     /**
+     * Return if padding has been resolved
+     */
+    boolean isPaddingResolved() {
+        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) != 0;
+    }
+
+    /**
      * 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;
-                }
-        }
+        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
+        if (targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport()) {
+            // Pre Jelly Bean MR1 case (compatibility mode) OR no RTL support case:
+            // left / right padding are used if defined. 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).
+            if (!mUserPaddingLeftDefined && mUserPaddingStart != UNDEFINED_PADDING) {
+                mUserPaddingLeft = mUserPaddingStart;
+            }
+            if (!mUserPaddingRightDefined && mUserPaddingEnd != UNDEFINED_PADDING) {
+                mUserPaddingRight = mUserPaddingEnd;
+            }
 
-        mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
+            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
 
-        if(isPaddingRelative()) {
-            setPaddingRelative(mUserPaddingStart, mPaddingTop, mUserPaddingEnd, mUserPaddingBottom);
+            internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
+                    mUserPaddingBottom);
         } else {
-            recomputePadding();
+            // 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 = getResolvedLayoutDirection();
+            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);
+            onPaddingChanged(resolvedLayoutDirection);
         }
-        onPaddingChanged(resolvedLayoutDirection);
+
+        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
     }
 
     /**
@@ -11607,7 +11607,6 @@
      *
      * @see {@link #LAYOUT_DIRECTION_LTR}
      * @see {@link #LAYOUT_DIRECTION_RTL}
-     * @hide
      */
     public void onPaddingChanged(int layoutDirection) {
     }
@@ -11616,7 +11615,6 @@
      * 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()) {
@@ -11630,11 +11628,10 @@
     /**
      * Reset the resolved layout direction. Will call {@link View#onResolvedLayoutDirectionReset}
      * when reset is done.
-     * @hide
      */
     public void resetResolvedLayoutDirection() {
         // Reset the current resolved bits
-        mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED_MASK;
+        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
         onResolvedLayoutDirectionReset();
         // Reset also the text direction
         resetResolvedTextDirection();
@@ -11647,7 +11644,6 @@
      * resolved layout direction, or to inform child views that inherit their layout direction.
      *
      * The default implementation does nothing.
-     * @hide
      */
     public void onResolvedLayoutDirectionReset() {
     }
@@ -11657,7 +11653,6 @@
      *
      * @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));
@@ -11670,7 +11665,7 @@
      * @see #onAttachedToWindow()
      */
     protected void onDetachedFromWindow() {
-        mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
+        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
 
         removeUnsetPressCallback();
         removeLongPressCallback();
@@ -11696,6 +11691,7 @@
         resetResolvedLayoutDirection();
         resetResolvedTextAlignment();
         resetAccessibilityStateChanged();
+        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
     }
 
     /**
@@ -11737,6 +11733,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 +11759,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 +11788,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 +11819,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 +11853,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 +11889,7 @@
      * @see #setSaveEnabled(boolean)
      */
     protected Parcelable onSaveInstanceState() {
-        mPrivateFlags |= SAVE_STATE_CALLED;
+        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
         return BaseSavedState.EMPTY_STATE;
     }
 
@@ -11918,9 +11924,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 +11947,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 +12022,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 +12080,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 +12185,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,20 +12206,37 @@
             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
             if (!mHardwareLayer.isValid()) {
                 return null;
             }
+            mHardwareLayer.setLayerPaint(mLayerPaint);
 
             mHardwareLayer.redraw(getHardwareLayerDisplayList(mHardwareLayer), mLocalDirtyRect);
             mLocalDirtyRect.setEmpty();
@@ -12278,10 +12338,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 +12405,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 +12442,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 +12468,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 +12491,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 +12614,7 @@
     public void setDrawingCacheBackgroundColor(int color) {
         if (color != mDrawingCacheBackgroundColor) {
             mDrawingCacheBackgroundColor = color;
-            mPrivateFlags &= ~DRAWING_CACHE_VALID;
+            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
         }
     }
 
@@ -12602,7 +12660,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 +12679,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 int projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
+            final int 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 +12725,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 +12781,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 +12818,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 +12857,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 +13044,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 +13063,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 +13125,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 +13156,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 +13173,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 +13200,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 +13265,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 +13300,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 +13340,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 +13365,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 +13418,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 +13470,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 +13492,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 +13749,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 +13762,7 @@
             numFlags++;
         }
 
-        if ((privateFlags & SELECTED) == SELECTED) {
+        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
             if (numFlags > 0) {
                 output += " ";
             }
@@ -13699,7 +13770,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 +13778,7 @@
             numFlags++;
         }
 
-        if ((privateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
+        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
             if (numFlags > 0) {
                 output += " ";
             }
@@ -13715,7 +13786,7 @@
             numFlags++;
         }
 
-        if ((privateFlags & DRAWN) == DRAWN) {
+        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
             if (numFlags > 0) {
                 output += " ";
             }
@@ -13732,7 +13803,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 +13833,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 +13847,7 @@
                 }
             }
         }
-        mPrivateFlags &= ~FORCE_LAYOUT;
+        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
     }
 
     /**
@@ -13820,7 +13891,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 +13910,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 +13929,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 +14034,29 @@
     }
 
     /**
-    * 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.
+     */
+    public void resolveDrawables() {
+        if (mBackground != null) {
+            mBackground.setLayoutDirection(getResolvedLayoutDirection());
+        }
+        onResolveDrawables(getResolvedLayoutDirection());
+    }
+
+    /**
+     * Called when layout direction has been resolved.
+     *
+     * The default implementation does nothing.
+     *
+     * @param layoutDirection The resolved layout direction.
+     *
+     * @see {@link #LAYOUT_DIRECTION_LTR}
+     * @see {@link #LAYOUT_DIRECTION_RTL}
+     */
+    public void onResolveDrawables(int layoutDirection) {
     }
 
     /**
@@ -14020,7 +14107,7 @@
      * @see #getDrawableState
      */
     public void refreshDrawableState() {
-        mPrivateFlags |= DRAWABLE_STATE_DIRTY;
+        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
         drawableStateChanged();
 
         ViewParent parent = mParent;
@@ -14040,11 +14127,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 +14162,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 +14175,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 +14187,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 +14254,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 +14303,8 @@
      */
     @Deprecated
     public void setBackgroundDrawable(Drawable background) {
+        computeOpaqueFlags();
+
         if (background == mBackground) {
             return;
         }
@@ -14238,14 +14328,17 @@
                 padding = new Rect();
                 sThreadLocal.set(padding);
             }
+            background.setLayoutDirection(getResolvedLayoutDirection());
             if (background.getPadding(padding)) {
-                switch (background.getResolvedLayoutDirectionSelf()) {
+                // Reset padding resolution
+                mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
+                switch (background.getLayoutDirection()) {
                     case LAYOUT_DIRECTION_RTL:
-                        setPadding(padding.right, padding.top, padding.left, padding.bottom);
+                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
                         break;
                     case LAYOUT_DIRECTION_LTR:
                     default:
-                        setPadding(padding.left, padding.top, padding.right, padding.bottom);
+                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
                 }
             }
 
@@ -14263,23 +14356,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 +14428,19 @@
      * @param bottom the bottom padding in pixels
      */
     public void setPadding(int left, int top, int right, int bottom) {
-        mUserPaddingStart = -1;
-        mUserPaddingEnd = -1;
-        mUserPaddingRelative = false;
+        // Reset padding resolution
+        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
+
+        mUserPaddingStart = UNDEFINED_PADDING;
+        mUserPaddingEnd = UNDEFINED_PADDING;
 
         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 +14455,7 @@
                         ? 0 : getVerticalScrollbarWidth();
                 switch (mVerticalScrollbarPosition) {
                     case SCROLLBAR_POSITION_DEFAULT:
-                        if (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
+                        if (isLayoutRtl()) {
                             left += offset;
                         } else {
                             right += offset;
@@ -14402,18 +14500,26 @@
     /**
      * 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) {
+        // Reset padding resolution
+        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
+
         mUserPaddingStart = start;
         mUserPaddingEnd = end;
-        mUserPaddingRelative = true;
 
         switch(getResolvedLayoutDirection()) {
             case LAYOUT_DIRECTION_RTL:
@@ -14453,6 +14559,9 @@
      * @return the left padding in pixels
      */
     public int getPaddingLeft() {
+        if (!isPaddingResolved()) {
+            resolvePadding();
+        }
         return mPaddingLeft;
     }
 
@@ -14462,9 +14571,11 @@
      * required to display the scrollbars as well.
      *
      * @return the start padding in pixels
-     * @hide
      */
     public int getPaddingStart() {
+        if (!isPaddingResolved()) {
+            resolvePadding();
+        }
         return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
                 mPaddingRight : mPaddingLeft;
     }
@@ -14477,6 +14588,9 @@
      * @return the right padding in pixels
      */
     public int getPaddingRight() {
+        if (!isPaddingResolved()) {
+            resolvePadding();
+        }
         return mPaddingRight;
     }
 
@@ -14486,22 +14600,25 @@
      * required to display the scrollbars as well.
      *
      * @return the end padding in pixels
-     * @hide
      */
     public int getPaddingEnd() {
+        if (!isPaddingResolved()) {
+            resolvePadding();
+        }
         return (getResolvedLayoutDirection() == 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);
     }
 
     /**
@@ -14530,8 +14647,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 +14676,7 @@
      */
     @ViewDebug.ExportedProperty
     public boolean isSelected() {
-        return (mPrivateFlags & SELECTED) != 0;
+        return (mPrivateFlags & PFLAG_SELECTED) != 0;
     }
 
     /**
@@ -14576,8 +14693,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 +14718,7 @@
      */
     @ViewDebug.ExportedProperty
     public boolean isActivated() {
-        return (mPrivateFlags & ACTIVATED) != 0;
+        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
     }
 
     /**
@@ -14879,6 +14996,9 @@
      */
     public void setId(int id) {
         mID = id;
+        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
+            mID = generateViewId();
+        }
     }
 
     /**
@@ -14889,9 +15009,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 +15021,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 +15170,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 +15250,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 +15264,8 @@
      * on the parent.
      */
     public void forceLayout() {
-        mPrivateFlags |= FORCE_LAYOUT;
-        mPrivateFlags |= INVALIDATED;
+        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
+        mPrivateFlags |= PFLAG_INVALIDATED;
     }
 
     /**
@@ -15173,25 +15289,29 @@
      * @see #onMeasure(int, int)
      */
     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
-        if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||
+        if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
                 widthMeasureSpec != mOldWidthMeasureSpec ||
                 heightMeasureSpec != mOldHeightMeasureSpec) {
 
             // first clears the measured dimension flag
-            mPrivateFlags &= ~MEASURED_DIMENSION_SET;
+            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
+
+            if (!isPaddingResolved()) {
+                resolvePadding();
+            }
 
             // 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 +15385,7 @@
         mMeasuredWidth = measuredWidth;
         mMeasuredHeight = measuredHeight;
 
-        mPrivateFlags |= MEASURED_DIMENSION_SET;
+        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
     }
 
     /**
@@ -15509,7 +15629,7 @@
      * @see #getAnimation()
      */
     protected void onAnimationStart() {
-        mPrivateFlags |= ANIMATION_STARTED;
+        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
     }
 
     /**
@@ -15521,7 +15641,7 @@
      * @see #getAnimation()
      */
     protected void onAnimationEnd() {
-        mPrivateFlags &= ~ANIMATION_STARTED;
+        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
     }
 
     /**
@@ -15558,14 +15678,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 +16162,7 @@
     }
 
     boolean canAcceptDrag() {
-        return (mPrivateFlags2 & DRAG_CAN_ACCEPT) != 0;
+        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
     }
 
     /**
@@ -16297,7 +16417,6 @@
      * {@link #TEXT_DIRECTION_LTR},
      * {@link #TEXT_DIRECTION_RTL},
      * {@link #TEXT_DIRECTION_LOCALE}
-     * @hide
      */
     @ViewDebug.ExportedProperty(category = "text", mapping = {
             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
@@ -16308,7 +16427,7 @@
             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
     })
     public int getTextDirection() {
-        return (mPrivateFlags2 & TEXT_DIRECTION_MASK) >> TEXT_DIRECTION_MASK_SHIFT;
+        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
     }
 
     /**
@@ -16322,15 +16441,14 @@
      * {@link #TEXT_DIRECTION_LTR},
      * {@link #TEXT_DIRECTION_RTL},
      * {@link #TEXT_DIRECTION_LOCALE}
-     * @hide
      */
     public void setTextDirection(int textDirection) {
         if (getTextDirection() != textDirection) {
             // Reset the current text direction and the resolved one
-            mPrivateFlags2 &= ~TEXT_DIRECTION_MASK;
+            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
             resetResolvedTextDirection();
             // Set the new text direction
-            mPrivateFlags2 |= ((textDirection << TEXT_DIRECTION_MASK_SHIFT) & TEXT_DIRECTION_MASK);
+            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
             // Refresh
             requestLayout();
             invalidate(true);
@@ -16352,24 +16470,22 @@
      * {@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) {
+        if ((mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) != PFLAG2_TEXT_DIRECTION_RESOLVED) {
             resolveTextDirection();
         }
-        return (mPrivateFlags2 & TEXT_DIRECTION_RESOLVED_MASK) >> TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
+        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
     }
 
     /**
      * Resolve the text direction. Will call {@link View#onResolvedTextDirectionChanged} when
      * resolution is done.
-     * @hide
      */
     public void resolveTextDirection() {
         // Reset any previous text direction resolution
-        mPrivateFlags2 &= ~(TEXT_DIRECTION_RESOLVED | TEXT_DIRECTION_RESOLVED_MASK);
+        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
 
         if (hasRtlSupport()) {
             // Set resolved text direction flag depending on text direction flag
@@ -16388,15 +16504,15 @@
                             case TEXT_DIRECTION_RTL:
                             case TEXT_DIRECTION_LOCALE:
                                 mPrivateFlags2 |=
-                                        (parentResolvedDirection << TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
+                                        (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
                                 break;
                             default:
                                 // Default resolved direction is "first strong" heuristic
-                                mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
+                                mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
                         }
                     } else {
                         // We cannot do the resolution if there is no parent, so use the default one
-                        mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
+                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
                     }
                     break;
                 case TEXT_DIRECTION_FIRST_STRONG:
@@ -16405,19 +16521,19 @@
                 case TEXT_DIRECTION_RTL:
                 case TEXT_DIRECTION_LOCALE:
                     // Resolved direction is the same as text direction
-                    mPrivateFlags2 |= (textDirection << TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
+                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
                     break;
                 default:
                     // Default resolved direction is "first strong" heuristic
-                    mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
+                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
             }
         } else {
             // Default resolved direction is "first strong" heuristic
-            mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
+            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
         }
 
         // Set to resolved
-        mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED;
+        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
         onResolvedTextDirectionChanged();
     }
 
@@ -16426,7 +16542,6 @@
      * resolution should override this method.
      *
      * The default implementation does nothing.
-     * @hide
      */
     public void onResolvedTextDirectionChanged() {
     }
@@ -16435,7 +16550,6 @@
      * 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()) {
@@ -16450,10 +16564,9 @@
      * Reset resolved text direction. Text direction can be resolved with a call to
      * getResolvedTextDirection(). Will call {@link View#onResolvedTextDirectionReset} when
      * reset is done.
-     * @hide
      */
     public void resetResolvedTextDirection() {
-        mPrivateFlags2 &= ~(TEXT_DIRECTION_RESOLVED | TEXT_DIRECTION_RESOLVED_MASK);
+        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
         onResolvedTextDirectionReset();
     }
 
@@ -16461,7 +16574,6 @@
      * 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.
-     * @hide
      */
     public void onResolvedTextDirectionReset() {
     }
@@ -16479,7 +16591,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"),
@@ -16491,7 +16602,7 @@
             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
     })
     public int getTextAlignment() {
-        return (mPrivateFlags2 & TEXT_ALIGNMENT_MASK) >> TEXT_ALIGNMENT_MASK_SHIFT;
+        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
     }
 
     /**
@@ -16508,15 +16619,14 @@
      * {@link #TEXT_ALIGNMENT_VIEW_END}
      *
      * @attr ref android.R.styleable#View_textAlignment
-     * @hide
      */
     public void setTextAlignment(int textAlignment) {
         if (textAlignment != getTextAlignment()) {
             // Reset the current and resolved text alignment
-            mPrivateFlags2 &= ~TEXT_ALIGNMENT_MASK;
+            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
             resetResolvedTextAlignment();
             // Set the new text alignment
-            mPrivateFlags2 |= ((textAlignment << TEXT_ALIGNMENT_MASK_SHIFT) & TEXT_ALIGNMENT_MASK);
+            mPrivateFlags2 |= ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
             // Refresh
             requestLayout();
             invalidate(true);
@@ -16538,7 +16648,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"),
@@ -16551,20 +16660,19 @@
     })
     public int getResolvedTextAlignment() {
         // If text alignment is not resolved, then resolve it
-        if ((mPrivateFlags2 & TEXT_ALIGNMENT_RESOLVED) != TEXT_ALIGNMENT_RESOLVED) {
+        if ((mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) != PFLAG2_TEXT_ALIGNMENT_RESOLVED) {
             resolveTextAlignment();
         }
-        return (mPrivateFlags2 & TEXT_ALIGNMENT_RESOLVED_MASK) >> TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
+        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >> PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
     }
 
     /**
      * Resolve the text alignment. Will call {@link View#onResolvedTextAlignmentChanged} when
      * resolution is done.
-     * @hide
      */
     public void resolveTextAlignment() {
         // Reset any previous text alignment resolution
-        mPrivateFlags2 &= ~(TEXT_ALIGNMENT_RESOLVED | TEXT_ALIGNMENT_RESOLVED_MASK);
+        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
 
         if (hasRtlSupport()) {
             // Set resolved text alignment flag depending on text alignment flag
@@ -16586,16 +16694,16 @@
                                 // Resolved text alignment is the same as the parent resolved
                                 // text alignment
                                 mPrivateFlags2 |=
-                                        (parentResolvedTextAlignment << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
+                                        (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
                                 break;
                             default:
                                 // Use default resolved text alignment
-                                mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
+                                mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
                         }
                     }
                     else {
                         // We cannot do the resolution if there is no parent so use the default
-                        mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
+                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
                     }
                     break;
                 case TEXT_ALIGNMENT_GRAVITY:
@@ -16605,19 +16713,19 @@
                 case TEXT_ALIGNMENT_VIEW_START:
                 case TEXT_ALIGNMENT_VIEW_END:
                     // Resolved text alignment is the same as text alignment
-                    mPrivateFlags2 |= (textAlignment << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
+                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
                     break;
                 default:
                     // Use default resolved text alignment
-                    mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
+                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
             }
         } else {
             // Use default resolved text alignment
-            mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
+            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
         }
 
         // Set the resolved
-        mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED;
+        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
         onResolvedTextAlignmentChanged();
     }
 
@@ -16625,7 +16733,6 @@
      * 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()) {
@@ -16641,7 +16748,6 @@
      * resolution should override this method.
      *
      * The default implementation does nothing.
-     * @hide
      */
     public void onResolvedTextAlignmentChanged() {
     }
@@ -16650,11 +16756,10 @@
      * 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);
+        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
         onResolvedTextAlignmentReset();
     }
 
@@ -16662,11 +16767,28 @@
      * 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.
-     * @hide
      */
     public void onResolvedTextAlignmentReset() {
     }
 
+    /**
+     * 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;
+            }
+        }
+    }
+
     //
     // Properties
     //
@@ -16967,7 +17089,7 @@
 
     private final class CheckForTap implements Runnable {
         public void run() {
-            mPrivateFlags &= ~PREPRESSED;
+            mPrivateFlags &= ~PFLAG_PREPRESSED;
             setPressed(true);
             checkForLongClick(ViewConfiguration.getTapTimeout());
         }
@@ -17315,6 +17437,8 @@
 
         final IBinder mWindowToken;
 
+        final Display mDisplay;
+
         final Callbacks mRootCallbacks;
 
         HardwareCanvas mHardwareCanvas;
@@ -17359,20 +17483,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 +17652,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 +17698,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 +17777,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 +18085,22 @@
             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);
+        }
+    }
 }
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..1286eb9 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,
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 0c83a73..ae10fbe 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,
@@ -3430,6 +3391,11 @@
         if (child.hasTransientState()) {
             childHasTransientStateChanged(child, true);
         }
+
+        if (child.getLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
+            child.resetResolvedLayoutDirection();
+            child.resolveRtlProperties();
+        }
     }
 
     private void addInArray(View child, int index) {
@@ -3655,6 +3621,8 @@
             childHasTransientStateChanged(view, false);
         }
 
+        view.resetResolvedLayoutDirection();
+
         onViewRemoved(view);
 
         needGlobalAttributesUpdate(false);
@@ -3838,6 +3806,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 +3853,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 +3884,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 +3895,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 +3916,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 +3937,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 +3959,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 +4000,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 +4011,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 +4057,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 +4068,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 +4102,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 +4117,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 +4142,7 @@
                 }
 
                 if (mLayerType != LAYER_TYPE_NONE) {
-                    mPrivateFlags |= INVALIDATED;
+                    mPrivateFlags |= PFLAG_INVALIDATED;
                     mLocalDirtyRect.union(dirty);
                 }
 
@@ -4192,8 +4204,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 +4968,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 +5071,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 +5096,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);
             }
@@ -5245,9 +5257,6 @@
         }
     }
 
-    /**
-     * @hide
-     */
     @Override
     public void onResolvedLayoutDirectionReset() {
         // Take care of resetting the children resolution too
@@ -5260,9 +5269,6 @@
         }
     }
 
-    /**
-     * @hide
-     */
     @Override
     public void onResolvedTextDirectionReset() {
         // Take care of resetting the children resolution too
@@ -5275,9 +5281,6 @@
         }
     }
 
-    /**
-     * @hide
-     */
     @Override
     public void onResolvedTextAlignmentReset() {
         // Take care of resetting the children resolution too
@@ -5448,15 +5451,19 @@
         }
 
         /**
-         * Extracts the layout parameters from the supplied attributes.
+         * Extracts the <code>width</code> and <code>height</code> layout parameters
+         * from the supplied TypedArray, <code>a</code>, and assigns them
+         * to the appropriate fields. If, <code>a</code>, does not contain an
+         * entry for either attribute, the value, {@link ViewGroup.LayoutParams#WRAP_CONTENT},
+         * is used as a default.
          *
          * @param a the style attributes to extract the parameters from
          * @param widthAttr the identifier of the width attribute
          * @param heightAttr the identifier of the height attribute
          */
         protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
-            width = a.getLayoutDimension(widthAttr, "layout_width");
-            height = a.getLayoutDimension(heightAttr, "layout_height");
+            width = a.getLayoutDimension(widthAttr, WRAP_CONTENT);
+            height = a.getLayoutDimension(heightAttr, WRAP_CONTENT);
         }
 
         /**
@@ -5468,7 +5475,6 @@
          *
          * {@link View#LAYOUT_DIRECTION_LTR}
          * {@link View#LAYOUT_DIRECTION_RTL}
-         * @hide
          */
         public void onResolveLayoutDirection(int layoutDirection) {
         }
@@ -5560,24 +5566,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 +5630,9 @@
                         R.styleable.ViewGroup_MarginLayout_layout_marginEnd, DEFAULT_RELATIVE);
             }
 
+            initialLeftMargin = leftMargin;
+            initialRightMargin = rightMargin;
+
             a.recycle();
         }
 
@@ -5642,6 +5658,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 +5692,8 @@
             topMargin = top;
             rightMargin = right;
             bottomMargin = bottom;
+            initialLeftMargin = left;
+            initialRightMargin = right;
         }
 
         /**
@@ -5688,6 +5711,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 +5719,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 +5740,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 +5769,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,33 +5787,61 @@
          * @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) {
+            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;
             }
         }
 
+        protected boolean isLayoutRtl() {
+            return (layoutDirection == View.LAYOUT_DIRECTION_RTL);
+        }
+
         /**
          * @hide
          */
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..27fd374 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,7 @@
     HashSet<View> mTempHashSet;
 
     private final int mDensity;
+    private final int mNoncompatDensity;
 
     /**
      * Consistency verifier for debugging purposes.
@@ -330,24 +322,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 +329,7 @@
         int localChanges;
     }
     
-    public ViewRootImpl(Context context) {
+    public ViewRootImpl(Context context, Display display) {
         super();
 
         if (MEASURE_LATENCY) {
@@ -367,7 +341,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 +369,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 +446,10 @@
      * @hide
      */
     static boolean isInTouchMode() {
-        if (mInitialized) {
+        IWindowSession windowSession = WindowManagerGlobal.peekWindowSession();
+        if (windowSession != null) {
             try {
-                return sWindowSession.getInTouchMode();
+                return windowSession.getInTouchMode();
             } catch (RemoteException e) {
             }
         }
@@ -548,9 +528,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,7 +552,7 @@
                 mPendingContentInsets.set(mAttachInfo.mContentInsets);
                 mPendingVisibleInsets.set(0, 0, 0, 0);
                 if (DEBUG_LAYOUT) Log.v(TAG, "Added window " + mWindow);
-                if (res < WindowManagerImpl.ADD_OKAY) {
+                if (res < WindowManagerGlobal.ADD_OKAY) {
                     mView = null;
                     mAttachInfo.mRootView = null;
                     mAdded = false;
@@ -580,33 +560,33 @@
                     unscheduleTraversals();
                     setAccessibilityFocus(null, null);
                     switch (res) {
-                        case WindowManagerImpl.ADD_BAD_APP_TOKEN:
-                        case WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN:
-                            throw new WindowManagerImpl.BadTokenException(
+                        case WindowManagerGlobal.ADD_BAD_APP_TOKEN:
+                        case WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN:
+                            throw new WindowManager.BadTokenException(
                                 "Unable to add window -- token " + attrs.token
                                 + " is not valid; is your activity running?");
-                        case WindowManagerImpl.ADD_NOT_APP_TOKEN:
-                            throw new WindowManagerImpl.BadTokenException(
+                        case WindowManagerGlobal.ADD_NOT_APP_TOKEN:
+                            throw new WindowManager.BadTokenException(
                                 "Unable to add window -- token " + attrs.token
                                 + " is not for an application");
-                        case WindowManagerImpl.ADD_APP_EXITING:
-                            throw new WindowManagerImpl.BadTokenException(
+                        case WindowManagerGlobal.ADD_APP_EXITING:
+                            throw new WindowManager.BadTokenException(
                                 "Unable to add window -- app for token " + attrs.token
                                 + " is exiting");
-                        case WindowManagerImpl.ADD_DUPLICATE_ADD:
-                            throw new WindowManagerImpl.BadTokenException(
+                        case WindowManagerGlobal.ADD_DUPLICATE_ADD:
+                            throw new WindowManager.BadTokenException(
                                 "Unable to add window -- window " + mWindow
                                 + " has already been added");
-                        case WindowManagerImpl.ADD_STARTING_NOT_NEEDED:
+                        case WindowManagerGlobal.ADD_STARTING_NOT_NEEDED:
                             // Silently ignore -- we would have just removed it
                             // right away, anyway.
                             return;
-                        case WindowManagerImpl.ADD_MULTIPLE_SINGLETON:
-                            throw new WindowManagerImpl.BadTokenException(
+                        case WindowManagerGlobal.ADD_MULTIPLE_SINGLETON:
+                            throw new WindowManager.BadTokenException(
                                 "Unable to add window " + mWindow +
                                 " -- another window of this type already exists");
-                        case WindowManagerImpl.ADD_PERMISSION_DENIED:
-                            throw new WindowManagerImpl.BadTokenException(
+                        case WindowManagerGlobal.ADD_PERMISSION_DENIED:
+                            throw new WindowManager.BadTokenException(
                                 "Unable to add window " + mWindow +
                                 " -- permission denied for this window type");
                     }
@@ -629,8 +609,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();
@@ -852,8 +832,8 @@
     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));
             }
         }
@@ -1027,17 +1007,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 +1105,7 @@
         if (host == null || !mAdded)
             return;
 
+        mIsInTraversal = true;
         mWillDrawSoon = true;
         boolean windowSizeMayChange = false;
         boolean newSurface = false;
@@ -1171,9 +1150,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 {
@@ -1258,9 +1236,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 +1287,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,6 +1402,7 @@
                                     mResizeBuffer.getHeight() != mHeight) {
                                 mResizeBuffer.resize(mWidth, mHeight);
                             }
+                            // TODO: should handle create/resize failure
                             layerCanvas = mResizeBuffer.start(hwRendererCanvas);
                             layerCanvas.setViewport(mWidth, mHeight);
                             layerCanvas.onPreDraw(null);
@@ -1504,11 +1482,12 @@
 
                         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)) {
                                         Slog.w(TAG, "No processes killed for memory; killing self");
                                         Process.killProcess(Process.myPid());
                                     }
@@ -1537,11 +1516,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 +1607,14 @@
                         mHeight != mAttachInfo.mHardwareRenderer.getHeight()) {
                     mAttachInfo.mHardwareRenderer.setup(mWidth, mHeight);
                     if (!hwInitialized) {
-                        mAttachInfo.mHardwareRenderer.invalidate(mHolder);
+                        mAttachInfo.mHardwareRenderer.invalidate(mHolder.getSurface());
                     }
                 }
             }
 
             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 +1659,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 +1694,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 +1711,7 @@
                     mPreviousTransparentRegion.set(mTransparentRegion);
                     // reconfigure window manager
                     try {
-                        sWindowSession.setTransparentRegion(mWindow, mTransparentRegion);
+                        mWindowSession.setTransparentRegion(mWindow, mTransparentRegion);
                     } catch (RemoteException e) {
                     }
                 }
@@ -1757,7 +1760,7 @@
                 }
 
                 try {
-                    sWindowSession.setInsets(mWindow, insets.mTouchableInsets,
+                    mWindowSession.setInsets(mWindow, insets.mTouchableInsets,
                             contentInsets, visibleInsets, touchableRegion);
                 } catch (RemoteException e) {
                 }
@@ -1782,7 +1785,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 +1816,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 +1845,8 @@
                 mPendingTransitions.clear();
             }
         }
+
+        mIsInTraversal = false;
     }
 
     private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {
@@ -1875,7 +1880,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 +2048,7 @@
                 }
             }
             try {
-                sWindowSession.finishDrawing(mWindow);
+                mWindowSession.finishDrawing(mWindow);
             } catch (RemoteException e) {
             }
         }
@@ -2199,7 +2204,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 +2243,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 +2256,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 +2285,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
@@ -2637,7 +2633,7 @@
             mInputEventReceiver = null;
         }
         try {
-            sWindowSession.remove(mWindow);
+            mWindowSession.remove(mWindow);
         } catch (RemoteException e) {
         }
         
@@ -2660,7 +2656,7 @@
         CompatibilityInfo ci = mCompatibilityInfo.getIfNeeded();
         if (ci != null) {
             config = new Configuration(config);
-            ci.applyToConfiguration(config);
+            ci.applyToConfiguration(mNoncompatDensity, config);
         }
 
         synchronized (sConfigCallbacks) {
@@ -2671,7 +2667,7 @@
         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) {
                 mLastConfiguration.setTo(config);
@@ -2727,6 +2723,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 +2775,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 +2805,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((Rect) args.arg1)
+                        && mPendingContentInsets.equals((Rect) args.arg2)
+                        && mPendingVisibleInsets.equals((Rect) args.arg3)
+                        && ((Configuration) 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 +2837,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;
@@ -2854,11 +2874,11 @@
                             mFullRedrawNeeded = true;
                             try {
                                 mAttachInfo.mHardwareRenderer.initializeIfNeeded(mWidth, mHeight,
-                                        mHolder);
+                                        mHolder.getSurface());
                             } 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 +2999,9 @@
                 handleDispatchDoneAnimating();
             } break;
             case MSG_INVALIDATE_WORLD: {
-                invalidateWorld(mView);
+                if (mView != null) {
+                    invalidateWorld(mView);
+                }
             } break;
             }
         }
@@ -3003,7 +3025,7 @@
 
         // tell the window manager
         try {
-            sWindowSession.setInTouchMode(inTouchMode);
+            mWindowSession.setInTouchMode(inTouchMode);
         } catch (RemoteException e) {
             throw new RuntimeException(e);
         }
@@ -3190,6 +3212,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 +3372,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 +3419,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 +3575,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 +3605,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 +3817,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 +3832,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 +3934,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 +3995,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 +4041,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 +4076,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 +4136,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 +4728,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 +4787,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 +4908,7 @@
                 boolean sync) {
             if (sync) {
                 try {
-                    sWindowSession.wallpaperOffsetsComplete(asBinder());
+                    mWindowSession.wallpaperOffsetsComplete(asBinder());
                 } catch (RemoteException e) {
                 }
             }
@@ -4788,7 +4918,7 @@
                 int z, Bundle extras, boolean sync) {
             if (sync) {
                 try {
-                    sWindowSession.wallpaperCommandComplete(asBinder(), null);
+                    mWindowSession.wallpaperCommandComplete(asBinder(), null);
                 } catch (RemoteException e) {
                 }
             }
@@ -5186,15 +5316,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 +5355,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 +5374,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 +5392,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 +5411,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..d6f63a7 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,31 @@
     private ToneGenerator mToneGenerators[];
     private Vibrator mVibrator;
 
+    private static AlertDialog sConfirmSafeVolumeDialog;
+
+    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();
+        }
+
+        public void onDismiss(DialogInterface unused) {
+            mContext.unregisterReceiver(this);
+        }
+    }
+
+
     public VolumePanel(final Context context, AudioService volumeService) {
         mContext = context;
         mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
@@ -282,6 +312,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 +555,10 @@
         postMuteChanged(STREAM_MASTER, flags);
     }
 
+    public void postDisplaySafeVolumeWarning() {
+        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
@@ -786,11 +827,45 @@
         }
     }
 
+    protected void onDisplaySafeVolumeWarning() {
+        if (sConfirmSafeVolumeDialog != null) {
+            sConfirmSafeVolumeDialog.dismiss();
+        }
+        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 +966,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..a242895 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;
 
 /**
@@ -119,6 +116,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 +125,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 +454,7 @@
      * display panels.  This is <em>not</em> used for displaying the
      * Window itself -- that must be done by the client.
      *
-     * @param wm The ViewManager for adding new windows.
+     * @param wm The window manager for adding new windows.
      */
     public void setWindowManager(WindowManager wm, IBinder appToken, String appName) {
         setWindowManager(wm, appToken, appName, false);
@@ -465,86 +465,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 +696,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 +707,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 +729,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..fa2d4e8 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,24 @@
     }
 
     /**
-     * Use this method to get the default Display object.
-     * 
-     * @return default Display object
+     * 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 +89,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 +179,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 +188,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 +201,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;
     
@@ -435,6 +456,25 @@
         public static final int TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW+24;
 
         /**
+         * Window type: Behind the universe of the real windows.
+         * @hide
+         */
+        public static final int TYPE_UNIVERSE_BACKGROUND = FIRST_SYSTEM_WINDOW+25;
+
+        /**
+         * Window type: Display overlay window.  Used to simulate secondary display devices.
+         * @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.
+         * @hide
+         */
+        public static final int TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW+27;
+
+        /**
          * End of types of system windows.
          */
         public static final int LAST_SYSTEM_WINDOW      = 2999;
@@ -530,7 +570,9 @@
         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
@@ -718,7 +760,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
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
new file mode 100644
index 0000000..7855763c
--- /dev/null
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.animation.ValueAnimator;
+import android.app.ActivityManager;
+import android.content.ComponentCallbacks2;
+import android.content.res.Configuration;
+import android.opengl.ManagedEGLContext;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemProperties;
+import android.util.AndroidRuntimeException;
+import android.util.Log;
+import android.view.inputmethod.InputMethodManager;
+
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+
+/**
+ * Provides low-level communication with the system window manager for
+ * operations that are not associated with any particular context.
+ *
+ * This class is only used internally to implement global functions where
+ * the caller already knows the display and relevant compatibility information
+ * for the operation.  For most purposes, you should use {@link WindowManager} instead
+ * since it is bound to a context.
+ *
+ * @see WindowManagerImpl
+ * @hide
+ */
+public final class WindowManagerGlobal {
+    private static final String TAG = "WindowManager";
+
+    /**
+     * The user is navigating with keys (not the touch screen), so
+     * navigational focus should be shown.
+     */
+    public static final int RELAYOUT_RES_IN_TOUCH_MODE = 0x1;
+
+    /**
+     * This is the first time the window is being drawn,
+     * so the client must call drawingFinished() when done
+     */
+    public static final int RELAYOUT_RES_FIRST_TIME = 0x2;
+
+    /**
+     * The window manager has changed the surface from the last call.
+     */
+    public static final int RELAYOUT_RES_SURFACE_CHANGED = 0x4;
+
+    /**
+     * The window manager is currently animating.  It will call
+     * IWindow.doneAnimating() when done.
+     */
+    public static final int RELAYOUT_RES_ANIMATING = 0x8;
+
+    /**
+     * Flag for relayout: the client will be later giving
+     * internal insets; as a result, the window will not impact other window
+     * layouts until the insets are given.
+     */
+    public static final int RELAYOUT_INSETS_PENDING = 0x1;
+
+    /**
+     * Flag for relayout: the client may be currently using the current surface,
+     * so if it is to be destroyed as a part of the relayout the destroy must
+     * be deferred until later.  The client will call performDeferredDestroy()
+     * when it is okay.
+     */
+    public static final int RELAYOUT_DEFER_SURFACE_DESTROY = 0x2;
+
+    public static final int ADD_FLAG_APP_VISIBLE = 0x2;
+    public static final int ADD_FLAG_IN_TOUCH_MODE = RELAYOUT_RES_IN_TOUCH_MODE;
+
+    public static final int ADD_OKAY = 0;
+    public static final int ADD_BAD_APP_TOKEN = -1;
+    public static final int ADD_BAD_SUBWINDOW_TOKEN = -2;
+    public static final int ADD_NOT_APP_TOKEN = -3;
+    public static final int ADD_APP_EXITING = -4;
+    public static final int ADD_DUPLICATE_ADD = -5;
+    public static final int ADD_STARTING_NOT_NEEDED = -6;
+    public static final int ADD_MULTIPLE_SINGLETON = -7;
+    public static final int ADD_PERMISSION_DENIED = -8;
+
+    private static WindowManagerGlobal sDefaultWindowManager;
+    private static IWindowManager sWindowManagerService;
+    private static IWindowSession sWindowSession;
+
+    private final Object mLock = new Object();
+
+    private View[] mViews;
+    private ViewRootImpl[] mRoots;
+    private WindowManager.LayoutParams[] mParams;
+    private boolean mNeedsEglTerminate;
+
+    private Runnable mSystemPropertyUpdater;
+
+    private WindowManagerGlobal() {
+    }
+
+    public static WindowManagerGlobal getInstance() {
+        synchronized (WindowManagerGlobal.class) {
+            if (sDefaultWindowManager == null) {
+                sDefaultWindowManager = new WindowManagerGlobal();
+            }
+            return sDefaultWindowManager;
+        }
+    }
+
+    public static IWindowManager getWindowManagerService() {
+        synchronized (WindowManagerGlobal.class) {
+            if (sWindowManagerService == null) {
+                sWindowManagerService = IWindowManager.Stub.asInterface(
+                        ServiceManager.getService("window"));
+            }
+            return sWindowManagerService;
+        }
+    }
+
+    public static IWindowSession getWindowSession(Looper mainLooper) {
+        synchronized (WindowManagerGlobal.class) {
+            if (sWindowSession == null) {
+                try {
+                    InputMethodManager imm = InputMethodManager.getInstance(mainLooper);
+                    IWindowManager windowManager = getWindowManagerService();
+                    sWindowSession = windowManager.openSession(
+                            imm.getClient(), imm.getInputContext());
+                    float animatorScale = windowManager.getAnimationScale(2);
+                    ValueAnimator.setDurationScale(animatorScale);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Failed to open window session", e);
+                }
+            }
+            return sWindowSession;
+        }
+    }
+
+    public static IWindowSession peekWindowSession() {
+        synchronized (WindowManagerGlobal.class) {
+            return sWindowSession;
+        }
+    }
+
+    public void addView(View view, ViewGroup.LayoutParams params,
+            Display display, Window parentWindow) {
+        if (view == null) {
+            throw new IllegalArgumentException("view must not be null");
+        }
+        if (display == null) {
+            throw new IllegalArgumentException("display must not be null");
+        }
+        if (!(params instanceof WindowManager.LayoutParams)) {
+            throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
+        }
+
+        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
+        if (parentWindow != null) {
+            parentWindow.adjustLayoutParamsForSubWindow(wparams);
+        }
+
+        ViewRootImpl root;
+        View panelParentView = null;
+
+        synchronized (mLock) {
+            // Start watching for system property changes.
+            if (mSystemPropertyUpdater == null) {
+                mSystemPropertyUpdater = new Runnable() {
+                    @Override public void run() {
+                        synchronized (mLock) {
+                            for (ViewRootImpl root : mRoots) {
+                                root.loadSystemProperties();
+                            }
+                        }
+                    }
+                };
+                SystemProperties.addChangeCallback(mSystemPropertyUpdater);
+            }
+
+            int index = findViewLocked(view, false);
+            if (index >= 0) {
+                throw new IllegalStateException("View " + view
+                        + " has already been added to the window manager.");
+            }
+
+            // If this is a panel window, then find the window it is being
+            // attached to for future reference.
+            if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
+                    wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
+                final int count = mViews != null ? mViews.length : 0;
+                for (int i=0; i<count; i++) {
+                    if (mRoots[i].mWindow.asBinder() == wparams.token) {
+                        panelParentView = mViews[i];
+                    }
+                }
+            }
+
+            root = new ViewRootImpl(view.getContext(), display);
+
+            view.setLayoutParams(wparams);
+
+            if (mViews == null) {
+                index = 1;
+                mViews = new View[1];
+                mRoots = new ViewRootImpl[1];
+                mParams = new WindowManager.LayoutParams[1];
+            } else {
+                index = mViews.length + 1;
+                Object[] old = mViews;
+                mViews = new View[index];
+                System.arraycopy(old, 0, mViews, 0, index-1);
+                old = mRoots;
+                mRoots = new ViewRootImpl[index];
+                System.arraycopy(old, 0, mRoots, 0, index-1);
+                old = mParams;
+                mParams = new WindowManager.LayoutParams[index];
+                System.arraycopy(old, 0, mParams, 0, index-1);
+            }
+            index--;
+
+            mViews[index] = view;
+            mRoots[index] = root;
+            mParams[index] = wparams;
+        }
+
+        // do this last because it fires off messages to start doing things
+        root.setView(view, wparams, panelParentView);
+    }
+
+    public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
+        if (view == null) {
+            throw new IllegalArgumentException("view must not be null");
+        }
+        if (!(params instanceof WindowManager.LayoutParams)) {
+            throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
+        }
+
+        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
+
+        view.setLayoutParams(wparams);
+
+        synchronized (mLock) {
+            int index = findViewLocked(view, true);
+            ViewRootImpl root = mRoots[index];
+            mParams[index] = wparams;
+            root.setLayoutParams(wparams, false);
+        }
+    }
+
+    public void removeView(View view, boolean immediate) {
+        if (view == null) {
+            throw new IllegalArgumentException("view must not be null");
+        }
+
+        synchronized (mLock) {
+            int index = findViewLocked(view, true);
+            View curView = removeViewLocked(index, immediate);
+            if (curView == view) {
+                return;
+            }
+
+            throw new IllegalStateException("Calling with view " + view
+                    + " but the ViewAncestor is attached to " + curView);
+        }
+    }
+
+    public void closeAll(IBinder token, String who, String what) {
+        synchronized (mLock) {
+            if (mViews == null)
+                return;
+
+            int count = mViews.length;
+            //Log.i("foo", "Closing all windows of " + token);
+            for (int i=0; i<count; i++) {
+                //Log.i("foo", "@ " + i + " token " + mParams[i].token
+                //        + " view " + mRoots[i].getView());
+                if (token == null || mParams[i].token == token) {
+                    ViewRootImpl root = mRoots[i];
+
+                    //Log.i("foo", "Force closing " + root);
+                    if (who != null) {
+                        WindowLeaked leak = new WindowLeaked(
+                                what + " " + who + " has leaked window "
+                                + root.getView() + " that was originally added here");
+                        leak.setStackTrace(root.getLocation().getStackTrace());
+                        Log.e(TAG, leak.getMessage(), leak);
+                    }
+
+                    removeViewLocked(i, false);
+                    i--;
+                    count--;
+                }
+            }
+        }
+    }
+
+    private View removeViewLocked(int index, boolean immediate) {
+        ViewRootImpl root = mRoots[index];
+        View view = root.getView();
+
+        if (view != null) {
+            InputMethodManager imm = InputMethodManager.getInstance(view.getContext());
+            if (imm != null) {
+                imm.windowDismissed(mViews[index].getWindowToken());
+            }
+        }
+        root.die(immediate);
+
+        final int count = mViews.length;
+
+        // remove it from the list
+        View[] tmpViews = new View[count-1];
+        removeItem(tmpViews, mViews, index);
+        mViews = tmpViews;
+
+        ViewRootImpl[] tmpRoots = new ViewRootImpl[count-1];
+        removeItem(tmpRoots, mRoots, index);
+        mRoots = tmpRoots;
+
+        WindowManager.LayoutParams[] tmpParams
+                = new WindowManager.LayoutParams[count-1];
+        removeItem(tmpParams, mParams, index);
+        mParams = tmpParams;
+
+        if (view != null) {
+            view.assignParent(null);
+            // func doesn't allow null...  does it matter if we clear them?
+            //view.setLayoutParams(null);
+        }
+        return view;
+    }
+
+    private static void removeItem(Object[] dst, Object[] src, int index) {
+        if (dst.length > 0) {
+            if (index > 0) {
+                System.arraycopy(src, 0, dst, 0, index);
+            }
+            if (index < dst.length) {
+                System.arraycopy(src, index+1, dst, index, src.length-index-1);
+            }
+        }
+    }
+
+    private int findViewLocked(View view, boolean required) {
+        synchronized (mLock) {
+            if (mViews != null) {
+                final int count = mViews.length;
+                for (int i = 0; i < count; i++) {
+                    if (mViews[i] == view) {
+                        return i;
+                    }
+                }
+            }
+            if (required) {
+                throw new IllegalArgumentException("View not attached to window manager");
+            }
+            return -1;
+        }
+    }
+
+    public void startTrimMemory(int level) {
+        if (HardwareRenderer.isAvailable()) {
+            // On low-end gfx devices we trim when memory is moderate;
+            // on high-end devices we do this when low.
+            if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
+                    || (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE
+                            && !ActivityManager.isHighEndGfx())) {
+                // Destroy all hardware surfaces and resources associated to
+                // known windows
+                synchronized (mLock) {
+                    if (mViews == null) return;
+                    int count = mViews.length;
+                    for (int i = 0; i < count; i++) {
+                        mRoots[i].terminateHardwareResources();
+                    }
+                }
+                // Force a full memory flush
+                mNeedsEglTerminate = true;
+                HardwareRenderer.startTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
+                return;
+            }
+
+            HardwareRenderer.startTrimMemory(level);
+        }
+    }
+
+    public void endTrimMemory() {
+        HardwareRenderer.endTrimMemory();
+
+        if (mNeedsEglTerminate) {
+            ManagedEGLContext.doTerminate();
+            mNeedsEglTerminate = false;
+        }
+    }
+
+    public void trimLocalMemory() {
+        synchronized (mLock) {
+            if (mViews == null) return;
+            int count = mViews.length;
+            for (int i = 0; i < count; i++) {
+                mRoots[i].destroyHardwareLayers();
+            }
+        }
+    }
+
+    public void dumpGfxInfo(FileDescriptor fd) {
+        FileOutputStream fout = new FileOutputStream(fd);
+        PrintWriter pw = new PrintWriter(fout);
+        try {
+            synchronized (mLock) {
+                if (mViews != null) {
+                    final int count = mViews.length;
+
+                    pw.println("Profile data in ms:");
+
+                    for (int i = 0; i < count; i++) {
+                        ViewRootImpl root = mRoots[i];
+                        String name = getWindowName(root);
+                        pw.printf("\n\t%s", name);
+
+                        HardwareRenderer renderer =
+                                root.getView().mAttachInfo.mHardwareRenderer;
+                        if (renderer != null) {
+                            renderer.dumpGfxInfo(pw);
+                        }
+                    }
+
+                    pw.println("\nView hierarchy:\n");
+
+                    int viewsCount = 0;
+                    int displayListsSize = 0;
+                    int[] info = new int[2];
+
+                    for (int i = 0; i < count; i++) {
+                        ViewRootImpl root = mRoots[i];
+                        root.dumpGfxInfo(info);
+
+                        String name = getWindowName(root);
+                        pw.printf("  %s\n  %d views, %.2f kB of display lists",
+                                name, info[0], info[1] / 1024.0f);
+                        HardwareRenderer renderer =
+                                root.getView().mAttachInfo.mHardwareRenderer;
+                        if (renderer != null) {
+                            pw.printf(", %d frames rendered", renderer.getFrameCount());
+                        }
+                        pw.printf("\n\n");
+
+                        viewsCount += info[0];
+                        displayListsSize += info[1];
+                    }
+
+                    pw.printf("\nTotal ViewRootImpl: %d\n", count);
+                    pw.printf("Total Views:        %d\n", viewsCount);
+                    pw.printf("Total DisplayList:  %.2f kB\n\n", displayListsSize / 1024.0f);
+                }
+            }
+        } finally {
+            pw.flush();
+        }
+    }
+
+    private static String getWindowName(ViewRootImpl root) {
+        return root.mWindowAttributes.getTitle() + "/" +
+                root.getClass().getName() + '@' + Integer.toHexString(root.hashCode());
+    }
+
+    public void setStoppedState(IBinder token, boolean stopped) {
+        synchronized (mLock) {
+            if (mViews != null) {
+                int count = mViews.length;
+                for (int i=0; i < count; i++) {
+                    if (token == null || mParams[i].token == token) {
+                        ViewRootImpl root = mRoots[i];
+                        root.setStopped(stopped);
+                    }
+                }
+            }
+        }
+    }
+
+    public void reportNewConfiguration(Configuration config) {
+        synchronized (mLock) {
+            if (mViews != null) {
+                int count = mViews.length;
+                config = new Configuration(config);
+                for (int i=0; i < count; i++) {
+                    ViewRootImpl root = mRoots[i];
+                    root.requestUpdateConfiguration(config);
+                }
+            }
+        }
+    }
+}
+
+final class WindowLeaked extends AndroidRuntimeException {
+    public WindowLeaked(String msg) {
+        super(msg);
+    }
+}
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 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..75554da 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -22,7 +22,6 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.os.IBinder;
-import android.os.LocalPowerManager;
 import android.os.Looper;
 import android.view.animation.Animation;
 
@@ -115,16 +114,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 +338,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 +396,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,26 +478,24 @@
      * 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);
 
@@ -553,7 +556,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 +668,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 +713,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 +727,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 +768,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 +835,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
@@ -1061,9 +1074,9 @@
      * 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);
 
@@ -1086,31 +1099,6 @@
     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();
-
-    /**
      * Set the last used input method window state. This state is used to make IME transition
      * smooth.
      * @hide
@@ -1118,6 +1106,14 @@
     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 canMagnifyWindow(WindowManager.LayoutParams attrs);
+
+    /**
      * Print the WindowManagerPolicy's state into the given stream.
      *
      * @param prefix Text to print at the front of each line.
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/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/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/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..3ea6df3 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;
@@ -1105,6 +1160,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 +1250,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 +1293,7 @@
             mServedConnecting = true;
         }
 
-        if (ic != null) {
+        if (finishComposingText && ic != null) {
             ic.finishComposingText();
         }
 
@@ -1286,7 +1338,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 +1563,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 +1933,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/webkit/AccessibilityInjector.java b/core/java/android/webkit/AccessibilityInjector.java
index 7dfb5bb..a51a8f6 100644
--- a/core/java/android/webkit/AccessibilityInjector.java
+++ b/core/java/android/webkit/AccessibilityInjector.java
@@ -34,6 +34,7 @@
 
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -53,7 +54,7 @@
     private final WebView mWebView;
 
     // The Java objects that are exposed to JavaScript.
-    private TextToSpeech mTextToSpeech;
+    private TextToSpeechWrapper mTextToSpeech;
     private CallbackHandler mCallback;
 
     // Lazily loaded helper objects.
@@ -279,6 +280,7 @@
         }
 
         if (!shouldInjectJavaScript(url)) {
+            mAccessibilityScriptInjected = false;
             toggleFallbackAccessibilityInjector(true);
             return;
         }
@@ -292,6 +294,23 @@
     }
 
     /**
+     * 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();
+    }
+
+    /**
      * Toggles the non-JavaScript method for handling accessibility.
      *
      * @param enabled {@code true} to enable the non-JavaScript method, or
@@ -349,10 +368,7 @@
         if (mTextToSpeech != null) {
             return;
         }
-
-        final String pkgName = mContext.getPackageName();
-
-        mTextToSpeech = new TextToSpeech(mContext, null, null, pkgName + ".**webview**", true);
+        mTextToSpeech = new TextToSpeechWrapper(mContext);
         mWebView.addJavascriptInterface(mTextToSpeech, ALIAS_TTS_JS_INTERFACE);
     }
 
@@ -508,6 +524,41 @@
     }
 
     /**
+     * Used to protect the TextToSpeech class, only exposing the methods we want to expose.
+     */
+    private static class TextToSpeechWrapper {
+        private TextToSpeech mTextToSpeech;
+
+        public TextToSpeechWrapper(Context context) {
+            final String pkgName = context.getPackageName();
+            mTextToSpeech = new TextToSpeech(context, null, null, pkgName + ".**webview**", true);
+        }
+
+        @JavascriptInterface
+        @SuppressWarnings("unused")
+        public boolean isSpeaking() {
+            return mTextToSpeech.isSpeaking();
+        }
+
+        @JavascriptInterface
+        @SuppressWarnings("unused")
+        public int speak(String text, int queueMode, HashMap<String, String> params) {
+            return mTextToSpeech.speak(text, queueMode, params);
+        }
+
+        @JavascriptInterface
+        @SuppressWarnings("unused")
+        public int stop() {
+            return mTextToSpeech.stop();
+        }
+
+        @SuppressWarnings("unused")
+        protected void shutdown() {
+            mTextToSpeech.shutdown();
+        }
+    }
+
+    /**
      * Exposes result interface to JavaScript.
      */
     private static class CallbackHandler {
@@ -603,6 +654,7 @@
          * @param id The result id of the request as a {@link String}.
          * @param result The result of the request as a {@link String}.
          */
+        @JavascriptInterface
         @SuppressWarnings("unused")
         public void onResult(String id, String result) {
             final long resultId;
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 5108990..fea427d 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;
@@ -88,16 +89,24 @@
     // Is this frame the main frame?
     private boolean mIsMainFrame;
 
+    // Javascript interface object
+    private class JSObject {
+        Object object;
+        boolean requireAnnotation;
+
+        public JSObject(Object object, boolean requireAnnotation) {
+            this.object = object;
+            this.requireAnnotation = requireAnnotation;
+        }
+    }
+
     // Attached Javascript interfaces
-    private Map<String, Object> mJavaScriptObjects;
+    private Map<String, JSObject> mJavaScriptObjects;
     private Set<Object> mRemovedJavaScriptObjects;
 
     // 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;
@@ -233,20 +242,16 @@
         }
         sConfigCallback.addHandler(this);
 
-        mJavaScriptObjects = javascriptInterfaces;
-        if (mJavaScriptObjects == null) {
-            mJavaScriptObjects = new HashMap<String, Object>();
-        }
+        mJavaScriptObjects = new HashMap<String, JSObject>();
+        addJavaScriptObjects(javascriptInterfaces);
         mRemovedJavaScriptObjects = new HashSet<Object>();
 
         mSettings = settings;
         mContext = context;
         mCallbackProxy = proxy;
+        mDatabase = WebViewDatabaseClassic.getInstance(appContext);
         mWebViewCore = w;
 
-        mSearchBox = new SearchBoxImpl(mWebViewCore, mCallbackProxy);
-        mJavaScriptObjects.put(SearchBoxImpl.JS_INTERFACE_NAME, mSearchBox);
-
         AssetManager am = context.getAssets();
         nativeCreateFrame(w, am, proxy.getBackForwardList());
 
@@ -424,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);
                 }
             }
         }
@@ -497,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]);
                         }
@@ -591,15 +594,34 @@
         Iterator<String> iter = mJavaScriptObjects.keySet().iterator();
         while (iter.hasNext())  {
             String interfaceName = iter.next();
-            Object object = mJavaScriptObjects.get(interfaceName);
-            if (object != null) {
+            JSObject jsobject = mJavaScriptObjects.get(interfaceName);
+            if (jsobject != null && jsobject.object != null) {
                 nativeAddJavascriptInterface(nativeFramePointer,
-                        mJavaScriptObjects.get(interfaceName), interfaceName);
+                        jsobject.object, interfaceName, jsobject.requireAnnotation);
             }
         }
         mRemovedJavaScriptObjects.clear();
+    }
 
-        stringByEvaluatingJavaScriptFromString(SearchBoxImpl.JS_BRIDGE);
+    /*
+     * Add javascript objects to the internal list of objects. The default behavior
+     * 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())  {
+            String interfaceName = iter.next();
+            Object object = javascriptInterfaces.get(interfaceName);
+            if (object != null) {
+                mJavaScriptObjects.put(interfaceName, new JSObject(object, false));
+            }
+        }
     }
 
     /**
@@ -619,11 +641,11 @@
         }
     }
 
-    public void addJavascriptInterface(Object obj, String interfaceName) {
+    public void addJavascriptInterface(Object obj, String interfaceName,
+            boolean requireAnnotation) {
         assert obj != null;
         removeJavascriptInterface(interfaceName);
-
-        mJavaScriptObjects.put(interfaceName, obj);
+        mJavaScriptObjects.put(interfaceName, new JSObject(obj, requireAnnotation));
     }
 
     public void removeJavascriptInterface(String interfaceName) {
@@ -800,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
@@ -811,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
@@ -1138,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 {
@@ -1158,7 +1179,7 @@
             mKeyStoreHandler = new KeyStoreHandler(mimeType);
         } else {
             mCallbackProxy.onDownloadStart(url, userAgent,
-                contentDisposition, mimeType, contentLength);
+                contentDisposition, mimeType, referer, contentLength);
         }
     }
 
@@ -1191,10 +1212,6 @@
         }
     }
 
-    /*package*/ SearchBox getSearchBox() {
-        return mSearchBox;
-    }
-
     /**
      * Called by JNI when processing the X-Auto-Login header.
      */
@@ -1249,7 +1266,7 @@
      * Add a javascript interface to the main frame.
      */
     private native void nativeAddJavascriptInterface(int nativeFramePointer,
-            Object obj, String interfaceName);
+            Object obj, String interfaceName, boolean requireAnnotation);
 
     public native void clearCache();
 
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/JWebCoreJavaBridge.java b/core/java/android/webkit/JWebCoreJavaBridge.java
index e6eaa14..d9aeb70 100644
--- a/core/java/android/webkit/JWebCoreJavaBridge.java
+++ b/core/java/android/webkit/JWebCoreJavaBridge.java
@@ -89,6 +89,7 @@
     private void fireSharedTimer() { 
         // clear the flag so that sharedTimerFired() can set a new timer
         mHasInstantTimer = false;
+        removeMessages(TIMER_MESSAGE);
         sharedTimerFired();
     }
 
diff --git a/core/java/android/webkit/JavascriptInterface.java b/core/java/android/webkit/JavascriptInterface.java
new file mode 100644
index 0000000..6cd2a7b
--- /dev/null
+++ b/core/java/android/webkit/JavascriptInterface.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.webkit;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 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.
+ *
+ */
+@SuppressWarnings("javadoc")
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+public @interface JavascriptInterface {
+}
\ No newline at end of file
diff --git a/core/java/android/webkit/MockGeolocation.java b/core/java/android/webkit/MockGeolocation.java
index fbda492..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..be2d863 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();
     }
@@ -337,6 +379,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 +387,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 +434,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 +500,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 +508,9 @@
 
     /**
      * Gets whether light touches are enabled.
+     *
+     * @return whether light touches are enabled
+     * @see #setLightTouchEnabled
      */
     public boolean getLightTouchEnabled() {
         throw new MustOverrideException();
@@ -455,6 +521,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 +533,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 +542,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 +560,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 +579,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 +591,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 +620,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 +631,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 +677,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 +689,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 +965,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 +980,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 +1004,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 +1032,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 +1044,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 +1071,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 +1082,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 +1094,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 +1113,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 +1165,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 +1174,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 +1238,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 +1247,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 +1279,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 +1290,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..4202a7f 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();
@@ -1447,6 +1480,7 @@
      *
      * @param listener an implementation of WebView.PictureListener
      * @deprecated This method is now obsolete.
+     * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
      */
     @Deprecated
     public void setPictureListener(PictureListener listener) {
@@ -1457,10 +1491,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 +1514,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 +1525,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 +1588,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 +1623,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 +1660,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 +1675,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 +1708,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 0a9ab2b..d23f52c 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);
@@ -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() {
@@ -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,15 +2132,6 @@
 
     private void destroyJava() {
         mCallbackProxy.blockMessages();
-        clearHelpers();
-        if (mListBoxDialog != null) {
-            mListBoxDialog.dismiss();
-            mListBoxDialog = null;
-        }
-        if (mSavePasswordDialog != null) {
-            mSavePasswordDialog.dismiss();
-            mSavePasswordDialog = null;
-        }
         if (mWebViewCore != null) {
             // Tell WebViewCore to destroy itself
             synchronized (this) {
@@ -2223,7 +2238,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 +2252,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 +2451,7 @@
      */
     @Override
     public WebBackForwardList restoreState(Bundle inState) {
-        WebBackForwardList returnList = null;
+        WebBackForwardListClassic returnList = null;
         if (inState == null) {
             return returnList;
         }
@@ -2444,7 +2459,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 +2480,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.
@@ -2638,7 +2653,7 @@
      */
     @Override
     public boolean canGoBack() {
-        WebBackForwardList l = mCallbackProxy.getBackForwardList();
+        WebBackForwardListClassic l = mCallbackProxy.getBackForwardList();
         synchronized (l) {
             if (l.getClearPending()) {
                 return false;
@@ -2661,7 +2676,7 @@
      */
     @Override
     public boolean canGoForward() {
-        WebBackForwardList l = mCallbackProxy.getBackForwardList();
+        WebBackForwardListClassic l = mCallbackProxy.getBackForwardList();
         synchronized (l) {
             if (l.getClearPending()) {
                 return false;
@@ -2684,7 +2699,7 @@
      */
     @Override
     public boolean canGoBackOrForward(int steps) {
-        WebBackForwardList l = mCallbackProxy.getBackForwardList();
+        WebBackForwardListClassic l = mCallbackProxy.getBackForwardList();
         synchronized (l) {
             if (l.getClearPending()) {
                 return false;
@@ -3332,6 +3347,7 @@
         }
         if (mTouchMode == TOUCH_DRAG_LAYER_MODE) {
             scrollLayerTo(scrollX, scrollY);
+            animateHandles();
             return;
         }
         mInOverScrollMode = false;
@@ -3352,6 +3368,8 @@
 
         mWebViewPrivate.super_scrollTo(scrollX, scrollY);
 
+        animateHandles();
+
         if (mOverScrollGlow != null) {
             mOverScrollGlow.pullGlow(getScrollX(), getScrollY(), oldX, oldY, maxX, maxY);
         }
@@ -3398,7 +3416,7 @@
      */
     @Override
     public String getTouchIconUrl() {
-        WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
+        WebHistoryItemClassic h = mCallbackProxy.getBackForwardList().getCurrentItem();
         return h != null ? h.getTouchIconUrl() : null;
     }
 
@@ -3464,7 +3482,7 @@
                 nativeSetPauseDrawing(mNativeClass, true);
             }
 
-            cancelSelectDialog();
+            cancelDialogs();
             WebCoreThreadWatchdog.pause();
         }
     }
@@ -3562,7 +3580,7 @@
      * See {@link WebView#copyBackForwardList()}
      */
     @Override
-    public WebBackForwardList copyBackForwardList() {
+    public WebBackForwardListClassic copyBackForwardList() {
         return mCallbackProxy.getBackForwardList().clone();
     }
 
@@ -3570,7 +3588,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 +3612,7 @@
         return findAllBody(find, false);
     }
 
+    @Override
     public void findAllAsync(String find) {
         findAllBody(find, true);
     }
@@ -3631,6 +3651,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 +3867,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) {
@@ -3951,7 +3969,7 @@
 
         // 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 +3984,7 @@
     /* package */ void onPageFinished(String url) {
         mZoomManager.onPageFinished(url);
 
-        if (isAccessibilityEnabled()) {
+        if (isAccessibilityInjectionEnabled()) {
             getAccessibilityInjector().onPageFinished(url);
         }
     }
@@ -4097,12 +4115,22 @@
      */
     @Override
     public void addJavascriptInterface(Object object, String name) {
+
         if (object == null) {
             return;
         }
         WebViewCore.JSInterfaceData arg = new WebViewCore.JSInterfaceData();
+
         arg.mObject = object;
         arg.mInterfaceName = name;
+
+        // 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);
     }
 
@@ -4472,9 +4500,6 @@
     }
 
     private void onZoomAnimationStart() {
-        if (!mSelectingText && mHandleAlpha.getAlpha() > 0) {
-            mHandleAlphaAnimator.end();
-        }
     }
 
     private void onZoomAnimationEnd() {
@@ -4507,34 +4532,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() {
@@ -4545,66 +4599,87 @@
                     com.android.internal.R.drawable.text_select_handle_left);
             mSelectHandleRight = mContext.getResources().getDrawable(
                     com.android.internal.R.drawable.text_select_handle_right);
-            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
@@ -4839,6 +4914,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
@@ -4923,7 +5035,7 @@
         }
 
         // See if the accessibility injector needs to handle this event.
-        if (isAccessibilityEnabled()
+        if (isAccessibilityInjectionEnabled()
                 && getAccessibilityInjector().handleKeyEventIfNecessary(event)) {
             return true;
         }
@@ -5030,7 +5142,7 @@
         }
 
         // See if the accessibility injector needs to handle this event.
-        if (isAccessibilityEnabled()
+        if (isAccessibilityInjectionEnabled()
                 && getAccessibilityInjector().handleKeyEventIfNecessary(event)) {
             return true;
         }
@@ -5071,8 +5183,8 @@
         ClipboardManager cm = (ClipboardManager)(mContext
                 .getSystemService(Context.CLIPBOARD_SERVICE));
         if (cm.hasPrimaryClip()) {
-            Point cursorPoint = new Point(contentToViewX(mSelectCursorLeft.x),
-                    contentToViewY(mSelectCursorLeft.y));
+            Point cursorPoint = new Point(contentToViewX(mSelectCursorBase.x),
+                    contentToViewY(mSelectCursorBase.y));
             Point cursorTop = calculateCaretTop();
             cursorTop.set(contentToViewX(cursorTop.x),
                     contentToViewY(cursorTop.y));
@@ -5122,12 +5234,12 @@
      * calculates the top of a caret.
      */
     private Point calculateCaretTop() {
-        float scale = scaleAlongSegment(mSelectCursorLeft.x, mSelectCursorLeft.y,
-                mSelectCursorLeftTextQuad.p4, mSelectCursorLeftTextQuad.p3);
+        float scale = scaleAlongSegment(mSelectCursorBase.x, mSelectCursorBase.y,
+                mSelectCursorBaseTextQuad.p4, mSelectCursorBaseTextQuad.p3);
         int x = Math.round(scaleCoordinate(scale,
-                mSelectCursorLeftTextQuad.p1.x, mSelectCursorLeftTextQuad.p2.x));
+                mSelectCursorBaseTextQuad.p1.x, mSelectCursorBaseTextQuad.p2.x));
         int y = Math.round(scaleCoordinate(scale,
-                mSelectCursorLeftTextQuad.p1.y, mSelectCursorLeftTextQuad.p2.y));
+                mSelectCursorBaseTextQuad.p1.y, mSelectCursorBaseTextQuad.p2.y));
         return new Point(x, y);
     }
 
@@ -5138,50 +5250,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() {
@@ -5196,18 +5270,11 @@
     }
 
     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);
-        }
+        int handleId = (mSelectDraggingCursor == mSelectCursorBase)
+                ? HANDLE_ID_BASE : HANDLE_ID_EXTENT;
         mWebViewCore.removeMessages(EventHub.SELECT_TEXT);
-        mWebViewCore.sendMessageAtFrontOfQueue(EventHub.SELECT_TEXT, handles);
+        mWebViewCore.sendMessageAtFrontOfQueue(EventHub.SELECT_TEXT,
+                mSelectDraggingCursor.x, mSelectDraggingCursor.y, (Integer)handleId);
     }
 
     private void resetCaretTimer() {
@@ -5219,14 +5286,6 @@
     }
 
     /**
-     * See {@link WebView#emulateShiftHeld()}
-     */
-    @Override
-    @Deprecated
-    public void emulateShiftHeld() {
-    }
-
-    /**
      * Select all of the text in this WebView.
      *
      * This is an implementation detail.
@@ -5313,16 +5372,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() {
@@ -5334,7 +5383,7 @@
     public void onAttachedToWindow() {
         if (mWebView.hasWindowFocus()) setActive(true);
 
-        if (isAccessibilityEnabled()) {
+        if (isAccessibilityInjectionEnabled()) {
             getAccessibilityInjector().addAccessibilityApisIfNecessary();
         }
 
@@ -5347,7 +5396,7 @@
         mZoomManager.dismissZoomPicker();
         if (mWebView.hasWindowFocus()) setActive(false);
 
-        if (isAccessibilityEnabled()) {
+        if (isAccessibilityInjectionEnabled()) {
             getAccessibilityInjector().removeAccessibilityApisIfNecessary();
         } else {
             // Ensure the injector is cleared if we're detaching from the window
@@ -5570,21 +5619,21 @@
         Point caretTop = calculateCaretTop();
         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;
             }
         }
@@ -5828,28 +5877,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();
                         }
@@ -5894,9 +5934,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);
@@ -6033,12 +6073,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) {
@@ -6145,6 +6188,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() -
@@ -6153,10 +6200,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);
@@ -6172,10 +6246,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) {
@@ -6185,24 +6259,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);
-                    scrollEditText(scrollX, scrollY);
-                    int cursorX = mSelectDraggingCursor.x;
-                    int cursorY = mSelectDraggingCursor.y;
-                    mSelectDraggingCursor.set(x - deltaX, y - deltaY);
+                    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();
-                    mSelectDraggingCursor.set(cursorX, cursorY);
+                    scrollEditText(scrollX, scrollY);
+                    mSelectDraggingCursor.set(oldX, oldY);
                 }
             }
         }
@@ -6258,10 +6335,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
@@ -6362,10 +6439,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);
     }
@@ -6394,9 +6471,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;
                     }
                 }
             }
@@ -6428,9 +6509,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
@@ -6440,6 +6524,7 @@
     private DrawData mDelaySetPicture;
     private DrawData mLoadedPicture;
 
+    @Override
     public void setMapTrackballToArrowKeys(boolean setMap) {
         mMapTrackballToArrowKeys = setMap;
     }
@@ -6666,6 +6751,7 @@
         }
     }
 
+    @Override
     public void flingScroll(int vx, int vy) {
         mScroller.fling(getScrollX(), getScrollY(), vx, vy, 0, computeMaxScrollX(), 0,
                 computeMaxScrollY(), mOverflingDistance, mOverflingDistance);
@@ -6918,6 +7004,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;
@@ -7227,11 +7315,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;
@@ -7317,15 +7401,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();
@@ -7405,7 +7480,7 @@
                     break;
 
                 case SELECTION_STRING_CHANGED:
-                    if (isAccessibilityEnabled()) {
+                    if (isAccessibilityInjectionEnabled()) {
                         getAccessibilityInjector()
                                 .handleSelectionChangedIfNecessary((String) msg.obj);
                     }
@@ -7464,7 +7539,7 @@
                         mEditTextLayerId = initData.mNodeLayerId;
                         nativeMapLayerRect(mNativeClass, mEditTextLayerId,
                                 mEditTextContentBounds);
-                        mEditTextContent.set(initData.mContentRect);
+                        mEditTextContent.set(initData.mClientRect);
                         relocateAutoCompletePopup();
                     }
                     break;
@@ -7545,6 +7620,10 @@
                     scrollEditWithCursor();
                     break;
 
+                case SCROLL_HANDLE_INTO_VIEW:
+                    scrollDraggedSelectionHandleIntoView();
+                    break;
+
                 default:
                     super.handleMessage(msg);
                     break;
@@ -7580,8 +7659,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;
         }
@@ -7869,7 +7948,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
@@ -7928,8 +8009,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)) {
@@ -7938,11 +8021,10 @@
             } else {
                 if (!mSelectingText) {
                     setupWebkitSelect();
-                } else if (!mSelectionStarted) {
-                    syncSelectionCursors();
                 } else {
-                    adjustSelectionCursors();
+                    syncSelectionCursors();
                 }
+                animateHandles();
                 if (mIsCaretSelection) {
                     resetCaretTimer();
                 }
@@ -7958,8 +8040,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() {
@@ -8404,14 +8488,6 @@
     }
 
     /**
-     * See {@link WebView#debugDump()}
-     */
-    @Override
-    @Deprecated
-    public void debugDump() {
-    }
-
-    /**
      * Enable the communication b/t the webView and VideoViewProxy
      *
      * only used by the Browser
@@ -8545,6 +8621,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);
@@ -8565,6 +8689,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();
@@ -8608,4 +8734,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 728ddbf..2d834ff 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);
@@ -839,6 +824,7 @@
     static class JSInterfaceData {
         Object mObject;
         String mInterfaceName;
+        boolean mRequireAnnotation;
     }
 
     static class JSKeyData {
@@ -960,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
@@ -1199,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;
@@ -1306,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: {
@@ -1508,7 +1490,7 @@
                         case ADD_JS_INTERFACE:
                             JSInterfaceData jsData = (JSInterfaceData) msg.obj;
                             mBrowserFrame.addJavascriptInterface(jsData.mObject,
-                                    jsData.mInterfaceName);
+                                    jsData.mInterfaceName, jsData.mRequireAnnotation);
                             break;
 
                         case REMOVE_JS_INTERFACE:
@@ -1660,6 +1642,10 @@
                                     (Set<String>) msg.obj);
                             break;
 
+                        case SET_USE_MOCK_GEOLOCATION:
+                            setUseMockGeolocation();
+                            break;
+
                         case SET_USE_MOCK_DEVICE_ORIENTATION:
                             setUseMockDeviceOrientation();
                             break;
@@ -1708,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: {
@@ -2139,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();
@@ -2192,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;
@@ -2217,12 +2198,20 @@
                 mEventHub.sendMessage(Message.obtain(null, EventHub.WEBKIT_DRAW));
             }
             m_skipDrawFlag = false;
+            m_skipDrawFlagLock.notify();
         }
     }
 
     private void webkitDraw() {
         synchronized (m_skipDrawFlagLock) {
             if (m_skipDrawFlag) {
+                try {
+                    // Aggressively throttle webkit to give the UI more CPU
+                    // to catch up with
+                    m_skipDrawFlagLock.wait(50);
+                } catch (InterruptedException e) {}
+            }
+            if (m_skipDrawFlag) {
                 m_drawWasSkipped = true;
                 return;
             }
@@ -2247,7 +2236,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(
@@ -2330,7 +2318,6 @@
                     Log.w(LOGTAG, "Cannot pauseUpdatePicture, core destroyed or not initialized!");
                     return;
                 }
-                core.nativeSetIsPaused(core.mNativeClass, true);
                 core.mDrawIsPaused = true;
             }
         }
@@ -2348,7 +2335,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;
@@ -2363,13 +2349,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;
     }
 
@@ -2787,14 +2773,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();
         }
     }
 
@@ -2855,7 +2838,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,
@@ -3063,6 +3046,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,
@@ -3089,7 +3088,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);
@@ -3135,7 +3133,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..62ec0d5 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";
 
     /**
@@ -43,50 +45,65 @@
     }
 
     /**
-     * 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..c804b90 100644
--- a/core/java/android/webkit/WebViewDatabaseClassic.java
+++ b/core/java/android/webkit/WebViewDatabaseClassic.java
@@ -100,6 +100,7 @@
     private boolean mInitialized = false;
 
     WebViewDatabaseClassic(final Context context) {
+        JniUtil.setContext(context);
         new Thread() {
             @Override
             public void run() {
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 73ae910..2fc9b39 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";
 
@@ -38,18 +47,45 @@
         // us honest and minimize usage of WebViewClassic internals when binding the proxy.
         if (sProviderInstance != null) return sProviderInstance;
 
-        sProviderInstance = getFactoryByName(DEFAULT_WEB_VIEW_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 explicit linkage");
-            sProviderInstance = new WebViewClassic.Factory();
+            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;
     }
 
-    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/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 437da59..920d44f 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;
@@ -974,6 +973,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);
         }
 
@@ -1329,150 +1334,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
@@ -2297,7 +2158,9 @@
             if (mAccessibilityDelegate == null) {
                 mAccessibilityDelegate = new ListItemAccessibilityDelegate();
             }
-            child.setAccessibilityDelegate(mAccessibilityDelegate);
+            if (child.getAccessibilityDelegate() == null) {
+                child.setAccessibilityDelegate(mAccessibilityDelegate);
+            }
         }
 
         return child;
@@ -6090,6 +5953,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..62253d3 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(getResolvedLayoutDirection());
+            }
 
             // Assuming the thumb drawable is symmetric, set the thumb offset
             // such that the thumb will hang halfway off either edge of the
@@ -301,9 +304,19 @@
         }
         
         // 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);
     }
-    
+
+    @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 +422,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;
         
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/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index 988760d..f79ec42 100755
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -18,17 +18,25 @@
 
 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.PackageUserState;
 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 +44,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,52 +59,202 @@
  * 
  * {@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);
@@ -109,29 +266,40 @@
         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) {
         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>();
         if(pkg == null) {
             return;
         }
+
+        // Convert to a PackageInfo
+        PackageInfo info = PackageParser.generatePackageInfo(pkg, null,
+                PackageManager.GET_PERMISSIONS, 0, 0, null,
+                new PackageUserState());
+        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 (pkg.mSharedUserId != null) {
             int sharedUid;
             try {
                 sharedUid = mPm.getUidForSharedUser(pkg.mSharedUserId);
@@ -141,13 +309,23 @@
             }
         }
         // 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 +333,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 +352,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 +448,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 +559,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..e4d4981 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.app.SearchManager.OnDismissListener;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.database.DataSetObserver;
@@ -579,6 +580,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 +922,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) {
@@ -1078,6 +1094,7 @@
             mPopup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NEEDED);
             mPopup.setListItemExpandMax(EXPAND_MAX);
         }
+        mPopup.setLayoutDirection(getResolvedLayoutDirection());
         mPopup.show();
         mPopup.getListView().setOverScrollMode(View.OVER_SCROLL_ALWAYS);
     }
@@ -1208,6 +1225,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/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index 61935c2..bc78adc 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -151,7 +151,7 @@
             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,12 +169,25 @@
         return mCheckMarkDrawable;
     }
 
+    /**
+     * @hide
+     */
+    @Override
+    protected void internalSetPadding(int left, int top, int right, int bottom) {
+        super.internalSetPadding(left, top, right, bottom);
+        setBasePadding(isLayoutRtl());
+    }
+
     @Override
     public void onPaddingChanged(int layoutDirection) {
         int newPadding = (mCheckMarkDrawable != null) ?
                 mCheckMarkWidth + mBasePadding : mBasePadding;
         mNeedRequestlayout |= (mPaddingRight != newPadding);
-        mPaddingRight = newPadding;
+        if (isLayoutRtl()) {
+            mPaddingLeft = newPadding;
+        } else {
+            mPaddingRight = newPadding;
+        }
         if (mNeedRequestlayout) {
             requestLayout();
             mNeedRequestlayout = false;
@@ -184,13 +197,21 @@
     @Override
     public void setPadding(int left, int top, int right, int bottom) {
         super.setPadding(left, top, right, bottom);
-        mBasePadding = mPaddingRight;
+        setBasePadding(isLayoutRtl());
     }
 
     @Override
     public void setPaddingRelative(int start, int top, int end, int bottom) {
         super.setPaddingRelative(start, top, end, bottom);
-        mBasePadding = getPaddingEnd();
+        setBasePadding(isLayoutRtl());
+    }
+
+    private void setBasePadding(boolean isLayoutRtl) {
+        if (isLayoutRtl) {
+            mBasePadding = mPaddingLeft;
+        } else {
+            mBasePadding = mPaddingRight;
+        }
     }
 
     @Override
@@ -213,12 +234,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/DigitalClock.java b/core/java/android/widget/DigitalClock.java
index add9d9b..3e9107f 100644
--- a/core/java/android/widget/DigitalClock.java
+++ b/core/java/android/widget/DigitalClock.java
@@ -34,13 +34,17 @@
  *
  * FIXME: implement separate views for hours/minutes/seconds, so
  * proportional fonts don't shake rendering
+ * 
+ * @deprecated It is recommended you use a {@link TextView} and {@link DateFormat}
+ * to implement the same behavior.
  */
-
+@Deprecated
 public class DigitalClock extends TextView {
 
     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 +56,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();
         }
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index c29dd58..237275a 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -978,8 +978,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();
         }
     }
 
@@ -1801,13 +1801,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 +2282,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 d019d8c..a025610 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;
@@ -603,6 +603,12 @@
          */
         public int gravity = -1;
 
+        @Override
+        protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
+            width = a.getLayoutDimension(widthAttr, MATCH_PARENT);
+            height = a.getLayoutDimension(heightAttr, MATCH_PARENT);
+        }
+
         /**
          * {@inheritDoc}
          */
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 37e0b90..b6fcb03 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;
             }
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..ea85325 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);
         }
     }
 
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 1d966b3..3baf5a9 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -22,6 +22,7 @@
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.util.AttributeSet;
+import android.util.LocaleUtil;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -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 = LocaleUtil.getLayoutDirectionFromLocale(locale);
     }
 
     /**
@@ -1013,6 +1021,8 @@
                 mDropDownList.setOnItemSelectedListener(mItemSelectedListener);
             }
 
+            mDropDownList.setLayoutDirection(mLayoutDirection);
+
             dropDownView = mDropDownList;
 
             View hintView = mPromptView;
@@ -1122,6 +1132,21 @@
     }
 
     /**
+     * Set the layout direction for this popup. Should be a resolved direction as the
+     * popup as no capacity to do the resolution on his own.
+     *
+     * @param layoutDirection One of {@link View#LAYOUT_DIRECTION_LTR},
+     *   {@link View#LAYOUT_DIRECTION_RTL},
+     *
+     */
+    public void setLayoutDirection(int layoutDirection) {
+        mLayoutDirection = layoutDirection;
+        if (mDropDownList != null) {
+            mDropDownList.setLayoutDirection(mLayoutDirection);
+        }
+    }
+
+    /**
      * <p>Wrapper class for a ListView. This wrapper can hijack the focus to
      * make sure the list uses the appropriate drawables and states when
      * displayed on screen within a drop down. The focus is never actually
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..dbc777e 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -1417,19 +1417,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());
@@ -2297,78 +2284,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 +2305,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 +2425,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) {
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..af3365e 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -835,7 +835,7 @@
        
         preparePopup(p);
         if (gravity == Gravity.NO_GRAVITY) {
-            gravity = Gravity.TOP | Gravity.LEFT;
+            gravity = Gravity.TOP | Gravity.START;
         }
         p.gravity = gravity;
         p.x = x;
@@ -1003,7 +1003,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 +1100,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 +1134,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;
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index f3f18d5..b6d0995 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -354,7 +354,7 @@
                     Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
             shapeDrawable.getPaint().setShader(bitmapShader);
 
-            return (clip) ? new ClipDrawable(shapeDrawable, Gravity.LEFT,
+            return (clip) ? new ClipDrawable(shapeDrawable, Gravity.START,
                     ClipDrawable.HORIZONTAL) : shapeDrawable;
         }
         
@@ -478,6 +478,9 @@
             d.setCallback(this);
         }
         mIndeterminateDrawable = d;
+        if (mIndeterminateDrawable != null && canResolveLayoutDirection()) {
+            mIndeterminateDrawable.setLayoutDirection(getResolvedLayoutDirection());
+        }
         if (mIndeterminate) {
             mCurrentDrawable = d;
             postInvalidate();
@@ -517,6 +520,9 @@
 
         if (d != null) {
             d.setCallback(this);
+            if (canResolveLayoutDirection()) {
+                d.setLayoutDirection(getResolvedLayoutDirection());
+            }
 
             // Make sure the ProgressBar is always tall enough
             int drawableHeight = d.getMinimumHeight();
@@ -560,6 +566,20 @@
     }
 
     @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) {
             super.postInvalidate();
@@ -648,6 +668,9 @@
 
             if (d instanceof LayerDrawable) {
                 progressDrawable = ((LayerDrawable) d).findDrawableByLayerId(id);
+                if (progressDrawable != null && canResolveLayoutDirection()) {
+                    progressDrawable.setLayoutDirection(getResolvedLayoutDirection());
+                }
             }
 
             final int level = (int) (scale * MAX_LEVEL);
@@ -975,24 +998,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;
 
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index f217c9c..42d63b2 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -297,33 +297,6 @@
         public LayoutParams(MarginLayoutParams source) {
             super(source);
         }
-
-        /**
-         * <p>Fixes the child's width to
-         * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} and the child's
-         * height to  {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}
-         * when not specified in the XML file.</p>
-         *
-         * @param a the styled attributes set
-         * @param widthAttr the width attribute to fetch
-         * @param heightAttr the height attribute to fetch
-         */
-        @Override
-        protected void setBaseAttributes(TypedArray a,
-                int widthAttr, int heightAttr) {
-
-            if (a.hasValue(widthAttr)) {
-                width = a.getLayoutDimension(widthAttr, "layout_width");
-            } else {
-                width = WRAP_CONTENT;
-            }
-            
-            if (a.hasValue(heightAttr)) {
-                height = a.getLayoutDimension(heightAttr, "layout_height");
-            } else {
-                height = WRAP_CONTENT;
-            }
-        }
     }
 
     /**
@@ -376,7 +349,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..43519df 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 = getResolvedLayoutDirection();
+
         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 = getResolvedLayoutDirection();
+        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,9 @@
     private boolean positionChildHorizontal(View child, LayoutParams params, int myWidth,
             boolean wrapContent) {
 
-        int[] rules = params.getRules();
+        final int layoutDirection = getResolvedLayoutDirection();
+        int[] rules = params.getRules(layoutDirection);
+        params.onResolveLayoutDirection(layoutDirection);
 
         if (params.mLeft < 0 && params.mRight >= 0) {
             // Right is fixed, but left varies
@@ -718,11 +748,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 +792,8 @@
     }
 
     private void applyHorizontalSizeRules(LayoutParams childParams, int myWidth) {
-        int[] rules = childParams.getRules();
+        final int layoutDirection = getResolvedLayoutDirection();
+        int[] rules = childParams.getRules(layoutDirection);
         RelativeLayout.LayoutParams anchorParams;
 
         // -1 indicated a "soft requirement" in that direction. For example:
@@ -945,8 +983,8 @@
             if (child.getVisibility() != GONE) {
                 RelativeLayout.LayoutParams st =
                         (RelativeLayout.LayoutParams) child.getLayoutParams();
+                st.onResolveLayoutDirection(getResolvedLayoutDirection());
                 child.layout(st.mLeft, st.mTop, st.mRight, st.mBottom);
-
             }
         }
     }
@@ -1061,6 +1099,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 +1123,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 +1159,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 +1216,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 +1272,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 +1282,8 @@
          */
         public void addRule(int verb) {
             mRules[verb] = TRUE;
+            mInitialRules[verb] = TRUE;
+            mRulesChanged = true;
         }
 
         /**
@@ -1220,12 +1302,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 +1391,24 @@
         public int[] getRules() {
             return mRules;
         }
+
+        @Override
+        public void onResolveLayoutDirection(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.onResolveLayoutDirection(layoutDirection);
+        }
     }
 
     private static class DependencyGraph {
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 4710798f..c65a67b 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -61,9 +61,9 @@
  * the content of the inflated hierarchy.
  */
 public class RemoteViews implements Parcelable, Filter {
-    
+
     private static final String LOG_TAG = "RemoteViews";
-    
+
     /**
      * The intent extra that contains the appWidgetId.
      * @hide
@@ -71,11 +71,11 @@
     static final String EXTRA_REMOTEADAPTER_APPWIDGET_ID = "remoteAdapterAppWidgetId";
 
     /**
-     * The package name of the package containing the layout 
+     * The package name of the package containing the layout
      * resource. (Added to the parcel)
      */
     private final String mPackage;
-    
+
     /**
      * The resource ID of the layout file. (Added to the parcel)
      */
@@ -86,7 +86,7 @@
      * inflated
      */
     private ArrayList<Action> mActions;
-    
+
     /**
      * A class to keep track of memory usage by this RemoteViews
      */
@@ -522,13 +522,13 @@
                                     .getCompatibilityInfo().applicationScale;
                             final int[] pos = new int[2];
                             v.getLocationOnScreen(pos);
-    
+
                             final Rect rect = new Rect();
                             rect.left = (int) (pos[0] * appScale + 0.5f);
                             rect.top = (int) (pos[1] * appScale + 0.5f);
                             rect.right = (int) ((pos[0] + v.getWidth()) * appScale + 0.5f);
                             rect.bottom = (int) ((pos[1] + v.getHeight()) * appScale + 0.5f);
-    
+
                             final Intent intent = new Intent();
                             intent.setSourceBounds(rect);
                             handler.onClickHandler(v, pendingIntent, intent);
@@ -567,7 +567,7 @@
             this.filterMode = mode;
             this.level = level;
         }
-        
+
         public SetDrawableParameters(Parcel parcel) {
             viewId = parcel.readInt();
             targetBackground = parcel.readInt() != 0;
@@ -581,7 +581,7 @@
             }
             level = parcel.readInt();
         }
-        
+
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeInt(TAG);
             dest.writeInt(viewId);
@@ -596,12 +596,12 @@
             }
             dest.writeInt(level);
         }
-        
+
         @Override
         public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
             final View target = root.findViewById(viewId);
             if (target == null) return;
-            
+
             // Pick the correct drawable to modify for this view
             Drawable targetDrawable = null;
             if (targetBackground) {
@@ -610,7 +610,7 @@
                 ImageView imageView = (ImageView) target;
                 targetDrawable = imageView.getDrawable();
             }
-            
+
             if (targetDrawable != null) {
                 // Perform modifications only if values are set correctly
                 if (alpha != -1) {
@@ -634,7 +634,7 @@
 
         public final static int TAG = 3;
     }
-    
+
     private class ReflectionActionWithoutParams extends Action {
         int viewId;
         String methodName;
@@ -938,7 +938,7 @@
                     out.writeString((String)this.value);
                     break;
                 case CHAR_SEQUENCE:
-                    TextUtils.writeToParcel((CharSequence)this.value, out, flags);   
+                    TextUtils.writeToParcel((CharSequence)this.value, out, flags);
                     break;
                 case URI:
                     out.writeInt(this.value != null ? 1 : 0);
@@ -1314,7 +1314,7 @@
     /**
      * Create a new RemoteViews object that will display the views contained
      * in the specified layout file.
-     * 
+     *
      * @param packageName Name of the package that contains the layout resource
      * @param layoutId The id of the layout resource
      */
@@ -1364,7 +1364,7 @@
 
     /**
      * Reads a RemoteViews object from a parcel.
-     * 
+     *
      * @param parcel
      */
     public RemoteViews(Parcel parcel) {
@@ -1547,7 +1547,7 @@
 
     /**
      * Add an action to be executed on the remote side when apply is called.
-     * 
+     *
      * @param a The action to add
      */
     private void addAction(Action a) {
@@ -1619,7 +1619,7 @@
 
     /**
      * Equivalent to calling View.setVisibility
-     * 
+     *
      * @param viewId The id of the view whose visibility should change
      * @param visibility The new visibility for the view
      */
@@ -1629,7 +1629,7 @@
 
     /**
      * Equivalent to calling TextView.setText
-     * 
+     *
      * @param viewId The id of the view whose text should change
      * @param text The new text for the view
      */
@@ -1639,7 +1639,7 @@
 
     /**
      * Equivalent to calling {@link TextView#setTextSize(int, float)}
-     * 
+     *
      * @param viewId The id of the view whose text size should change
      * @param units The units of size (e.g. COMPLEX_UNIT_SP)
      * @param size The size of the text
@@ -1649,20 +1649,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 +1679,17 @@
 
     /**
      * Equivalent to calling ImageView.setImageResource
-     * 
+     *
      * @param viewId The id of the view whose drawable should change
      * @param srcId The new resource id for the drawable
      */
-    public void setImageViewResource(int viewId, int srcId) {   
+    public void setImageViewResource(int viewId, int srcId) {
         setInt(viewId, "setImageResource", srcId);
     }
 
     /**
      * Equivalent to calling ImageView.setImageURI
-     * 
+     *
      * @param viewId The id of the view whose drawable should change
      * @param uri The Uri for the image
      */
@@ -1696,7 +1699,7 @@
 
     /**
      * Equivalent to calling ImageView.setImageBitmap
-     * 
+     *
      * @param viewId The id of the view whose bitmap should change
      * @param bitmap The new Bitmap for the drawable
      */
@@ -1719,7 +1722,7 @@
      * {@link Chronometer#setFormat Chronometer.setFormat},
      * and {@link Chronometer#start Chronometer.start()} or
      * {@link Chronometer#stop Chronometer.stop()}.
-     * 
+     *
      * @param viewId The id of the {@link Chronometer} to change
      * @param base The time at which the timer would have read 0:00.  This
      *             time should be based off of
@@ -1733,21 +1736,21 @@
         setString(viewId, "setFormat", format);
         setBoolean(viewId, "setStarted", started);
     }
-    
+
     /**
      * Equivalent to calling {@link ProgressBar#setMax ProgressBar.setMax},
      * {@link ProgressBar#setProgress ProgressBar.setProgress}, and
      * {@link ProgressBar#setIndeterminate ProgressBar.setIndeterminate}
      *
      * If indeterminate is true, then the values for max and progress are ignored.
-     * 
+     *
      * @param viewId The id of the {@link ProgressBar} to change
      * @param max The 100% value for the progress bar
      * @param progress The current value of the progress bar.
-     * @param indeterminate True if the progress bar is indeterminate, 
+     * @param indeterminate True if the progress bar is indeterminate,
      *                false if not.
      */
-    public void setProgressBar(int viewId, int max, int progress, 
+    public void setProgressBar(int viewId, int max, int progress,
             boolean indeterminate) {
         setBoolean(viewId, "setIndeterminate", indeterminate);
         if (!indeterminate) {
@@ -1755,12 +1758,12 @@
             setInt(viewId, "setProgress", progress);
         }
     }
-    
+
     /**
      * Equivalent to calling
      * {@link android.view.View#setOnClickListener(android.view.View.OnClickListener)}
      * to launch the provided {@link PendingIntent}.
-     * 
+     *
      * When setting the on-click action of items within collections (eg. {@link ListView},
      * {@link StackView} etc.), this method will not work. Instead, use {@link
      * RemoteViews#setPendingIntentTemplate(int, PendingIntent) in conjunction with
@@ -1820,7 +1823,7 @@
      * view.
      * <p>
      * You can omit specific calls by marking their values with null or -1.
-     * 
+     *
      * @param viewId The id of the view that contains the target
      *            {@link Drawable}
      * @param targetBackground If true, apply these parameters to the
@@ -1846,7 +1849,7 @@
 
     /**
      * Equivalent to calling {@link android.widget.TextView#setTextColor(int)}.
-     * 
+     *
      * @param viewId The id of the view whose text color should change
      * @param color Sets the text color for all the states (normal, selected,
      *            focused) to be this color.
@@ -2074,15 +2077,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 +2111,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 +2148,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 +2176,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);
@@ -2191,7 +2205,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/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..9b62a51 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 onResolvedLayoutDirectionChanged() {
+        mQueryTextView.setLayoutDirection(getResolvedLayoutDirection());
+    }
+
     /**
      * Query rewriting.
      */
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..ecd7277 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -355,7 +355,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 +460,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 +492,9 @@
         View sel = makeAndAddView(mSelectedPosition);
         int width = sel.getMeasuredWidth();
         int selectedOffset = childrenLeft;
-        switch (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
+        final int layoutDirection = getResolvedLayoutDirection();
+        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 +941,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,17 +960,20 @@
                 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);
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..113299a 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
@@ -739,11 +743,7 @@
         @Override
         protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
             this.width = MATCH_PARENT;
-            if (a.hasValue(heightAttr)) {
-                this.height = a.getLayoutDimension(heightAttr, "layout_height");
-            } else {
-                this.height = WRAP_CONTENT;
-            }
+            this.height = a.getLayoutDimension(heightAttr, WRAP_CONTENT);
         }
     }
 
diff --git a/core/java/android/widget/TableRow.java b/core/java/android/widget/TableRow.java
index 01c4c2c..fb548df 100644
--- a/core/java/android/widget/TableRow.java
+++ b/core/java/android/widget/TableRow.java
@@ -502,19 +502,8 @@
 
         @Override
         protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
-            // We don't want to force users to specify a layout_width
-            if (a.hasValue(widthAttr)) {
-                width = a.getLayoutDimension(widthAttr, "layout_width");
-            } else {
-                width = MATCH_PARENT;
-            }
-
-            // We don't want to force users to specify a layout_height
-            if (a.hasValue(heightAttr)) {
-                height = a.getLayoutDimension(heightAttr, "layout_height");
-            } else {
-                height = WRAP_CONTENT;
-            }
+            width = a.getLayoutDimension(widthAttr, MATCH_PARENT);
+            height = a.getLayoutDimension(heightAttr, WRAP_CONTENT);
         }
     }
 
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 01617da..dd2ff35 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -302,6 +302,7 @@
 
     // The alignment to pass to Layout, or null if not resolved.
     private Layout.Alignment mLayoutAlignment;
+    private int mResolvedTextAlignment;
 
     private boolean mResolvedDrawables;
 
@@ -1542,7 +1543,6 @@
     /**
      * Returns the start padding of the view, plus space for the start
      * Drawable if any.
-     * @hide
      */
     public int getCompoundPaddingStart() {
         resolveDrawables();
@@ -1558,7 +1558,6 @@
     /**
      * Returns the end padding of the view, plus space for the end
      * Drawable if any.
-     * @hide
      */
     public int getCompoundPaddingEnd() {
         resolveDrawables();
@@ -1656,7 +1655,6 @@
     /**
      * Returns the total start padding of the view, including the start
      * Drawable if any.
-     * @hide
      */
     public int getTotalPaddingStart() {
         return getCompoundPaddingStart();
@@ -1665,7 +1663,6 @@
     /**
      * Returns the total end padding of the view, including the end
      * Drawable if any.
-     * @hide
      */
     public int getTotalPaddingEnd() {
         return getCompoundPaddingEnd();
@@ -1868,7 +1865,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 +1986,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 +2009,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 +2055,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 +2204,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 +4463,6 @@
 
         mTemporaryDetach = false;
 
-        // Resolve drawables as the layout direction has been resolved
-        resolveDrawables();
-
         if (mEditor != null) mEditor.onAttachedToWindow();
     }
 
@@ -4586,23 +4597,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 +4856,23 @@
         }
         canvas.translate(compoundPaddingLeft, extendedPaddingTop + voffsetText);
 
+        final boolean isLayoutRtl = isLayoutRtl();
+
         final int layoutDirection = getResolvedLayoutDirection();
         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 +4886,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 +5634,11 @@
                       physicalWidth, false);
     }
 
-    /** @hide */
     @Override
     public void onResolvedLayoutDirectionReset() {
         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 +5646,8 @@
 
     private Layout.Alignment getLayoutAlignment() {
         if (mLayoutAlignment == null) {
-            int textAlign = getResolvedTextAlignment();
-            switch (textAlign) {
+            mResolvedTextAlignment = getResolvedTextAlignment();
+            switch (mResolvedTextAlignment) {
                 case TEXT_ALIGNMENT_GRAVITY:
                     switch (mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) {
                         case Gravity.START:
@@ -7481,7 +7479,8 @@
             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;
                 }
@@ -7509,7 +7508,9 @@
                 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 absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
@@ -8180,7 +8181,6 @@
         return mEditor.mInBatchEditControllers;
     }
 
-    /** @hide */
     @Override
     public void onResolvedTextDirectionChanged() {
         if (hasPasswordTransformationMethod()) {
@@ -8216,13 +8216,8 @@
         }
     }
 
-    /**
-     * 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.
-     */
-    protected void resolveDrawables() {
+    @Override
+    public void onResolveDrawables(int layoutDirection) {
         // No need to resolve twice
         if (mResolvedDrawables) {
             return;
@@ -8238,7 +8233,7 @@
         }
 
         Drawables dr = mDrawables;
-        switch(getResolvedLayoutDirection()) {
+        switch(layoutDirection) {
             case LAYOUT_DIRECTION_RTL:
                 if (dr.mDrawableStart != null) {
                     dr.mDrawableRight = dr.mDrawableStart;
@@ -8270,9 +8265,25 @@
                 }
                 break;
         }
+        updateDrawablesLayoutDirection(dr, layoutDirection);
         mResolvedDrawables = true;
     }
 
+    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);
+        }
+    }
+
     protected void resetResolvedDrawables() {
         mResolvedDrawables = false;
     }
@@ -8341,7 +8352,7 @@
      */
     @Override
     public CharSequence getIterableTextForAccessibility() {
-        if (getContentDescription() == null) {
+        if (!TextUtils.isEmpty(mText)) {
             if (!(mText instanceof Spannable)) {
                 setText(mText, BufferType.SPANNABLE);
             }
@@ -8593,13 +8604,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 +8702,14 @@
             return mGhostOffset;
         }
 
+        float getScroll() {
+            return mScroll;
+        }
+
+        float getMaxFadeScroll() {
+            return mMaxFadeScroll;
+        }
+
         boolean shouldDrawLeftFade() {
             return mScroll <= mFadeStop;
         }
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 2061c90..bcf0ea4 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -751,6 +751,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/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/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 7334ac3..bffbe11 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;
@@ -149,7 +150,8 @@
 
             resizeGrid();
         } else if (count == 1) {
-            startActivity(mAdapter.intentForPosition(0));
+            startActivityAsUser(mAdapter.intentForPosition(0),
+                    new UserHandle(UserHandle.getUserId(mLaunchedFromUid)));
             mPackageMonitor.unregister();
             mRegistered = false;
             finish();
@@ -247,6 +249,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 +260,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);
         }
@@ -360,19 +364,20 @@
                     if (r.match > bestMatch) bestMatch = r.match;
                 }
                 getPackageManager().addPreferredActivity(filter, bestMatch, set,
-                        intent.getComponent());
+                        intent.getComponent(), UserHandle.getUserId(mLaunchedFromUid));
             }
         }
 
         if (intent != null) {
-            startActivity(intent);
+            startActivityAsUser(intent, new UserHandle(UserHandle.getUserId(mLaunchedFromUid)));
         }
     }
 
     void showAppDetails(ResolveInfo ri) {
         Intent in = new Intent().setAction("android.settings.APPLICATION_DETAILS_SETTINGS")
-                .setData(Uri.fromParts("package", ri.activityInfo.packageName, null));
-        startActivity(in);
+                .setData(Uri.fromParts("package", ri.activityInfo.packageName, null))
+                .addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+        startActivityAsUser(in, new UserHandle(UserHandle.getUserId(mLaunchedFromUid)));
     }
 
     private final class DisplayResolveInfo {
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..3477a90 100644
--- a/core/java/com/android/internal/content/PackageMonitor.java
+++ b/core/java/com/android/internal/content/PackageMonitor.java
@@ -49,6 +49,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);
     }
@@ -111,16 +112,22 @@
     
     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) {
     }
-    
+
     public void onPackageUpdateStarted(String packageName, int uid) {
     }
-    
+
     public void onPackageUpdateFinished(String packageName, int uid) {
     }
     
@@ -130,6 +137,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 +154,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) {
     }
     
@@ -295,6 +311,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;
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..7287327
--- /dev/null
+++ b/core/java/com/android/internal/net/VpnProfile.java
@@ -0,0 +1,181 @@
+/*
+ * 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 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;
+        }
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(key);
+        out.writeByteArray(encode());
+    }
+
+    public static final Creator<VpnProfile> CREATOR = new Creator<VpnProfile>() {
+        @Override
+        public VpnProfile createFromParcel(Parcel in) {
+            final String key = in.readString();
+            return decode(key, in.createByteArray());
+        }
+
+        @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/statusbar/StatusBarNotification.java b/core/java/com/android/internal/statusbar/StatusBarNotification.java
index d443523..cb87ac4 100644
--- a/core/java/com/android/internal/statusbar/StatusBarNotification.java
+++ b/core/java/com/android/internal/statusbar/StatusBarNotification.java
@@ -19,6 +19,7 @@
 import android.app.Notification;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.UserHandle;
 import android.widget.RemoteViews;
 
 
@@ -132,6 +133,11 @@
         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 UserHandle.getUserId(this.uid);
+    }
 }
 
 
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 699e9b3..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..98beadb 100644
--- a/core/java/com/android/internal/view/RotationPolicy.java
+++ b/core/java/com/android/internal/view/RotationPolicy.java
@@ -27,6 +27,7 @@
 import android.util.Log;
 import android.view.IWindowManager;
 import android.view.Surface;
+import android.view.WindowManagerGlobal;
 
 /**
  * Provides helper functions for configuring the display rotation policy.
@@ -79,8 +80,7 @@
             @Override
             public void run() {
                 try {
-                    IWindowManager wm = IWindowManager.Stub.asInterface(
-                            ServiceManager.getService(Context.WINDOW_SERVICE));
+                    IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
                     if (enabled) {
                         wm.freezeRotation(-1);
                     } else {
@@ -107,8 +107,7 @@
             @Override
             public void run() {
                 try {
-                    IWindowManager wm = IWindowManager.Stub.asInterface(
-                            ServiceManager.getService(Context.WINDOW_SERVICE));
+                    IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
                     if (enabled) {
                         wm.freezeRotation(Surface.ROTATION_0);
                     } else {
diff --git a/core/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..2811332 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -576,6 +576,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..c7c8571 100644
--- a/core/java/com/android/internal/view/menu/IconMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/IconMenuItemView.java
@@ -282,7 +282,7 @@
         getLineBounds(0, tmpRect);
         mPositionIconAvailable.set(0, 0, getWidth(), tmpRect.top);
         final int layoutDirection = getResolvedLayoutDirection();
-        Gravity.apply(Gravity.CENTER_VERTICAL | Gravity.LEFT, mIcon.getIntrinsicWidth(), mIcon
+        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..6bcaa0e 100644
--- a/core/java/com/android/internal/widget/ActionBarContainer.java
+++ b/core/java/com/android/internal/widget/ActionBarContainer.java
@@ -77,20 +77,104 @@
     }
 
     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();
+        }
+    }
+
+    @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..8bc1081 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..2108d0d 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;
@@ -847,7 +848,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 +856,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 +872,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 +1010,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 +1017,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 +1042,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 +1050,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 +1088,64 @@
             customView = mCustomNavView;
         }
         if (customView != null) {
+            final int resolvedLayoutDirection = getResolvedLayoutDirection();
             ViewGroup.LayoutParams lp = customView.getLayoutParams();
+            lp.onResolveLayoutDirection(resolvedLayoutDirection);
             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, resolvedLayoutDirection)) {
                 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 +1168,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 +1271,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 +1321,7 @@
             mIconView = (ImageView) findViewById(com.android.internal.R.id.home);
         }
 
-        public int getLeftOffset() {
+        public int getStartOffset() {
             return mUpView.getVisibility() == GONE ? mUpWidth : 0;
         }
 
@@ -1340,25 +1371,51 @@
         @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 layoutDirection = getResolvedLayoutDirection();
+            final int width = getWidth();
             int upOffset = 0;
             if (mUpView.getVisibility() != GONE) {
                 final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams();
+                upLp.onResolveLayoutDirection(layoutDirection);
                 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();
+            iconLp.onResolveLayoutDirection(layoutDirection);
             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/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index f77e8f3..0710d96 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -20,6 +20,7 @@
 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.content.ContentResolver;
@@ -34,7 +35,7 @@
 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;
@@ -225,7 +226,11 @@
 
     public int getCurrentUser() {
         if (Process.myUid() == Process.SYSTEM_UID) {
-            return mCurrentUserId;
+            try {
+                return ActivityManagerNative.getDefault().getCurrentUser().id;
+            } catch (RemoteException re) {
+                return mCurrentUserId;
+            }
         } else {
             throw new SecurityException("Only the system process can get the current user");
         }
@@ -246,7 +251,7 @@
         if (callingUid == android.os.Process.SYSTEM_UID) {
             return mCurrentUserId;
         } else {
-            return UserId.getUserId(callingUid);
+            return UserHandle.getUserId(callingUid);
         }
     }
 
@@ -1001,6 +1006,17 @@
         }
     }
 
+    public int[] getUserDefinedWidgets() {
+        int appWidgetId = -1;
+        String appWidgetIdString = Settings.Secure.getString(
+                mContentResolver, Settings.Secure.LOCK_SCREEN_USER_SELECTED_APPWIDGET_ID);
+        if (appWidgetIdString != null) {
+            appWidgetId = (int) Integer.decode(appWidgetIdString);
+        }
+
+        return new int[] { appWidgetId };
+    }
+
     private long getLong(String secureSettingKey, long defaultValue) {
         try {
             return getLockSettings().getLong(secureSettingKey, defaultValue,
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/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
index 83ac896..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/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/multiwaveview/GlowPadView.java b/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java
index 4e60b75..421e247 100644
--- a/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java
@@ -214,8 +214,8 @@
                 mVibrationDuration);
         mFeedbackCount = a.getInt(R.styleable.GlowPadView_feedbackCount,
                 mFeedbackCount);
-        mHandleDrawable = new TargetDrawable(res,
-                a.peekValue(R.styleable.GlowPadView_handleDrawable).resourceId);
+        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));
@@ -717,7 +717,7 @@
         startBackgroundAnimation(0, 0.0f);
         stopAndHideWaveAnimation();
         hideTargets(animate, false);
-        hideGlow(0, 0, 1.0f, null);
+        hideGlow(0, 0, 0.0f, null);
         Tweener.reset();
     }
 
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 6f3653d..5f6042d 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 \
@@ -233,7 +228,6 @@
 	external/dbus \
 	system/bluetooth/bluez-clean-headers
 LOCAL_CFLAGS += -DHAVE_BLUETOOTH
-LOCAL_SHARED_LIBRARIES += libbluedroid libdbus
 endif
 
 LOCAL_SHARED_LIBRARIES += \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index d08e651..27684d7 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);
@@ -1092,7 +1088,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 +1096,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 +1162,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/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 6b74705..5c27602 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -766,15 +766,64 @@
         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 = 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,
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index a4d5477..1f70c66 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -22,6 +22,7 @@
 #include "jni.h"
 #include "GraphicsJNI.h"
 #include <android_runtime/AndroidRuntime.h>
+#include <ScopedUtfChars.h>
 
 #include "SkBlurDrawLooper.h"
 #include "SkColorFilter.h"
@@ -30,6 +31,7 @@
 #include "SkShader.h"
 #include "SkTypeface.h"
 #include "SkXfermode.h"
+#include "unicode/uloc.h"
 #include "unicode/ushape.h"
 #include "TextLayout.h"
 
@@ -254,11 +256,51 @@
         obj->setTextAlign(align);
     }
 
+    // generate bcp47 identifier for the supplied locale
+    static void toLanguageTag(char* output, size_t outSize,
+            const char* locale) {
+        if (output == NULL || outSize <= 0) {
+            return;
+        }
+        if (locale == NULL) {
+            output[0] = '\0';
+            return;
+        }
+        char canonicalChars[ULOC_FULLNAME_CAPACITY];
+        UErrorCode uErr = U_ZERO_ERROR;
+        uloc_canonicalize(locale, canonicalChars, ULOC_FULLNAME_CAPACITY,
+                &uErr);
+        if (U_SUCCESS(uErr)) {
+            char likelyChars[ULOC_FULLNAME_CAPACITY];
+            uErr = U_ZERO_ERROR;
+            uloc_addLikelySubtags(canonicalChars, likelyChars,
+                    ULOC_FULLNAME_CAPACITY, &uErr);
+            if (U_SUCCESS(uErr)) {
+                uErr = U_ZERO_ERROR;
+                uloc_toLanguageTag(likelyChars, output, outSize, FALSE, &uErr);
+                if (U_SUCCESS(uErr)) {
+                    return;
+                } else {
+                    ALOGD("uloc_toLanguageTag(\"%s\") failed: %s", likelyChars,
+                            u_errorName(uErr));
+                }
+            } else {
+                ALOGD("uloc_addLikelySubtags(\"%s\") failed: %s",
+                        canonicalChars, u_errorName(uErr));
+            }
+        } else {
+            ALOGD("uloc_canonicalize(\"%s\") failed: %s", locale,
+                    u_errorName(uErr));
+        }
+        // unable to build a proper language identifier
+        output[0] = '\0';
+    }
+
     static void setTextLocale(JNIEnv* env, jobject clazz, SkPaint* obj, jstring locale) {
-        const char* localeArray = env->GetStringUTFChars(locale, NULL);
-        SkString skLocale(localeArray);
-        obj->setTextLocale(skLocale);
-        env->ReleaseStringUTFChars(locale, localeArray);
+        ScopedUtfChars localeChars(env, locale);
+        char langTag[ULOC_FULLNAME_CAPACITY];
+        toLanguageTag(langTag, ULOC_FULLNAME_CAPACITY, localeChars.c_str());
+        obj->setLanguage(SkLanguage(langTag));
     }
 
     static jfloat getTextSize(JNIEnv* env, jobject paint) {
diff --git a/core/jni/android/graphics/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/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index c48b974..bc58813 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -223,6 +223,10 @@
     } else if (err < 0) {
         jniThrowRuntimeException(env, "Error during updateTexImage (see logcat for details)");
     }
+    err = surfaceTexture->doGLFenceWait();
+    if (err != NO_ERROR) {
+        jniThrowRuntimeException(env, "Error waiting for fence (see logcat for details)");
+    }
 }
 
 static jint SurfaceTexture_detachFromGLContext(JNIEnv* env, jobject thiz)
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 35f82a8..8032ed8 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();
 }
 
 /*
@@ -232,7 +227,7 @@
  */
 TextLayoutCacheKey::TextLayoutCacheKey(): text(NULL), start(0), count(0), contextCount(0),
         dirFlags(0), typeface(NULL), textSize(0), textSkewX(0), textScaleX(0), flags(0),
-        hinting(SkPaint::kNo_Hinting)  {
+        hinting(SkPaint::kNo_Hinting), variant(SkPaint::kDefault_Variant), language()  {
 }
 
 TextLayoutCacheKey::TextLayoutCacheKey(const SkPaint* paint, const UChar* text,
@@ -245,6 +240,8 @@
     textScaleX = paint->getTextScaleX();
     flags = paint->getFlags();
     hinting = paint->getHinting();
+    variant = paint->getFontVariant();
+    language = paint->getLanguage();
 }
 
 TextLayoutCacheKey::TextLayoutCacheKey(const TextLayoutCacheKey& other) :
@@ -259,7 +256,9 @@
         textSkewX(other.textSkewX),
         textScaleX(other.textScaleX),
         flags(other.flags),
-        hinting(other.hinting) {
+        hinting(other.hinting),
+        variant(other.variant),
+        language(other.language) {
     if (other.text) {
         textCopy.setTo(other.text, other.contextCount);
     }
@@ -296,6 +295,12 @@
     deltaInt = lhs.dirFlags - rhs.dirFlags;
     if (deltaInt) return (deltaInt);
 
+    deltaInt = lhs.variant - rhs.variant;
+    if (deltaInt) return (deltaInt);
+
+    if (lhs.language < rhs.language) return -1;
+    if (lhs.language > rhs.language) return +1;
+
     return memcmp(lhs.getText(), rhs.getText(), lhs.contextCount * sizeof(UChar));
 }
 
@@ -316,11 +321,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 +343,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 +355,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 +370,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 +380,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 +447,7 @@
                                 ALOGW("Visual run is not valid");
                                 outGlyphs->clear();
                                 outAdvances->clear();
+                                outPos->clear();
                                 *outTotalAdvance = 0;
                                 isRTL = (paraDir == 1);
                                 useSingleRun = true;
@@ -483,15 +470,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 +499,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 +521,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 +623,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):
@@ -716,7 +703,6 @@
             currentAdvance = HBFixedToFloat(mShaperItem.advances[i]);
             totalFontRunAdvance += currentAdvance;
         }
-        totalAdvance += totalFontRunAdvance;
 
 #if DEBUG_ADVANCES
         ALOGD("Returned advances");
@@ -741,6 +727,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 +768,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 +809,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 +907,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 +967,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..1f4e22c 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
@@ -101,6 +102,8 @@
     SkScalar textScaleX;
     uint32_t flags;
     SkPaint::Hinting hinting;
+    SkPaint::FontVariant variant;
+    SkLanguage language;
 
     inline const UChar* getText() const { return text ? text : textCopy.string(); }
 
@@ -129,6 +132,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 +151,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 +198,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 +225,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 +276,7 @@
     /**
      * Clear the cache
      */
-    void clear();
+    void purgeCaches();
 
 private:
     TextLayoutShaper* mShaper;
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..e1e97a1 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -781,6 +781,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)
 {
@@ -890,6 +909,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 },
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_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..78f989a 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 },
+    { "elapsedRealtimeNano",      "()J",
+            (void*) android_os_SystemClock_elapsedRealtimeNano },
 };
 int register_android_os_SystemClock(JNIEnv* env)
 {
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_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index a51b77e..2ff886e 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>
@@ -150,7 +151,7 @@
 }
 
 static jint android_view_GLES20Canvas_getStencilSize(JNIEnv* env, jobject clazz) {
-    return OpenGLRenderer::getStencilSize();
+    return Stencil::getStencilSize();
 }
 
 // ----------------------------------------------------------------------------
@@ -528,8 +529,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 +560,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,
@@ -759,14 +766,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,
@@ -803,10 +833,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);
@@ -968,14 +994,16 @@
 
     { "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 },
     { "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 },
 
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 5739cbe..fc04cd1 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,51 @@
 #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 <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;
+} 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 +98,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 +150,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 +517,68 @@
     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 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 +587,170 @@
     }
 
     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) {
+    ScopedUtfChars name(env, nameObj);
+    sp<IBinder> token(SurfaceComposerClient::createDisplay(String8(name.c_str())));
+    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);
+    return JNI_TRUE;
+}
+
 // ----------------------------------------------------------------------------
 
-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 +762,122 @@
     // 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 },
+    {"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;)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 },
+    {"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");
     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 8777131..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 6546fed..89d78b6 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -43,6 +43,7 @@
     <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.CONFIGURATION_CHANGED" />
     <protected-broadcast android:name="android.intent.action.LOCALE_CHANGED" />
@@ -62,6 +63,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 +110,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 +127,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" />
@@ -139,39 +146,11 @@
     <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 +162,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 +248,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,14 +274,21 @@
     <!-- 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 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. -->
     <permission android:name="android.permission.READ_CALL_LOG"
-        android:permissionGroup="android.permission-group.PERSONAL_INFO"
+        android:permissionGroup="android.permission-group.SOCIAL_INFO"
         android:protectionLevel="dangerous"
         android:label="@string/permlab_readCallLog"
         android:description="@string/permdesc_readCallLog" />
@@ -287,11 +296,42 @@
     <!-- Allows an application to write (but not read) the user's
          contacts data. -->
     <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 +347,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 +376,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 +439,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,7 +495,9 @@
     <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 -->
     <permission android:name="android.permission.ACCESS_FINE_LOCATION"
@@ -413,14 +515,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 +544,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 +568,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,13 +583,39 @@
         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 applications to perform I/O operations over NFC -->
     <permission android:name="android.permission.NFC"
         android:permissionGroup="android.permission-group.NETWORK"
@@ -486,28 +623,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 +643,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 +677,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 +757,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 +796,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. -->
@@ -679,6 +888,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,11 +913,14 @@
     <!-- 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 -->
     <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" />
@@ -711,6 +940,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 +1197,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 +1236,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 +1247,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 +1268,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 +1278,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 +1311,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 +1326,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 +1380,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 +1402,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 +1433,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 +1526,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 +1545,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 +1561,25 @@
         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 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 +1735,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 +1769,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 +1845,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 -->
@@ -1602,9 +1981,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 +2034,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"
@@ -1745,6 +2124,12 @@
             </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.MasterClearReceiver"
             android:permission="android.permission.MASTER_CLEAR"
             android:priority="100" >
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..7d5516a
--- /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="@interpolator/decelerate_quad"
+    android:fromAlpha="0.0" android:toAlpha="1.0"
+    android:duration="@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..caf896e
--- /dev/null
+++ b/core/res/res/anim/keyguard_security_fade_out.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.
+-->
+<alpha xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@interpolator/accelerate_quad"
+    android:fromAlpha="1.0"
+    android:toAlpha="0.0"
+    android:duration="@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/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_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_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/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..e13a9f8 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/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-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_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_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/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 29aff4d..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 6de0ba8..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/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-nodpi/kg_widget_overscroll_layer_left.9.png b/core/res/res/drawable-nodpi/kg_widget_overscroll_layer_left.9.png
new file mode 100644
index 0000000..c30eb1c
--- /dev/null
+++ b/core/res/res/drawable-nodpi/kg_widget_overscroll_layer_left.9.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/kg_widget_overscroll_layer_right.9.png b/core/res/res/drawable-nodpi/kg_widget_overscroll_layer_right.9.png
new file mode 100644
index 0000000..e5d5771
--- /dev/null
+++ b/core/res/res/drawable-nodpi/kg_widget_overscroll_layer_right.9.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/magnified_region_frame.9.png b/core/res/res/drawable-nodpi/magnified_region_frame.9.png
new file mode 100644
index 0000000..4cadefb
--- /dev/null
+++ b/core/res/res/drawable-nodpi/magnified_region_frame.9.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/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..a8f02d6 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_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_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/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 f006541..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/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/kg_avatar_overlay.xml b/core/res/res/drawable/kg_avatar_overlay.xml
new file mode 100644
index 0000000..781c1df
--- /dev/null
+++ b/core/res/res/drawable/kg_avatar_overlay.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/activity_picker_bg_activated" />
+</selector>
\ No newline at end of file
diff --git a/core/res/res/drawable/progress_horizontal_holo_dark.xml b/core/res/res/drawable/progress_horizontal_holo_dark.xml
index ff270b3..bc1ecf3 100644
--- a/core/res/res/drawable/progress_horizontal_holo_dark.xml
+++ b/core/res/res/drawable/progress_horizontal_holo_dark.xml
@@ -21,11 +21,13 @@
 
     <item android:id="@android:id/secondaryProgress">
         <scale android:scaleWidth="100%"
+               android:scaleGravity="start"
                android:drawable="@android:drawable/progress_secondary_holo_dark" />
     </item>
 
     <item android:id="@android:id/progress">
         <scale android:scaleWidth="100%"
+               android:scaleGravity="start"
                android:drawable="@android:drawable/progress_primary_holo_dark" />
     </item>
 
diff --git a/core/res/res/drawable/progress_horizontal_holo_light.xml b/core/res/res/drawable/progress_horizontal_holo_light.xml
index 4935185..ee9b629 100644
--- a/core/res/res/drawable/progress_horizontal_holo_light.xml
+++ b/core/res/res/drawable/progress_horizontal_holo_light.xml
@@ -21,11 +21,13 @@
 
     <item android:id="@android:id/secondaryProgress">
         <scale android:scaleWidth="100%"
+               android:scaleGravity="start"
                android:drawable="@android:drawable/progress_secondary_holo_light" />
     </item>
 
     <item android:id="@android:id/progress">
         <scale android:scaleWidth="100%"
+               android:scaleGravity="start"
                android:drawable="@android:drawable/progress_primary_holo_light" />
     </item>
 
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..4d83191 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,12 @@
             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:scaleGravity="start"
+               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:scaleGravity="start"
+               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..a3461fa 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,12 @@
             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:scaleGravity="start"
+               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:scaleGravity="start"
+               android:drawable="@android:drawable/scrubber_primary_holo" />
     </item>
 </layer-list>
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..01e1866
--- /dev/null
+++ b/core/res/res/layout-land/keyguard_host_view.xml
@@ -0,0 +1,55 @@
+<?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"
+    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.KeyguardWidgetPager
+        android:id="@+id/app_widget_container"
+        android:layout_width="0dip"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:visibility="gone">
+
+        <!-- TODO: Remove this once supported as a widget -->
+        <include layout="@layout/keyguard_status_view"/>
+        <include layout="@layout/keyguard_transport_control_view"/>
+
+    </com.android.internal.policy.impl.keyguard.KeyguardWidgetPager>
+
+
+    <com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper
+        android:id="@+id/view_flipper"
+        android:layout_width="0dip"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:gravity="center">
+
+        <!-- SelectorView is always used, so add it here. The rest are loaded dynamically -->
+        <include layout="@layout/keyguard_selector_view"/>
+
+    </com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper>
+
+</com.android.internal.policy.impl.keyguard.KeyguardHostView>
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..55c4c0d
--- /dev/null
+++ b/core/res/res/layout-port/keyguard_host_view.xml
@@ -0,0 +1,42 @@
+<?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"
+    android:id="@+id/keyguard_host_view"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:gravity="center_horizontal"
+    android:clipChildren="false">
+
+    <com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper
+        android:id="@+id/view_flipper"
+        android:layout_height="match_parent"
+        android:gravity="center">
+
+        <!-- SelectorView is always used, so add it here. The rest are loaded dynamically -->
+        <include layout="@layout/keyguard_selector_view"/>
+
+    </com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper>
+
+</com.android.internal.policy.impl.keyguard.KeyguardHostView>
+
diff --git a/core/res/res/layout-sw600dp-land/keyguard_host_view.xml b/core/res/res/layout-sw600dp-land/keyguard_host_view.xml
new file mode 100644
index 0000000..ea0b3ba
--- /dev/null
+++ b/core/res/res/layout-sw600dp-land/keyguard_host_view.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 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"
+    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.KeyguardWidgetPager
+        android:id="@+id/app_widget_container"
+        android:layout_width="0dip"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:visibility="gone">
+
+        <!-- TODO: Remove this once supported as a widget -->
+        <include layout="@layout/keyguard_status_view"/>
+        <include layout="@layout/keyguard_transport_control_view"/>
+
+    </com.android.internal.policy.impl.keyguard.KeyguardWidgetPager>
+
+    <FrameLayout
+        android:layout_width="0dip"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:gravity="center">
+
+        <com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper
+            android:id="@+id/view_flipper"
+            android:layout_width="@dimen/kg_security_view_width"
+            android:layout_height="match_parent"
+            android:layout_gravity="center"
+            android:layout_weight="1"
+            android:gravity="center">
+
+            <!-- SelectorView is always used, so add it here. The rest are loaded dynamically -->
+            <include layout="@layout/keyguard_selector_view"/>
+
+        </com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper>
+
+    </FrameLayout>
+
+</com.android.internal.policy.impl.keyguard.KeyguardHostView>
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..84b1b03
--- /dev/null
+++ b/core/res/res/layout-sw600dp-port/keyguard_host_view.xml
@@ -0,0 +1,56 @@
+<?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"
+    android:id="@+id/keyguard_host_view"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:gravity="center_horizontal">
+
+    <com.android.internal.policy.impl.keyguard.KeyguardWidgetPager
+        android:id="@+id/app_widget_container"
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="0.4"
+        android:visibility="gone">
+
+        <!-- TODO: Remove this once supported as a widget -->
+        <include layout="@layout/keyguard_status_view"/>
+        <include layout="@layout/keyguard_transport_control_view"/>
+
+    </com.android.internal.policy.impl.keyguard.KeyguardWidgetPager>
+
+    <com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper
+        android:id="@+id/view_flipper"
+        android:layout_width="@dimen/kg_security_view_width"
+        android:layout_height="0dip"
+        android:layout_weight="0.6"
+        android:layout_gravity="center">
+
+        <!-- SelectorView is always used, so add it here. The rest are loaded dynamically -->
+        <include layout="@layout/keyguard_selector_view"/>
+
+    </com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper>
+
+</com.android.internal.policy.impl.keyguard.KeyguardHostView>
+
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_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..4f94f96 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,7 @@
                     android:layout_weight="1"
                     android:gravity="center"
                     android:layout_gravity="center"
-                    android:layout_marginLeft="@dimen/keyguard_lockscreen_pin_margin_left"
+                    android:layout_marginStart="@dimen/keyguard_lockscreen_pin_margin_left"
                     android:singleLine="true"
                     android:textStyle="normal"
                     android:inputType="textPassword"
@@ -154,7 +154,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 +174,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..9a649fbb 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,7 @@
                     android:inputType="textPassword"
                     android:gravity="center"
                     android:layout_gravity="center"
-                    android:layout_marginLeft="@dimen/keyguard_lockscreen_pin_margin_left"
+                    android:layout_marginStart="@dimen/keyguard_lockscreen_pin_margin_left"
                     android:textSize="24sp"
                     android:textAppearance="?android:attr/textAppearanceMedium"
                     android:background="@null"
@@ -157,7 +157,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 +177,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_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..0fb3443 100644
--- a/core/res/res/layout-xlarge/breadcrumbs_in_fragment.xml
+++ b/core/res/res/layout-xlarge/breadcrumbs_in_fragment.xml
@@ -18,8 +18,8 @@
         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 +27,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
index 7c95693..f931cf2 100644
--- a/core/res/res/layout-xlarge/select_dialog_holo.xml
+++ b/core/res/res/layout-xlarge/select_dialog_holo.xml
@@ -28,8 +28,8 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:layout_marginTop="5dip"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
     android:cacheColorHint="@null"
     android:divider="?android:attr/listDividerAlertDialog"
     android:scrollbars="vertical"
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..3ac0e21 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"
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..ab0d532
--- /dev/null
+++ b/core/res/res/layout/app_permission_item_money.xml
@@ -0,0 +1,71 @@
+<?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_below="@id/perm_name"
+            android:scaleType="fitCenter" />
+        <TextView
+            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: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 2508f72e..3ddbbb2 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..769d80b 100644
--- a/core/res/res/layout/choose_account_type.xml
+++ b/core/res/res/layout/choose_account_type.xml
@@ -21,14 +21,14 @@
     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">
 
     <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:layout_gravity="start"
         android:text="@string/add_account_label"
         android:paddingTop="16dip"
         android:paddingBottom="16dip"
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/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..481f0c1
--- /dev/null
+++ b/core/res/res/layout/keyguard_account_view.xml
@@ -0,0 +1,72 @@
+<?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:orientation="vertical">
+
+    <include layout="@layout/keyguard_navigation"/>
+
+    <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_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_alignParentBottom="true"
+            android:text="@string/kg_login_submit_button"
+            />
+
+    </RelativeLayout>
+
+</com.android.internal.policy.impl.keyguard.KeyguardAccountView>
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..60f0492
--- /dev/null
+++ b/core/res/res/layout/keyguard_face_unlock_view.xml
@@ -0,0 +1,61 @@
+<?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">
+
+    <include layout="@layout/keyguard_navigation"/>
+
+    <Space
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1" />
+
+    <RelativeLayout
+        android:id="@+id/face_unlock_area_view"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/face_unlock_height"
+        android:background="@drawable/intro_bg"
+        android:gravity="center">
+
+        <View
+            android:id="@+id/spotlightMask"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:background="@color/facelock_spotlight_mask"
+        />
+
+        <ImageView
+            android:id="@+id/cancel_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:padding="5dip"
+            android:layout_alignParentTop="true"
+            android:layout_alignParentEnd="true"
+            android:src="@drawable/ic_facial_backup"
+        />
+
+    </RelativeLayout>
+
+</com.android.internal.policy.impl.keyguard.KeyguardFaceUnlockView>
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..23f9b6d
--- /dev/null
+++ b/core/res/res/layout/keyguard_multi_user_avatar.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.KeyguardMultiUserAvatar
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="125dp"
+    android:layout_height="125dp"
+    android:background="#550000ff"
+    android:gravity="center_horizontal"
+    android:foreground="@drawable/kg_avatar_overlay">
+    <ImageView
+        android:id="@+id/keyguard_user_avatar"
+        android:scaleType="centerCrop"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_gravity="center"/>
+    <TextView
+        android:id="@+id/keyguard_user_name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="bottom|right"
+        android:textSize="12sp"
+        android:background="#99FFFFFF"
+        android:textColor="#ff000000"/>
+</com.android.internal.policy.impl.keyguard.KeyguardMultiUserAvatar>
\ No newline at end of file
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..c599fd5dd
--- /dev/null
+++ b/core/res/res/layout/keyguard_multi_user_selector.xml
@@ -0,0 +1,33 @@
+<?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:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_gravity="center">
+
+    <com.android.internal.policy.impl.keyguard.KeyguardSubdivisionLayout
+        android:id="@+id/keyguard_users_grid"
+        android:orientation="horizontal"
+        android:layout_width="300dp"
+        android:layout_height="300dp"
+        android:layout_gravity="center" />
+
+</com.android.internal.policy.impl.keyguard.KeyguardMultiUserSelectorView>
\ No newline at end of file
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..c00089c
--- /dev/null
+++ b/core/res/res/layout/keyguard_multi_user_selector_widget.xml
@@ -0,0 +1,28 @@
+<?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:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <include layout="@layout/keyguard_multi_user_selector"/>
+
+</com.android.internal.policy.impl.keyguard.KeyguardWidgetFrame>
\ No newline at end of file
diff --git a/core/res/res/layout/keyguard_navigation.xml b/core/res/res/layout/keyguard_navigation.xml
new file mode 100644
index 0000000..a033101
--- /dev/null
+++ b/core/res/res/layout/keyguard_navigation.xml
@@ -0,0 +1,55 @@
+<?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.
+*/
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:gravity="left">
+
+    <LinearLayout
+        android:id="@+id/keyguard_click_area"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        style="?android:attr/buttonBarButtonStyle"
+        android:padding="10dip"
+        android:clickable="true">
+
+        <ImageView
+               android:src="?android:attr/homeAsUpIndicator"
+               android:layout_gravity="center_vertical|start"
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"/>
+
+        <!-- message area for security screen -->
+        <TextView
+            android:id="@+id/keyguard_message_area"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:layout_gravity="end"
+            android:singleLine="true"
+            android:ellipsize="marquee"
+            android:layout_marginEnd="6dip"
+            android:layout_marginStart="6dip"
+            android:textAppearance="?android:attr/textAppearanceMedium"/>
+
+    </LinearLayout>
+
+</LinearLayout>
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..4ea471e
--- /dev/null
+++ b/core/res/res/layout/keyguard_password_view.xml
@@ -0,0 +1,100 @@
+<?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:gravity="center_horizontal">
+
+    <include layout="@layout/keyguard_navigation"/>
+
+    <!-- Password entry field -->
+    <!-- Note: the entire container is styled to look like the edit field,
+         since the backspace/IME switcher looks better inside -->
+    <LinearLayout
+        android:layout_gravity="center_vertical|fill_horizontal"
+        android:layout_width="match_parent"
+        android:orientation="horizontal"
+        android:background="@*android:drawable/lockscreen_password_field_dark"
+        android:layout_marginStart="16dip"
+        android:layout_marginEnd="16dip">
+
+        <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"
+            />
+
+        <!-- This delete button is only visible for numeric PIN entry -->
+        <ImageButton android:id="@+id/delete_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@*android:drawable/ic_input_delete"
+            android:clickable="true"
+            android:padding="8dip"
+            android:layout_gravity="center_vertical"
+            android:background="?android:attr/selectableItemBackground"
+            android:visibility="gone"
+            />
+
+        <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>
+
+    <Space
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1"/>
+
+    <!-- Numeric keyboard -->
+    <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
+        android:layout_width="match_parent"
+        android:layout_marginStart="4dip"
+        android:layout_marginEnd="4dip"
+        android:paddingTop="4dip"
+        android:paddingBottom="4dip"
+        android:background="#40000000"
+        android:keyBackground="@*android:drawable/btn_keyboard_key_ics"
+        android:visibility="gone"
+        android:clickable="true"
+    />
+
+</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..356bce3
--- /dev/null
+++ b/core/res/res/layout/keyguard_pattern_view.xml
@@ -0,0 +1,58 @@
+<?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:gravity="center_horizontal">
+
+    <include layout="@layout/keyguard_navigation"/>
+
+    <Space android:layout_gravity="fill" />
+
+    <Button android:id="@+id/forgot_password_button"
+        android:layout_gravity="right"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="@*android:dimen/keyguard_lockscreen_status_line_font_size"
+        android:drawableLeft="@*android:drawable/lockscreen_forgot_password_button"
+        android:drawablePadding="0dip"
+        android:visibility="gone"/>
+
+    <!-- We need MATCH_PARENT here only to force the size of the parent to be passed to
+    the pattern view for it to compute its size. This is an unusual case, caused by
+    LockPatternView's requirement to maintain a square aspect ratio based on the width
+    of the screen. -->
+    <com.android.internal.widget.LockPatternView
+        android:id="@+id/lockPatternView"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_marginEnd="8dip"
+        android:layout_marginBottom="4dip"
+        android:layout_marginStart="8dip"
+        android:layout_gravity="center_horizontal"
+     />
+
+</com.android.internal.policy.impl.keyguard.KeyguardPatternView>
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 43867f4..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..e0a3ce3 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,7 @@
             android:layout_width="0dip"
             android:layout_weight="1"
             android:gravity="center"
-            android:layout_marginLeft="@dimen/keyguard_lockscreen_pin_margin_left"
+            android:layout_marginStart="@dimen/keyguard_lockscreen_pin_margin_left"
             android:layout_gravity="center_vertical"
             android:singleLine="true"
             android:textStyle="normal"
@@ -185,8 +185,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 +209,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 +233,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..0212f73 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,8 +102,8 @@
         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"
@@ -111,7 +111,7 @@
             android:layout_weight="1"
             android:gravity="center_horizontal"
             android:layout_gravity="center_vertical"
-            android:layout_marginLeft="@dimen/keyguard_lockscreen_pin_margin_left"
+            android:layout_marginStart="@dimen/keyguard_lockscreen_pin_margin_left"
             android:singleLine="true"
             android:textStyle="normal"
             android:inputType="textPassword"
@@ -150,8 +150,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 +200,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 +224,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..20c2142 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..b090f13
--- /dev/null
+++ b/core/res/res/layout/keyguard_selector_view.xml
@@ -0,0 +1,83 @@
+<?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:orientation="vertical">
+
+    <com.android.internal.policy.impl.keyguard.KeyguardWidgetPager
+        android:id="@+id/app_widget_container"
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:visibility="gone">
+            <!-- TODO: Remove this when supported as a widget -->
+            <include layout="@layout/keyguard_status_view"/>
+            <include layout="@layout/keyguard_transport_control_view"/>
+    </com.android.internal.policy.impl.keyguard.KeyguardWidgetPager>
+
+    <RelativeLayout
+        android:layout_width="wrap_content"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:layout_gravity="center"
+        android:gravity="center">
+
+        <com.android.internal.widget.multiwaveview.GlowPadView
+            android:id="@+id/glow_pad_view"
+            android:orientation="horizontal"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:focusable="true"
+
+            prvandroid:targetDrawables="@*android:array/lockscreen_targets_with_camera"
+            prvandroid:targetDescriptions="@*android:array/lockscreen_target_descriptions_with_camera"
+            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:feedbackCount="1"
+            prvandroid:vibrationDuration="20"
+            prvandroid:glowRadius="@*android:dimen/glowpadview_glow_radius"
+            prvandroid:pointDrawable="@*android:drawable/ic_lockscreen_glowdot"/>
+
+        <Button
+            android:id="@+id/emergency_call_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="end"
+            android:drawableLeft="@*android:drawable/lockscreen_emergency_button"
+            android:text="@string/kg_emergency_call_label"
+            style="?android:attr/buttonBarButtonStyle"
+            android:drawablePadding="8dip"
+            android:layout_alignRight="@id/glow_pad_view"
+            android:layout_alignTop="@id/glow_pad_view"
+            />
+
+    </RelativeLayout>
+
+</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..122484a
--- /dev/null
+++ b/core/res/res/layout/keyguard_sim_pin_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 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"
+    android:id="@+id/keyguard_sim_pin_view"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:gravity="center_horizontal">
+
+    <include layout="@layout/keyguard_navigation"/>
+
+    <Space
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1"/>
+
+    <!-- Password entry field -->
+    <!-- Note: the entire container is styled to look like the edit field,
+         since the backspace/IME switcher looks better inside -->
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        android:layout_marginEnd="6dip"
+        android:layout_marginStart="6dip"
+        android:gravity="center_vertical"
+        android:background="@android:drawable/edit_text">
+
+        <!-- displays dots as user enters pin -->
+        <EditText android:id="@+id/sim_pin_entry"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:maxLines="1"
+            android:singleLine="true"
+            android:textAppearance="?android:attr/textAppearanceLargeInverse"
+            android:textColor="@*android:color/primary_text_holo_light"
+            android:textStyle="bold"
+            android:inputType="textPassword"
+            android:imeOptions="flagForceAscii|actionDone"
+        />
+
+        <ImageButton android:id="@+id/delete_button"
+            android:src="@android:drawable/ic_input_delete"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginEnd="-3dip"
+            android:layout_marginBottom="-3dip"
+        />
+    </LinearLayout>
+
+    <!-- Numeric keyboard -->
+    <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
+        android:layout_width="match_parent"
+        android:layout_marginStart="4dip"
+        android:layout_marginEnd="4dip"
+        android:paddingTop="4dip"
+        android:paddingBottom="4dip"
+        android:background="#80ffffff"
+        android:keyBackground="@*android:drawable/btn_keyboard_key_ics"
+        android:clickable="true"
+    />
+
+</com.android.internal.policy.impl.keyguard.KeyguardSimPinView>
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..8bb76c1
--- /dev/null
+++ b/core/res/res/layout/keyguard_sim_puk_view.xml
@@ -0,0 +1,133 @@
+<?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.KeyguardSimPukView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/keyguard_sim_puk_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:gravity="center_horizontal">
+
+    <include layout="@layout/keyguard_navigation"/>
+
+    <Space
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1"/>
+
+    <LinearLayout android:id="@+id/topDisplayGroup"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+
+        <LinearLayout
+            android:orientation="horizontal"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+
+            <LinearLayout
+                  android:orientation="vertical"
+                  android:layout_width="wrap_content"
+                  android:layout_weight="1"
+                  android:layout_height="match_parent"
+                  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_marginEnd="6dip"
+                      android:layout_marginStart="6dip"
+                      android:gravity="center_vertical"
+                      android:background="@*android:drawable/edit_text">
+
+                      <!-- displays dots as user enters puk -->
+                      <EditText android:id="@+id/sim_puk_entry"
+                          android:layout_width="0dip"
+                          android:layout_height="wrap_content"
+                          android:layout_weight="1"
+                          android:maxLines="1"
+                          android:textStyle="bold"
+                          android:inputType="textPassword"
+                          android:textColor="#000"
+                          android:hint="@string/kg_puk_enter_puk_hint"
+                      />
+
+                      <ImageButton android:id="@+id/puk_delete_button"
+                          android:src="@*android:drawable/ic_input_delete"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:layout_marginEnd="-3dip"
+                          android:layout_marginBottom="-3dip"
+                      />
+
+                  </LinearLayout>
+
+
+                  <LinearLayout
+                      android:layout_width="match_parent"
+                      android:layout_height="wrap_content"
+                      android:orientation="horizontal"
+                      android:layout_marginEnd="6dip"
+                      android:layout_marginStart="6dip"
+                      android:gravity="center_vertical"
+                      android:background="@*android:drawable/edit_text">
+
+                      <!-- displays dots as user enters new pin -->
+                      <EditText android:id="@+id/sim_pin_entry"
+                          android:layout_width="0dip"
+                          android:layout_height="wrap_content"
+                          android:layout_weight="1"
+                          android:maxLines="1"
+                          android:textStyle="bold"
+                          android:inputType="textPassword"
+                          android:textColor="#000"
+                          android:hint="@string/kg_puk_enter_pin_hint"
+                      />
+
+                      <ImageButton android:id="@+id/pin_delete_button"
+                          android:src="@*android:drawable/ic_input_delete"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:layout_marginEnd="-3dip"
+                          android:layout_marginBottom="-3dip"
+                      />
+                  </LinearLayout>
+
+             </LinearLayout>
+
+        </LinearLayout>
+
+    </LinearLayout>
+
+    <!-- Numeric keyboard -->
+    <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
+        android:layout_width="match_parent"
+        android:layout_marginStart="4dip"
+        android:layout_marginEnd="4dip"
+        android:paddingTop="4dip"
+        android:paddingBottom="4dip"
+        android:background="#80ffffff"
+        android:keyBackground="@*android:drawable/btn_keyboard_key_ics"
+        android:clickable="true"
+    />
+
+</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..5d8020e
--- /dev/null
+++ b/core/res/res/layout/keyguard_status_view.xml
@@ -0,0 +1,131 @@
+<?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:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:id="@+id/keyguard_status_view"
+    android:gravity="center_horizontal">
+
+    <com.android.internal.policy.impl.keyguard.KeyguardStatusView
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center_horizontal">
+
+        <com.android.internal.widget.DigitalClock android:id="@+id/time"
+            android:layout_marginTop="@*android:dimen/keyguard_lockscreen_status_line_clockfont_top_margin"
+            android:layout_marginBottom="12dip"
+            android:layout_marginEnd="@*android: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... -->
+            <TextView android:id="@*android:id/timeDisplayBackground"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:singleLine="true"
+                android:ellipsize="none"
+                android:textSize="@*android:dimen/keyguard_lockscreen_clock_font_size"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:layout_marginBottom="6dip"
+                android:textColor="@*android:color/lockscreen_clock_background"
+                />
+
+            <TextView android:id="@*android:id/timeDisplayForeground"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:singleLine="true"
+                android:ellipsize="none"
+                android:textSize="@*android:dimen/keyguard_lockscreen_clock_font_size"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:layout_marginBottom="6dip"
+                android:textColor="@*android:color/lockscreen_clock_foreground"
+                android:layout_alignStart="@*android:id/timeDisplayBackground"
+                android:layout_alignTop="@*android:id/timeDisplayBackground"
+                />
+
+        </com.android.internal.widget.DigitalClock>
+
+        <LinearLayout
+            android:orientation="horizontal"
+            android:layout_gravity="end"
+            android:layout_marginEnd="@*android:dimen/keyguard_lockscreen_status_line_font_right_margin">
+
+            <TextView
+                android:id="@*android:id/date"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:singleLine="true"
+                android:ellipsize="marquee"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:textSize="@*android:dimen/keyguard_lockscreen_status_line_font_size"
+                />
+
+            <TextView
+                android:id="@*android:id/alarm_status"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="16dip"
+                android:singleLine="true"
+                android:ellipsize="marquee"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:textSize="@*android:dimen/keyguard_lockscreen_status_line_font_size"
+                android:drawablePadding="4dip"
+                />
+
+        </LinearLayout>
+
+        <TextView
+            android:id="@+id/status1"
+            android:layout_gravity="end"
+            android:layout_marginEnd="@*android:dimen/keyguard_lockscreen_status_line_font_right_margin"
+            android:singleLine="true"
+            android:ellipsize="marquee"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textSize="@*android:dimen/keyguard_lockscreen_status_line_font_size"
+            android:drawablePadding="4dip"
+            />
+
+        <TextView
+            android:id="@+id/owner_info"
+            android:layout_gravity="end"
+            android:layout_marginEnd="@*android:dimen/keyguard_lockscreen_status_line_font_right_margin"
+            android:singleLine="true"
+            android:ellipsize="marquee"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textSize="@*android:dimen/keyguard_lockscreen_status_line_font_size"
+            android:drawablePadding="4dip"
+            />
+
+        <TextView
+            android:id="@+id/carrier"
+            android:layout_gravity="end"
+            android:layout_marginEnd="@*android:dimen/keyguard_lockscreen_status_line_font_right_margin"
+            android:singleLine="true"
+            android:ellipsize="marquee"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textSize="@*android:dimen/keyguard_lockscreen_status_line_font_size"
+            android:textColor="?android:attr/textColorSecondary"
+            />
+
+    </com.android.internal.policy.impl.keyguard.KeyguardStatusView>
+</com.android.internal.policy.impl.keyguard.KeyguardWidgetFrame>
\ No newline at end of file
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..c40aa66
--- /dev/null
+++ b/core/res/res/layout/keyguard_transport_control_view.xml
@@ -0,0 +1,111 @@
+<?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="@drawable/ic_lockscreen_player_background">
+        <!-- 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="@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.policy.impl.keyguard.KeyguardTransportControlView>
\ No newline at end of file
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..53d813e 100644
--- a/core/res/res/layout/media_route_list_item.xml
+++ b/core/res/res/layout/media_route_list_item.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"
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..5fb82f7 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_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..988a81f 100644
--- a/core/res/res/layout/notification_template_big_text.xml
+++ b/core/res/res/layout/notification_template_big_text.xml
@@ -32,7 +32,7 @@
         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:paddingBottom="2dp"
@@ -42,8 +42,8 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:layout_weight="1"
             >
             <LinearLayout
@@ -87,7 +87,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 +99,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 +109,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 +142,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 +167,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..6ebb443 100644
--- a/core/res/res/layout/notification_template_inbox.xml
+++ b/core/res/res/layout/notification_template_inbox.xml
@@ -33,7 +33,7 @@
         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"
@@ -44,8 +44,8 @@
             android:id="@+id/line1"
             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:paddingTop="6dp"
             android:orientation="horizontal"
             android:layout_weight="0"
@@ -82,8 +82,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"
@@ -94,8 +94,8 @@
             android:id="@android:id/progress"
             android:layout_width="match_parent"
             android:layout_height="12dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:visibility="gone"
             android:layout_weight="0"
             style="?android:attr/progressBarStyleHorizontal"
@@ -104,8 +104,8 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
@@ -115,8 +115,8 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
@@ -126,8 +126,8 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
@@ -137,8 +137,8 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
@@ -148,7 +148,7 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
+            android:layout_marginStart="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
@@ -158,8 +158,8 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
@@ -169,8 +169,8 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
@@ -180,8 +180,8 @@
             android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
             android:layout_width="match_parent"
             android:layout_height="0dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginRight="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:singleLine="true"
             android:ellipsize="end"
             android:visibility="gone"
@@ -212,9 +212,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 +237,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 4167862..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..ed08375
--- /dev/null
+++ b/core/res/res/layout/sms_short_code_confirmation_dialog.xml
@@ -0,0 +1,61 @@
+<?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="8dip"/>
+
+    <LinearLayout android:id="@+id/sms_short_code_detail_layout"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        android:gravity="center_vertical"
+        android:minHeight="@dimen/alert_dialog_title_height"
+        android:layout_marginLeft="16dip"
+        android:layout_marginRight="16dip">
+        <ImageView android:id="@+id/sms_short_code_coins_icon"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingRight="8dip"
+            android:src="@null" />
+        <TextView android:id="@+id/sms_short_code_detail_message"
+                style="?android:attr/textAppearanceMedium"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content" />
+        </LinearLayout>
+
+    <CheckBox android:id="@+id/sms_short_code_remember_choice_checkbox"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/sms_short_code_remember_choice" />
+</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..3958fc6 100644
--- a/core/res/res/layout/time_picker.xml
+++ b/core/res/res/layout/time_picker.xml
@@ -39,7 +39,7 @@
         android:id="@+id/minute"
         android:layout_width="70dip"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="5dip"
+        android:layout_marginStart="5dip"
         android:focusable="true"
         android:focusableInTouchMode="true"
         />
@@ -50,9 +50,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..765e71d 100644
--- a/core/res/res/layout/time_picker_holo.xml
+++ b/core/res/res/layout/time_picker_holo.xml
@@ -32,8 +32,8 @@
         android:layout_height="wrap_content"
         android:layout_marginTop="16dip"
         android:layout_marginBottom="16dip"
-        android:layout_marginLeft="16dip"
-        android:layout_marginRight="6dip"
+        android:layout_marginStart="16dip"
+        android:layout_marginEnd="6dip"
         android:focusable="true"
         android:focusableInTouchMode="true"
         />
@@ -54,8 +54,8 @@
         android:layout_height="wrap_content"
         android:layout_marginTop="16dip"
         android:layout_marginBottom="16dip"
-        android:layout_marginLeft="6dip"
-        android:layout_marginRight="8dip"
+        android:layout_marginStart="6dip"
+        android:layout_marginEnd="8dip"
         android:focusable="true"
         android:focusableInTouchMode="true"
         />
@@ -67,8 +67,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/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..8026b16 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Kortreeks-netwerke"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Kry toegang tot toestelle met kortreeks-netwerke soos NFC."</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 +222,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 +257,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 +289,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_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>
+    <!-- no translation found for permlab_magnify_display (5973626738170618775) -->
+    <skip />
+    <!-- no translation found for permdesc_magnify_display (7121235684515003792) -->
+    <skip />
     <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>
@@ -273,6 +327,10 @@
     <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>
+    <!-- no translation found for permlab_freezeScreen (4708181184441880175) -->
+    <skip />
+    <!-- no translation found for permdesc_freezeScreen (8558923789222670064) -->
+    <skip />
     <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>
@@ -385,6 +443,14 @@
     <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>
+    <!-- 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">"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>
@@ -534,6 +600,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 +632,10 @@
     <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>
+    <!-- no translation found for policylab_disableKeyguardWidgets (1794894613389073926) -->
+    <skip />
+    <!-- no translation found for policydesc_disableKeyguardWidgets (7254624892984033592) -->
+    <skip />
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Tuis"</item>
     <item msgid="869923650527136615">"Mobiel"</item>
@@ -930,8 +1002,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>
@@ -1033,6 +1105,13 @@
     <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_title" msgid="1666863092640877318">"Stuur SMS na kortkode?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Stuur \'n premium-SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; wil graag \'n SMS stuur aan &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, wat lyk asof dit \'n SMS-kortkode is.&lt;p&gt;Die stuur van SMS\'e na sommige kortkodes kan veroorsaak dat jou selfoonrekening gedebiteer word vir premiumdienste.&lt;p&gt;Wil jy hierdie program toelaat om die boodskap te stuur?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; wil graag \'n SMS stuur aan &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, wat \'n betaalde SMS-kortkode is.&lt;p&gt;&lt;b&gt;As jy \'n boodskap na hierdie bestemming stuur, sal jou selfoonrekening gedebiteer word vir betaalde dienste.&lt;/b&gt;&lt;p&gt;Wil jy hierdie program toelaat om die boodskap te stuur?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Stuur boodskap"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Moenie stuur nie"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Gee kwaadwillige program aan"</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 +1122,9 @@
     <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_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="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 +1223,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>
@@ -1290,4 +1370,45 @@
     <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="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="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="5183097160254244459">"PUK-kode"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Nuwe 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="5216603185442368307">"Tik \'n PUK in wat 8 syfers of meer is."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Voer PUK en nuwe PIN-kode in"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"Jy het die verkeerde PUK getik."</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="8849589033659332457">"Kontroleer tans..."</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..e7dcecc 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"የአጭር ክልል አውታረ መረቦች"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"መሳሪያዎችን እንደ NFC ባሉ የአጭር ክልል አውታረ መረቦች በኩል አግኝ።"</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 +222,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 +257,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 +289,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_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>
+    <!-- no translation found for permlab_magnify_display (5973626738170618775) -->
+    <skip />
+    <!-- no translation found for permdesc_magnify_display (7121235684515003792) -->
+    <skip />
     <string name="permlab_shutdown" msgid="7185747824038909016">"ከፊል ዝጋ"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"የእንቅስቃሴውን አደራጅ ወደ ዝጋ ሁነታ አስቀምጥ።ሙሉ ለሙሉ ዝጋ አያከናውንም።"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"የትግበራ መቀያየርን ተከላከል"</string>
@@ -273,6 +327,10 @@
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"የአለም አቀፍ ተልወስዋሽ ምስሎች ፍጥነት(ፈጣን ወይም ቀርፋፋ ተልወስዋሽ ምስሎችን) በማንኛውም ጊዜ ለመለወጥ ለመተግበሪያው ይፈቅዳሉ።"</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"የትግበራ የምስጋና የምስክር ወረቀት አደራጅ"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"መደበኛውን Z-አደራደራቸውን  በመተላለፍ፤ የራሳቸውን የምስጋና ምስክር ወረቀት ለመፍጠር እና ለማደራጀት ለመተግበሪያው ይፈቅዳሉ፡፡ለመደበኛ መተግበሪያዎች መቼም ቢሆን አያስፈልግም፡፡"</string>
+    <!-- no translation found for permlab_freezeScreen (4708181184441880175) -->
+    <skip />
+    <!-- no translation found for permdesc_freezeScreen (8558923789222670064) -->
+    <skip />
     <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>
@@ -385,6 +443,14 @@
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"መተግበሪያውን የSurfaceFlinger ዝቅተኛ ደረጃ ባህሪያትን ለመጠቀም ይፈቅዳል።"</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"የንዑስ ክፈፍ ቋት አንብብ"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"የክፈፍ ቋት ይዘት ለማንበብ ለመተግበሪያው ይፈቅዳሉ።"</string>
+    <!-- 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">"የድምፅ ቅንብሮችን ለውጥ"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"መተግበሪያው አንደ የድምጽ መጠን እና ለውጽአት የትኛውን የድምጽ ማጉያ ጥቅም ላይ እንደዋለ የመሳሰሉ ሁለንተናዊ የድምጽ ቅንብሮችን እንዲያስተካክል ይፈቅድለታል።"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ኦዲዮ ቅዳ"</string>
@@ -534,6 +600,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 +632,10 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"የተከማቸ ትግበራ ውሂብ የተመሰጠረ እንዲሆን ጠይቅ።"</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"ካሜራዎችን አቦዝን"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"የሁሉንም መሣሪያ ካሜራዎች መጠቀም ከልክል።"</string>
+    <!-- no translation found for policylab_disableKeyguardWidgets (1794894613389073926) -->
+    <skip />
+    <!-- no translation found for policydesc_disableKeyguardWidgets (7254624892984033592) -->
+    <skip />
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"መነሻ"</item>
     <item msgid="869923650527136615">"ተንቀሳቃሽ"</item>
@@ -930,8 +1002,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>
@@ -1033,6 +1105,13 @@
     <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_title" msgid="1666863092640877318">"ኤስ.ኤም.ኤስ. ለአጭር ኮድ ይላክ?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"ከፍ ያለ ኤስ.ኤም.ኤስ. ይላክ?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&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; መላክ ይፈልጋል፣ ይሄ ደግሞ የኤስ.ኤም.ኤስ. አጭር ኮድ ሆኖ ተገኝቷል።&lt;p&gt;የጽሑፍ መልዕክቶች ለሆኑ አጭር ኮዶች መላክ የተንቀሳቃሽ መለያህ ከፍ ላሉ አገልግሎቶች ሊያስከፍለው ይችላል።&lt;p&gt;ይሄ መተግበሪያ መልዕክቱ እንዲልክ መፍቀድ ትፈልጋለህ?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&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; መላክ ይፈልጋል፣ ይሄ ደግሞ ከፍ ያለ የኤስ.ኤም.ኤስ. አጭር ኮድ ነው።&lt;p&gt;&lt;b&gt;መልዕክት ወደዚህ ቦታ መላክ የተንቀሳቃሽ መለያህ ከፍ ላሉ አገልግሎቶች ያስከፍለዋል።&lt;/b&gt;&lt;p&gt;ይሄ መተግበሪያ መልዕክቱ እንዲልክ መፍቀድ ትፈልጋለህ?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"መልዕክት ላክ"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"አትላክ"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"ተንኮል አዘል መተግበሪያ ሪፖርት አድርግ"</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 +1122,9 @@
     <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_description_app" msgid="5139836143293299417">"በ<xliff:g id="APP_NAME">%1$s</xliff:g> የቀረበ።"</string>
+    <string name="no_permissions" msgid="7283357728219338112">"ምንም ፍቃዶች አይጠየቁም"</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 +1215,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 +1223,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>
@@ -1290,4 +1370,45 @@
     <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="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="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="5183097160254244459">"የPUK ኮድ"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"አዲስ ፒን ኮድ"</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="5216603185442368307">"8 ወይም ከዚያ በላይ ቁጥሮችን የሆነ PUK ይተይቡ።"</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"PUK እና አዲስ ፒን ይተይቡ"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"የተየቡት PUK ትክክል  አይደለም።"</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="8849589033659332457">"በማረጋገጥ ላይ…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..875f47f 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"الشبكات قصيرة المدى"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"الدخول إلى الأجهزة من خلال الشبكات قصيرة المدى مثل الاتصالات قريبة المدى (NFC)."</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"تعطيل الأدوات على حارس المفاتيح"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"منع استخدام بعض الأدوات أو كلها على حارس المفاتيح."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"الرئيسية"</item>
     <item msgid="869923650527136615">"الجوال"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"إرسال رسالة SMS إلى رمز قصير؟"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"هل تريد إرسال رسالة قصيرة SMS مميزة؟"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&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;، والذي يُعد رمزًا قصيرًا لرسالة قصيرة SMS.&lt;p&gt;قد يؤدي إرسال رسائل نصية إلى بعض الرموز القصيرة إلى تحصيل رسوم من حساب جوالك للخدمات المميزة.&lt;p&gt;هل تريد السماح لهذا التطبيق بإرسال الرسالة؟"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&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;، والذي يُعد رمزًا قصيرًا لرسالة قصيرة SMS مميزة.&lt;p&gt;&lt;b&gt;سيؤدي إرسال رسالة إلى هذه الوجهة إلى تحصيل رسوم من حساب جوالك للخدمات المميزة.&lt;/b&gt;&lt;p&gt;هل تريد السماح لهذا التطبيق بإرسال الرسالة؟"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"إرسال رسالة"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"عدم الإرسال"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"الإبلاغ عن تطبيق ضار"</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 +1112,9 @@
     <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_description_app" msgid="5139836143293299417">"يقدمه <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"لا أذونات مطلوبة"</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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"رمز PUK"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"رمز رقم التعريف الشخصي الجديد"</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="5216603185442368307">"اكتب رمز PUK المكون من 8 أرقام أو أكثر."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"اكتب رمز PUK ورمز رقم التعريف الشخصي الجديد"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"رمز PUK الذي كتبته غير صحيح."</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="8849589033659332457">"جارٍ التحقق…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..07bd234 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Блізкія сеткі"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Доступ да прылад праз блізкія сеткі, напрыклад, NFC."</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Адключыць вiджэты на клавіятуры"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Прадухіліць выкарыстанне некаторых ці ўсіх віджэтаў на клавіятуры."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Галоўная старонка"</item>
     <item msgid="869923650527136615">"Мабільны"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Адправiць SMS на кароткі нумар?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Адправiць платнае SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"Прыкладанне &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&amp;gt спрабуе адправiць тэкставае паведамленне на нумар &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, які, здаецца, з\'яўляецца кароткім нумарам для SMS.&lt;p&gt;Дасыланне тэкставых паведамленняў на кароткія нумары можа прывесці да спісання сродкаў з вашага мабільнага рахунку за платныя паслугі.&lt;/b&gt;&lt;p&gt;Жадаеце дазволіць гэтаму прыкладанню даслаць паведамленне?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"Прыкладанне &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&amp;g спрабуе адправiць тэкставае паведамленне на нумар &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, які з\'яўляецца платным кароткім нумарам для SMS.&lt;p&gt;&lt;b&gt;Адпраўка паведамлення гэтаму атрымальніку прывядзе да спісання сродкаў з вашага мабільнага рахунку за платныя паслугі.&lt;/b&gt;&lt;p&gt;Жадаеце дазволіць гэтаму прыкладанню даслаць паведамленне?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Адправiць паведамленне"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Не адпраўляць"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Павед. аб шкодн. прыкладаннях"</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 +1112,9 @@
     <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_description_app" msgid="5139836143293299417">"Прадастаўленыя прыкладаннем <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Дазволу не патрабуецца"</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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"PUK"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Новы 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="5216603185442368307">"Увядзіце PUK з 8 лічбаў ці больш."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Увядзіце PUK-код і новы PIN-код"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"Няправільны PUK-код."</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="8849589033659332457">"Праверка..."</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..b815e81 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Мрежи с малък обхват"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Осъществяване на достъп до устройства през мрежи с малък обхват, например КБП."</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 +222,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 +257,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 +289,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_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>
+    <!-- no translation found for permlab_magnify_display (5973626738170618775) -->
+    <skip />
+    <!-- no translation found for permdesc_magnify_display (7121235684515003792) -->
+    <skip />
     <string name="permlab_shutdown" msgid="7185747824038909016">"частично изключване"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Изключва диспечера на дейностите. Не извършва пълно изключване."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"предотвратяване на превключването между приложения"</string>
@@ -273,6 +327,10 @@
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Разрешава на приложението да променя глобалната скорост на анимациите (по-бавни или по-бързи) по всяко време."</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"управление на означенията на приложения"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"Разрешава на приложението да създава и управлява собствени означения, заобикаляйки нормалния им z-ред. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
+    <!-- no translation found for permlab_freezeScreen (4708181184441880175) -->
+    <skip />
+    <!-- no translation found for permdesc_freezeScreen (8558923789222670064) -->
+    <skip />
     <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>
@@ -385,6 +443,14 @@
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Разрешава на приложението да използва функциите на SurfaceFlinger от ниско ниво."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"четене на кадровия буфер"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Разрешава на приложението да чете съдържанието на кадровия буфер."</string>
+    <!-- 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">"промяна на настройките ви за звука"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Разрешава на приложението да променя глобалните настройки за звука, като например силата и това, кой високоговорител се използва за изход."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"запис на звук"</string>
@@ -534,6 +600,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 +632,10 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Изисква съхраняваните данни за приложенията да бъдат шифровани."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Деактивиране на камерите"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Предотвратява употребата на камерите на всички устройства."</string>
+    <!-- no translation found for policylab_disableKeyguardWidgets (1794894613389073926) -->
+    <skip />
+    <!-- no translation found for policydesc_disableKeyguardWidgets (7254624892984033592) -->
+    <skip />
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Домашен"</item>
     <item msgid="869923650527136615">"Мобилен"</item>
@@ -930,8 +1002,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>
@@ -1033,6 +1105,13 @@
     <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_title" msgid="1666863092640877318">"Да се изпрати ли SMS до кратък код?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Да се изпрати ли импулсен SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&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;, което изглежда е кратък код на SMS.&lt;p&gt;Изпращането на съобщения до някои такива кодове може да доведе до таксуване на мобилната ви сметка за услуги, които се плащат допълнително.&lt;p&gt;Искате ли да разрешите на това приложение да изпрати съобщението?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&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;, което е кратък код за импулсен SMS.&lt;p&gt;&lt;b&gt;Изпращането до тази точка ще доведе до таксуване на мобилната ви сметка за услуги, които се плащат допълнително.&lt;/b&gt;&lt;p&gt;Искате ли да разрешите на това приложение да изпрати съобщението?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Изпращане на съобщението"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Да не се изпраща"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Сигнал за злонам. приложение"</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 +1122,9 @@
     <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_description_app" msgid="5139836143293299417">"Предоставено от <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Не се изискват разрешения"</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 +1223,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>
@@ -1290,4 +1370,45 @@
     <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="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="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="5183097160254244459">"PUK код"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Нов ПИН код"</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="5216603185442368307">"Въведете PUK код с поне осем цифри."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Въведете PUK и новия ПИН код"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"Въведеният от вас PUK код е неправилен."</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="8849589033659332457">"Проверява се…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</string>
 </resources>
diff --git a/core/res/res/values-ca-rES/donottranslate-cldr.xml b/core/res/res/values-ca-rES/donottranslate-cldr.xml
index 113133d..8feeeed 100644
--- a/core/res/res/values-ca-rES/donottranslate-cldr.xml
+++ b/core/res/res/values-ca-rES/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>
diff --git a/core/res/res/values-ca/donottranslate-cldr.xml b/core/res/res/values-ca/donottranslate-cldr.xml
index 03cf69d..3fda852 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>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 711030c..072e9be 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">"Realització d\'informe d\'errors"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Es recopilarà informació sobre l\'estat actual del dispositiu per enviar-la com a missatge de correu electrònic. Passarà un cert temps a partir del moment en què comenci a elaborar-se l\'informe d\'errors fins que no estigui llest per enviar; tingues 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Xarxes de poc abast"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Accés a dispositius mitjançant xarxes de poc abast, com ara NFC."</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 +222,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 +257,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>
@@ -243,6 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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>
@@ -534,6 +592,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>
@@ -564,6 +624,8 @@
     <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_disableKeyguardWidgets" msgid="1794894613389073926">"Desactivació dels widgets bloquejats"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Impedeix l\'ús de part o de la totalitat dels widgets bloquejats."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Casa"</item>
     <item msgid="869923650527136615">"Mòbil"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Vols enviar SMS a codi curt?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Vols enviar el SMS prèmium?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vol enviar un missatge de text a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, que sembla que és un codi SMS curt.&lt;p&gt;Si envies missatges de text a codis curts, pot ser que es carreguin serveis prèmium al teu compte mòbil.&lt;p&gt;Vols permetre que aquesta aplicació enviï el missatge?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vol enviar un missatge de text a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, que és un codi curt SMS prèmium.&lt;p&gt;&lt;b&gt;Si envies un missatge a aquesta destinació, es carregaran els serveis prèmium al teu compte mòbil.&lt;/b&gt;&lt;p&gt;Vols permetre que aquesta aplicació enviï el missatge?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Envia el missatge"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"No enviïs"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Informa d\'una aplic. maliciosa"</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 +1112,9 @@
     <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_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="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>
@@ -1147,6 +1213,10 @@
     <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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"Codi PUK"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Codi PIN nou"</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="5216603185442368307">"Introdueix un PUK que tingui com a mínim 8 números."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Introdueix el codi PUK i el codi PIN nou"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"El PUK que has escrit no és correcte."</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="8849589033659332457">"S\'està comprovant..."</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..42b3835 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Sítě krátkého dosahu"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Přístup do zařízení prostřednictvím sítí krátkého dosahu, např. NFC."</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 +222,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 +257,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 +289,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_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>
+    <!-- no translation found for permlab_magnify_display (5973626738170618775) -->
+    <skip />
+    <!-- no translation found for permdesc_magnify_display (7121235684515003792) -->
+    <skip />
     <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>
@@ -273,6 +327,10 @@
     <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>
+    <!-- no translation found for permlab_freezeScreen (4708181184441880175) -->
+    <skip />
+    <!-- no translation found for permdesc_freezeScreen (8558923789222670064) -->
+    <skip />
     <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>
@@ -385,6 +443,14 @@
     <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>
+    <!-- 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">"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>
@@ -534,6 +600,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 +632,10 @@
     <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>
+    <!-- no translation found for policylab_disableKeyguardWidgets (1794894613389073926) -->
+    <skip />
+    <!-- no translation found for policydesc_disableKeyguardWidgets (7254624892984033592) -->
+    <skip />
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Domů"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -831,7 +903,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 +1002,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>
@@ -1033,6 +1105,13 @@
     <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_title" msgid="1666863092640877318">"Odeslat SMS?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Odeslat zprávu Premium SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"Aplikace&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; chce odeslat zprávu na číslo &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, což je zřejmě číslo služby SMS.&lt;p&gt;Za odesílání zpráv na určitá čísla mohou být na mobilní účet naúčtovány poplatky za prémiové služby.&lt;p&gt;Chcete aplikaci povolit odeslání zprávy?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"Aplikace &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; chce poslat zprávu na číslo &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, což je číslo služby Premium SMS.&lt;p&gt;&lt;b&gt;Pokud zprávu odešlete na toto číslo, budou vám na mobilní účet naúčtovány poplatky za prémiové služby.&lt;/b&gt;&lt;p&gt;Chcete aplikaci povolit odeslání zprávy?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Odeslat zprávu"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Neodesílat"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Nahlásit škodlivou aplikaci"</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 +1122,9 @@
     <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_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="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 +1223,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>
@@ -1206,8 +1286,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>
@@ -1290,4 +1370,45 @@
     <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="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="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="5183097160254244459">"Kód PUK"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Nový 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="5216603185442368307">"Zadejte osmimístný nebo delší kód PUK."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Zadejte kód PUK a nový kód PIN."</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"Zadali jste nesprávný kód PUK."</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="8849589033659332457">"Kontrola…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..31034a7 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Kortrækkende netværk"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Få adgang til enheder via kortrækkende netværk, f.eks NFC."</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Deaktiver widgets på tastaturlåsen"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Undgå brug af nogle eller alle widgets på tastaturlåsen."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Hjem"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Send sms til shortcode?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Vil du sende en premium-sms?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vil du sende en sms til &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, som ser ud til at være en premium-sms-shortcode.&amp;.&lt;p&gt;Hvis du sender en sms til nogle shortcodes, kan det medføre, at din mobilkonto bliver debiteret for premium-tjenester.&lt;p&gt;Vil du tillade, at denne app sender beskeden?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vil du sende en sms til &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, som er en premium-sms-shortcode.&lt;p&gt;&lt;b&gt;Hvis du sender en besked til denne destination, bliver din mobilkonto debiteret for premium-tjenester.&lt;/b&gt;&lt;p&gt;Vil du tillade, at denne app sender beskeden?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Send besked"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Send ikke"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Rapportér ondsindet app"</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 +1112,9 @@
     <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_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="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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"PUK-kode"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Ny 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="5216603185442368307">"Angiv en PUK-kode på 8 eller flere cifre."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Indtast PUK-koden og den nye pinkode"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"Den indtastede PUK-kode er forkert."</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="8849589033659332457">"Kontrollerer..."</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..7176760 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Netzwerke im Nahbereich"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Auf Geräte über Netzwerke im Nahbereich wie NFC 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 +222,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 +257,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 +289,12 @@
     <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_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 die Anzeige möglicherweise, 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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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>
@@ -534,6 +592,8 @@
     <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="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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Widgets auf Keyguard deakt."</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Verwendung einiger oder aller Wigets auf Keyguard verhindern"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Privat"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -828,15 +890,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 +907,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 +927,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 +935,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,8 +992,8 @@
     <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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"SMS an Kurzwahl senden?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Premium-SMS senden?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; versucht, eine SMS an &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; zu senden. Dabei scheint es sich um eine SMS-Kurzwahl zu handeln.&lt;p&gt;Wenn Sie SMS an eine Kurzwahl senden, werden Ihnen für Ihr Mobilfunkkonto möglicherweise Premiumdienste in Rechnung gestellt.&lt;p&gt;Möchten Sie zulassen, dass die App die Nachricht sendet?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; versucht, eine SMS an die Premium-SMS-Kurzwahl &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; zu senden.&lt;p&gt;&lt;b&gt;Wenn Sie eine Nachricht an diese Zieladresse senden, werden Ihnen für Ihr Mobilfunkkonto Premiumdienste in Rechnung gestellt.&lt;/b&gt;&lt;p&gt;Möchten Sie zulassen, dass die App die Nachricht sendet?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Nachricht senden"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Nicht senden"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Schädliche App melden"</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 +1112,9 @@
     <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_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="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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"PUK-Code"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Neuer PIN-Code"</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="5216603185442368307">"Geben Sie eine mindestens 8-stellige PUK ein."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"PUK und neuen PIN-Code eingeben"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"Die von Ihnen eingegebene PUK ist nicht korrekt."</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="8849589033659332457">"Überprüfung…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..b55c86d 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Δίκτυα μικρού εύρους"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Πρόσβαση σε συσκευές μέσω δικτύων μικρού εύρους όπως NFC."</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Απεν.γραφ.στοιχ.ασφ.πλήκτρ."</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Παρεμπόδιση της χρήσης ορισμένων ή όλων των γραφικών στοιχείων στην ασφάλεια πλήκτρων."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Οικία"</item>
     <item msgid="869923650527136615">"Κινητό"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Να αποσταλεί SMS στον κωδικό;"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Να σταλεί SMS ειδικής χρέωσης;"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"Η εφαρμογή &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;, ο οποίος φαίνεται ότι είναι κωδικός για την αποστολή SMS με ειδική χρέωση.&lt;p&gt;Η αποστολή μηνύματος σε αυτόν τον αριθμό θα χρεωθεί στον λογαριασμό του κινητού σας ως παροχή υπηρεσιών.&lt;p&gt;Θέλετε να επιτρέψετε σε αυτήν την εφαρμογή να στείλει το μήνυμα;"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"Η εφαρμογή &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;, ο οποίος είναι ένας κωδικός αποστολής SMS με ειδική χρέωση.&lt;p&gt;&lt;b&gt;Η αποστολή μηνύματος σε αυτόν τον αριθμό θα χρεωθεί στον λογαριασμό του κινητού σας ως παροχή υπηρεσιών.&lt;/b&gt;&lt;p&gt;Θέλετε να επιτρέψετε σε αυτήν την εφαρμογή να στείλει το μήνυμα;"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Αποστολή μηνύματος"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Να μην αποσταλεί"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Αναφορά κακόβουλης εφαρμογής"</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 +1112,9 @@
     <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_description_app" msgid="5139836143293299417">"Παρέχεται από την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Δεν απαιτούνται άδειες"</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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"Κωδικός PUK"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Νέος κωδικός 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="5216603185442368307">"Πληκτρολογήστε έναν κωδικό PUK με 8 αριθμούς ή περισσότερους."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Πληκτρολογήστε τον κωδικό PUK και τον νέο κωδικό PIN"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"Ο κωδικός PUK που πληκτρολογήσατε είναι εσφαλμένος."</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="8849589033659332457">"Έλεγχος…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..cf45675 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 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>
     <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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Short-range Networks"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Access devices through short-range networks such as NFC."</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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 Wifi displays"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Allows the app to configure and connect to Wifi displays."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"control Wifi displays"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Allows the app to control low-level features of Wifi 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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Disable widgets on keyguard"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Prevent use of some or all widgets on keyguard."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Home"</item>
     <item msgid="869923650527136615">"Mobile"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Send SMS to short code?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Send premium SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; would like to send a text message to &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, which appears to be an SMS short code.&lt;p&gt;Sending text messages to some short codes may cause your mobile account to be billed for premium services.&lt;p&gt;do you want to allow this app to send the message?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; would like to send a text message to &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, which is a premium SMS short code.&lt;p&gt;&lt;b&gt;Sending a message to this destination will cause your mobile account to be billed for premium services.&lt;/b&gt;&lt;p&gt;Do you want to allow this app to send the message?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Send message"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Don\'t send"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Report malicious app"</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 +1112,9 @@
     <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_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="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 +1213,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>
@@ -1283,11 +1353,52 @@
     <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_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="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="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="5183097160254244459">"PUK code"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"New 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="5216603185442368307">"Type a PUK that is 8 numbers or longer."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Type PUK and new PIN code"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"The PUK you typed isn\'t correct."</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="8849589033659332457">"Checking…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..002ba84 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Redes de corto alcance"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Acceder a dispositivos a través de redes de corto alcance, como NFC"</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 vídeo"</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 +222,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 +257,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>
@@ -243,6 +289,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_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>
+    <!-- no translation found for permlab_magnify_display (5973626738170618775) -->
+    <skip />
+    <!-- no translation found for permdesc_magnify_display (7121235684515003792) -->
+    <skip />
     <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>
@@ -273,6 +327,10 @@
     <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>
+    <!-- no translation found for permlab_freezeScreen (4708181184441880175) -->
+    <skip />
+    <!-- no translation found for permdesc_freezeScreen (8558923789222670064) -->
+    <skip />
     <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>
@@ -385,6 +443,14 @@
     <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>
+    <!-- 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">"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>
@@ -534,6 +600,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 +632,10 @@
     <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>
+    <!-- no translation found for policylab_disableKeyguardWidgets (1794894613389073926) -->
+    <skip />
+    <!-- no translation found for policydesc_disableKeyguardWidgets (7254624892984033592) -->
+    <skip />
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Casa"</item>
     <item msgid="869923650527136615">"Móvil"</item>
@@ -930,8 +1002,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>
@@ -1033,6 +1105,13 @@
     <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_title" msgid="1666863092640877318">"¿Enviar SMS premium?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"¿Enviar SMS premium?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; quiere enviar un mensaje de texto a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, y parece que se trata de un SMS premium.&lt;p&gt;Al enviar mensajes de texto a estos números, es posible que se facturen servicios premium en tu cuenta móvil.&lt;p&gt;¿Quieres permitir que esta aplicación envíe el mensaje?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; quiere enviar un mensaje de texto a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, y se trata de un SMS premium.&lt;p&gt;&lt;b&gt;Al enviar un mensaje a este destino, se podrán facturar servicios premium en tu cuenta móvil.&lt;/b&gt;&lt;p&gt;¿Quieres permitir que esta aplicación envíe el mensaje?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Enviar mensaje"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"No enviar"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Notificar aplicación malintencionada"</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 +1122,9 @@
     <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_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="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>
@@ -1147,6 +1223,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>
@@ -1290,4 +1370,45 @@
     <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="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="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="5183097160254244459">"Código PUK"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Nuevo 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">"Escribe un PIN que tenga de cuatro a ocho números."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="5216603185442368307">"Ingresa un código PUK de ocho números o más."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Escribe el código PUK y un nuevo código PIN."</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"El código PUK que escribiste es incorrecto."</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="8849589033659332457">"Comprobando…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..ba1e76e 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">"Hacer 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Redes de corto alcance"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Acceder a dispositivos a través de redes de corto alcance, como NFC"</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Inhabilitar widgets durante el bloqueo"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Evita el uso de algunos widgets, o de todos ellos, durante el bloqueo."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Casa"</item>
     <item msgid="869923650527136615">"Móvil"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"¿Enviar SMS premium?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"¿Enviar SMS premium?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; quiere enviar un mensaje de texto a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; y parece que se trata de un SMS premium.&lt;p&gt;Al enviar mensajes de texto a estos números, es posible que se facturen servicios premium en tu cuenta móvil.&lt;p&gt;¿Quieres permitir que esta aplicación envíe el mensaje?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; quiere enviar un mensaje de texto a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; y se trata de un SMS premium.&lt;p&gt;&lt;b&gt;Al enviar un mensaje a este destino, se podrán facturar servicios premium en tu cuenta móvil.&lt;/b&gt;&lt;p&gt;¿Quieres permitir que esta aplicación envíe el mensaje?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Enviar mensaje"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"No enviar"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Notificar aplicación malintencionada"</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 +1112,9 @@
     <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_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="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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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">"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">"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."</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="5183097160254244459">"Código PUK"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Nuevo 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="5216603185442368307">"Escribe un código PUK de ocho caracteres o más."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Introduce el código PUK y un nuevo código PIN."</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"El código PUK que has introducido no es correcto."</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="8849589033659332457">"Comprobando..."</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..5c7ffc3 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Lähisidevõrgud"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Juurdepääs seadmetele lähisidevõrgu (nt NFC) 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 +222,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 +257,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 +289,12 @@
     <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_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 kuva 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>
@@ -273,6 +325,8 @@
     <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äisekraanil ü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>
@@ -385,6 +439,10 @@
     <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-kuvade seadistamine"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Lubab rakendusel seadistada WiFi-kuvasid ja nendega ühendus luua."</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"WiFi-kuvade juhtimine"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Lubab rakendusel juhtida WiFi-kuvade 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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Vidinate keel. klahvilukuga"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Keelake mõne või kõigi vidinate kasutamine klahviluku abil."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Kodu"</item>
     <item msgid="869923650527136615">"Mobiil"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Kas saata SMS lühinumbrile?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Kas saata tasuline SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tahab saata tekstsõnumi adressaadile &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, mis paistab olevat SMS-i lühinumber.&lt;p&gt;Mõnele lühinumbrile saadetud sõnumi eest võidakse teie mobiilikontole esitada arve tasuliste teenuste eest.&lt;p&gt;Kas lubate rakendusel selle sõnumi saata?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tahab saata tekstsõnumi adressaadile &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, mis on tasulise SMS-i lühinumber.&lt;p&gt;&lt;b&gt;Kui saadate sõnumi sellele adressaadile, esitatakse teie mobiilikontole arve tasuliste teenuste eest.&lt;/b&gt;&lt;p&gt;Kas lubate rakendusel sõnumi saata?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Saada sõnum"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Ära saada"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Teata pahatahtlikust rakend."</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 +1112,9 @@
     <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_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="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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"PUK-kood"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Uus 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="5216603185442368307">"Sisestage 8-numbriline või pikem PUK-kood."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Sisestage PUK-kood ja uus PIN-kood"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"Sisestatud PUK-kood pole õige."</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="8849589033659332457">"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_temp_back_string" msgid="5812983904056640466">"&lt;"</string>
 </resources>
diff --git a/core/res/res/values-fa/donottranslate-cldr.xml b/core/res/res/values-fa/donottranslate-cldr.xml
index 11473fe..b05268e 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>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index f52ab95..e9b02b04 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -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,59 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"شبکه‌های نزدیک"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"از طریق شبکه‌های نزدیک مانند NFC، به دستگاه‌ها دسترسی داشته باشد."</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 +248,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 +272,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,27 +289,33 @@
     <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_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="permdesc_batteryStats" msgid="6835186932305744068">"به برنامه اجازه می‎دهد تا آمار جمع‌آوری شده باتری را تغییر دهد. برای استفاده برنامه‎های عادی نیست."</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>
@@ -273,8 +325,10 @@
     <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 +350,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="3523396284474042284">"به برنامه اجازه می‎دهد تا حافظه رایانهٔ لوحی را با حذف فایل‌ها در فهرست حافظهٔ پنهان برنامه آزاد کند. معمولا دسترسی برای پردازش سیستم بسیار محدود است."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"به برنامه اجازه می‎دهد تا با حذف فایل‌ها در فهرست حافظهٔ پنهان برنامه حافظه تلفن را آزاد کند. معمولا دسترسی به پردازش سیستم بسیار محدود است."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"انتقال منابع برنامه"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"به برنامه اجازه می‎دهد تا منابع برنامه را از رسانه داخلی به رسانه خارجی و بالعکس منتقل کند."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"مطالعه داده‌های گزارش حساس"</string>
-    <string name="permdesc_readLogs" product="tablet" msgid="82061313293455151">"به برنامه اجازه می‎دهد فایل‌های مختلف گزارش سیستم را بخواند. با این کار، برنامه اطلاعات کلی مربوط به کاری که با رایانه لوحی انجام می‎دهید را کشف می‌کند، که ممکن است حاوی اطلاعات شخصی و خصوصی باشند."</string>
+    <string name="permdesc_readLogs" product="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 +393,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>
@@ -377,7 +431,7 @@
     <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="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>
@@ -385,20 +439,24 @@
     <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 +481,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 +500,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 +518,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 +547,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="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>
@@ -534,8 +592,10 @@
     <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_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>
@@ -547,23 +607,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_disableKeyguardWidgets" msgid="1794894613389073926">"غیرفعال کردن ابزارک‌های موجود در محافظ کلید"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"از استفاده از همه ابزارک‌های موجود در محافظ کلید یا برخی از آنها جلوگیری شود."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"خانه"</item>
     <item msgid="869923650527136615">"تلفن همراه"</item>
@@ -703,7 +765,7 @@
     <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" 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 +783,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 +800,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>
@@ -758,8 +820,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 +848,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 +884,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 +992,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,14 +1026,14 @@
     <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_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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"پیامک به کد کوتاه ارسال شود؟"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"پیامک ممتاز ارسال شود؟"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&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;, ارسال کند که به نظر می‌رسد یک کد کوتاه پیامک است.&lt;p&gt;ارسال پیام‌های نوشتاری به برخی از کدهای کوتاه ممکن است باعث شود برای حساب تلفن همراه شما بابت استفاده از سرویس‌های ممتاز صورتحساب ارسال شود.&lt;p&gt;آیا به این برنامه اجازه می‌دهید پیام ارسال کند؟"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&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;, ارسال کند که یک کد کوتاه پیامک ممتاز است.&lt;p&gt;&lt;b&gt;ارسال پیام به این مقصد ممکن است باعث شود برای حساب تلفن همراه شما بابت استفاده از سرویس‌های ممتاز صورتحساب ارسال شود.&lt;/b&gt;&lt;p&gt;آیا به این برنامه اجازه می‌دهید پیامک ارسال کند؟"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"ارسال پیام"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"ارسال نشود"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"گزارش برنامه مخرب"</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 +1112,22 @@
     <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_description_app" msgid="5139836143293299417">"ارائه شده توسط <xliff:g id="APP_NAME">%1$s</xliff:g> ."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"مجوزی لازم نیست"</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 +1135,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 +1149,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 +1167,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 +1205,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 +1213,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>
@@ -1272,7 +1342,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,7 +1352,7 @@
     <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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"کد PUK"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"پین کد جدید"</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="5216603185442368307">"یک PUK با ۸ رقم یا بیشتر تایپ کنید."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"PUK و پین کد جدید را تایپ کنید"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"PUK که نوشته‌اید صحیح نیست."</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="8849589033659332457">"در حال بررسی..."</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..1f18015 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Lyhyen kantaman verkot"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Käytä laitteita lyhyen kantaman verkkojen kuten NFC:n 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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Näpp.luk: widgetit pois käyt."</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Estä joidenkin tai kaikkien widgetien käyttö näppäinlukolla."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Puhelinnumero (koti)"</item>
     <item msgid="869923650527136615">"Mobiili"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Lähetetäänkö viesti?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Lähetä maksullinen viesti?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; haluaa lähettää tekstiviestin kohteeseen &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, joka voi olla maksullinen numero.&lt;p&gt;&lt;b&gt;Jos lähetät viestin tähän kohteeseen, sinua saatetaan veloittaa maksullisten palveluiden käytöstä.&lt;/b&gt;&lt;p&gt;Annetaanko sovelluksen lähettää viesti?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; haluaa lähettää tekstiviestin kohteeseen &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, joka on maksullinen numero.&lt;p&gt;&lt;b&gt;Jos lähetät viestin tähän kohteeseen, sinua veloitetaan maksullisten palveluiden käytöstä.&lt;/b&gt;&lt;p&gt;Annetaanko sovelluksen lähettää viesti?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Lähetä viesti"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Älä lähetä"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Ilmoita haittasovelluksesta"</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 +1112,9 @@
     <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_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="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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"PUK-koodi"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Uusi 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="5216603185442368307">"Kirjoita vähintään 8 numeron pituinen PUK-koodi."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Anna PUK-koodi ja uusi PIN-koodi"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"Antamasi PUK-koodi on virheellinen."</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="8849589033659332457">"Tarkistetaan..."</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..5e80fd5 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Réseaux de courte portée"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Accéder aux appareils via des réseaux de courte portée tels que la NFC"</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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 bas niveau 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 +536,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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Désact. widgets si protection clavier"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Empêcher l\'utilisation de tout ou partie des widgets lorsque la protection du clavier est activée"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Domicile"</item>
     <item msgid="869923650527136615">"Mobile"</item>
@@ -702,7 +764,7 @@
     <string name="lockscreen_charged" msgid="4938930459620989972">"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="7381499217732227295">"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>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Envoyer SMS au numéro abrégé ?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Envoyer un SMS premium ?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; essaie d\'envoyer un SMS à &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;. Il s\'agit apparemment d\'un numéro abrégé.&lt;p&gt;L\'envoi de SMS à de tels numéros peut entraîner la facturation de services premium sur votre compte mobile.&lt;p&gt;Autorisez-vous cette application à envoyer ce message ?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; essaie d\'envoyer un SMS à &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;. Il s\'agit apparemment d\'un numéro abrégé de type premium.&lt;p&gt;&lt;b&gt;L\'envoi de SMS à ce destinataire entraînera la facturation de services premium sur votre compte mobile.&lt;/b&gt;&lt;p&gt;Autorisez-vous cette application à envoyer le message ?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Envoyer le message"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Ne pas envoyer"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Signaler appli malveillante"</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 +1112,9 @@
     <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_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="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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"Clé PUK"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Nouveau code PIN"</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">"Saisissez un code PIN comprenant entre quatre et huit chiffres"</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="5216603185442368307">"Saisissez une clé PUK comportant au moins huit chiffres."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Saisissez la clé PUK et le nouveau code PIN"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"La clé PUK saisie est incorrecte."</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="8849589033659332457">"Vérification 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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..bacab1b 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"कम सीमा वाले नेटवर्क"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"कम सीमा वाले नेटवर्क जैसे NFC के माध्‍यम से उपकरणों पर पहुंचें."</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 +222,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 +257,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 +276,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 +289,12 @@
     <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_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,7 +311,7 @@
     <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="permlab_batteryStats" msgid="7863923071360031652">"बैटरी आंकड़े बदलें"</string>
     <string name="permdesc_batteryStats" msgid="6835186932305744068">"एप्‍लिकेशन को बैटरी के संकलित आंकड़ों को संशोधित करने देता है. सामान्‍य एप्‍लिकेशन द्वारा उपयोग करने के लिए नहीं."</string>
     <string name="permlab_backup" msgid="470013022865453920">"सिस्‍टम बैकअप नियंत्रित और पुनर्स्‍थापित करें"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"एप्लिकेशन को सिस्टम के बैकअप को नियंत्रित और क्रियाविधि को पुर्नस्थापित करने देता है. सामान्‍य एप्‍लिकेशन द्वारा उपयोग करने के लिए नहीं."</string>
@@ -269,10 +321,12 @@
     <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="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>
@@ -332,11 +386,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 +401,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 +412,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>
@@ -385,6 +439,10 @@
     <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 +496,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 +513,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>
@@ -528,12 +586,14 @@
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"संरक्ष‍ित संग्रहण पर पहुंच का परीक्षण करें"</string>
     <string name="permdesc_sdcardRead" product="nosdcard" msgid="5791957130190763289">"एप्लि. को 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 +602,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"कीगार्ड पर विजेट को अक्षम करें"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"कीगार्ड पर कुछ या सभी विजेट का उपयोग रोकें."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"घर"</item>
     <item msgid="869923650527136615">"मोबाइल"</item>
@@ -711,7 +773,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>
@@ -762,7 +824,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 +854,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 +983,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 +1044,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"शॉर्ट कोड पर SMS भेजें?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"प्रीमियम SMS भेजें?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&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; को एक पाठ संदेश भेजना चाहता है, जो एक SMS शॉर्ट कोड लगता है.&lt;p&gt;कुछ शॉर्ट कोड को पाठ संदेश भेजने से आपके मोबाइल खाते पर प्रीमियम सेवाओं का शुल्क लिया जा सकता है.&lt;p&gt;क्या आप इस एप्लिकेशन को यह संदेश भेजने देना चाहते हैं?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&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; को एक पाठ संदेश भेजना चाहता है, जो एक प्रीमियम SMS शॉर्ट कोड है.&lt;p&gt;&lt;b&gt;इस गंतव्य पर कोई संदेश भेजने से आपके मोबाइल खाते पर प्रीमियम सेवाओं का शुल्क लिया जाएगा.&lt;/b&gt;&lt;p&gt;क्या आप इस एप्लिकेशन को संदेश भेजने देना चाहते हैं?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"संदेश भेजें"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"न भेजें"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"दुर्भावनापूर्ण एप्लि. की रिपोर्ट करें"</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 +1112,9 @@
     <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_description_app" msgid="5139836143293299417">"<xliff:g id="APP_NAME">%1$s</xliff:g> द्वारा प्रदत्त."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"किसी अनुमति की आवश्‍यकता नहीं है"</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 +1123,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 +1151,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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"PUK कोड"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"नया 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="5216603185442368307">"ऐसा PUK लिखें जो 8 अंकों या अधिक का हो."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"PUK और नया PIN कोड लिखें"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"आपके द्वारा लिखा गया PUK सही नहीं है."</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="8849589033659332457">"जांच कर रहा है..."</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..e138022 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Mreže kratkog dometa"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Pristupajte uređajima putem mreža kratkog dometa kao što je NFC."</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Onemogući widgete na zaštiti"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Spriječi upotrebu nekih ili svih widgeta na zaštiti tipkovnice."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Početna"</item>
     <item msgid="869923650527136615">"Mobilni"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Poslati SMS na skraćeni broj?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Poslati premium SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"Aplikacija &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; želi poslati tekstnu poruku na &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, a čini se da je to skraćeni SMS broj.&lt;p&gt;Slanje tekstnih poruka na neke skraćene interne brojeve može dovesti do naplate premium usluga na vašem računu mobilnog uređaja.&lt;p&gt;Želite li dopustiti aplikaciji da pošalje poruku?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"Aplikacija &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; želi poslati tekstnu poruku na &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, a to je skraćeni premium SMS broj.&lt;p&gt;&lt;b&gt;Slanje poruke na taj broj dovest će do naplate premium usluga na vašem računu mobilnog uređaja.&lt;/b&gt;&lt;p&gt;Želite li dopustiti toj aplikaciji da pošalje poruku?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Pošalji poruku"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Ne šalji"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Prijavi zlonamjerne aplikacije"</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 +1112,9 @@
     <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_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="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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"PUK kôd"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Novi 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="5216603185442368307">"Upišite PUK koji se sastoji od barem 8 brojeva."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Unesite PUK i novi PIN kôd"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"PUK koji ste unijeli nije točan."</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="8849589033659332457">"Provjeravanje…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..3c1a856 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Rövid hatótávolságú hálózatok"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Eszközökhöz való hozzáférés rövid hatótávolságú hálózaton, például NFC-n 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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Modulletiltás billentyűzárnál"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Néhány vagy az összes modul letiltása billentyűzár esetén."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Otthoni"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"SMS küldése a rövid kódra?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Elküldi az emelt díjas SMS-t?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"A(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; szöveges üzenetet szeretne küldeni a(z) &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; címre, ami egy SMS rövid kódja.&lt;p&gt;Az egyes rövid kódokra küldött üzenetek miatt mobilszámláján emelt díjas szolgáltatások lesznek kiszámlázva.&lt;/b&gt;&lt;p&gt;Engedélyezi, hogy az alkalmazás elküldje az üzenetet?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"A(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; szöveges üzenetet szeretne küldeni a(z) &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; címre, ami egy emelt díjas SMS rövid kódja.&lt;p&gt;Az ide küldött üzenet miatt mobilszámláján emelt díjas szolgáltatások lesznek kiszámlázva.&lt;/b&gt;&lt;p&gt;Engedélyezi, hogy az alkalmazás elküldje az üzenetet?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Üzenet küldése"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Nincs küldés"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Rosszindulatú alk. bejelentése"</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 +1112,9 @@
     <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_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="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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"PUK kód"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Új PIN kód"</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="5216603185442368307">"8 számjegyű vagy hosszabb PUK kódot írjon be."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Írja be a PUK kódot, majd az új PIN kódot"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"A megadott PUK kód helytelen."</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="8849589033659332457">"Ellenőrzés..."</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..bd1d23e 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,6 +154,9 @@
     <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>
@@ -168,12 +171,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Jaringan jarak pendek"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Mengakses perangkat melalui jaringan jarak pendek seperti NFC."</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Nonaktifkan widgets pd keyguad"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Mencegah penggunaan beberapa atau semua widget di keyguard."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Rumah"</item>
     <item msgid="869923650527136615">"Seluler"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Kirim SMS ke kode singkat?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Kirim SMS premium?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; akan mengirim pesan teks ke &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, yang akan muncul sebagai kode singkat SMS.&lt;p&gt;Mengirim pesan teks ke beberapa kode singkat menyebabkan Anda dikenakan biaya layanan premium pada akun seluler Anda.&lt;p&gt;Izinkan aplikasi ini mengirim pesan?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; akan mengirim pesan teks ke &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, yang merupakan kode singkat SMS premium.&lt;p&gt;&lt;b&gt;Mengirim pesan ke tujuan ini menyebabkan Anda dikenakan biaya layanan premium pada akun seluler Anda.&lt;/b&gt;&lt;p&gt;Izinkan aplikasi ini mengirim pesan?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Kirim pesan"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Jangan kirim"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Laporkan aplikasi berbahaya"</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 +1112,9 @@
     <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_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="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 +1213,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,7 +1248,7 @@
     <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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"Kode PUK"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Kode PIN baru"</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="5216603185442368307">"Ketik PUK yang terdiri dari 8 angka atau lebih."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Ketik kode PUK dan PIN baru"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"PUK yang Anda ketikkan salah."</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="8849589033659332457">"Memeriksa…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..bd3dfc2 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Reti a corto raggio"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"È possibile accedere ai dispositivi tramite reti a corto raggio come le NFC."</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Disattiv. widget (blocco tastiera)"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Consente di impedire l\'utilizzo di alcuni o di tutti i widget con il blocco tastiera."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Casa"</item>
     <item msgid="869923650527136615">"Cellulare"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Inviare SMS a codice breve?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Inviare SMS premium?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vorrebbe inviare un messaggio di testo a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, che sembra essere un codice breve SMS.&lt;p&gt;L\'invio di messaggi di testo ad alcuni codici brevi potrebbe comportare l\'addebito di servizi premium sul tuo account per cellulari.&lt;p&gt;Vuoi consentire a questa applicazione di inviare il messaggio?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vorrebbe inviare un messaggio di testo a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, che è un codice breve SMS premium.&lt;p&gt;&lt;b&gt;L\'invio di un messaggio a questa destinazione comporterà l\'addebito di servizi premium sul tuo account per cellulari.&lt;/b&gt;&lt;p&gt;Vuoi consentire a questa applicazione di inviare il messaggio?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Invia messaggio"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Non inviare"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Segnala applicazione dannosa"</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 +1112,9 @@
     <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_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="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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"Codice PUK"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Nuovo codice PIN"</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="5216603185442368307">"Digita un PUK formato da almeno 8 numeri."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Inserisci il PUK e il nuovo codice PIN"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"Il PUK digitato è errato."</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="8849589033659332457">"Verifica…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..5443b5d 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"רשתות לטווח קצר"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"גישה למכשירים באמצעות רשתות קצרות-טווח, כגון רשתות NFC."</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"השבת Widgets ב-Keyguard"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"מנע שימוש של חלק מה-Widgets או כולם ב-Keyguard"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"בית"</item>
     <item msgid="869923650527136615">"נייד"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"לשלוח SMS לקוד קצר?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"לשלוח SMS פרימיום?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&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;, שנראה כמו קוד SMS קצר. &lt;p&gt; שליחת הודעות טקסט לקודים קצרים מסוימים עשויה לגרום לחיוב חשבון הנייד שלך בשירותי פרימיום. &lt;p&gt; האם ברצונך לאפשר ליישום זה לשלוח את ההודעה?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&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;, שהוא קוד פרימיום קצר של SMS. &lt;b&gt; &lt;p&gt; שליחת הודעה ליעד זה תגרום לחיוב חשבון הנייד שלך בשירותי פרימיום. &lt;/ b&gt; &lt;p&gt; האם ברצונך לאפשר ליישום זה לשלוח את ההודעה?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"שלח הודעה"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"אל תשלח"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"דווח על יישום זדוני"</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 +1112,9 @@
     <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_description_app" msgid="5139836143293299417">"מטעם <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"לא דרושים אישורים"</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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"קוד PUK"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"קוד 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="5216603185442368307">"הקלד PUK באורך 8 ספרות או יותר."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"הקלד את קוד ה-PUK וקוד ה-PIN החדש"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"ה-PUK שהקלדת שגוי."</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="8849589033659332457">"בודק…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..905b0ab 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"短距離ネットワーク"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"NFCなどの近距離ネットワーク経由でデバイスにアクセスします。"</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 +222,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 +257,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 +289,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_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>
+    <!-- no translation found for permlab_magnify_display (5973626738170618775) -->
+    <skip />
+    <!-- no translation found for permdesc_magnify_display (7121235684515003792) -->
+    <skip />
     <string name="permlab_shutdown" msgid="7185747824038909016">"部分的にシャットダウンする"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"アクティビティマネージャをシャットダウン状態にします。完全なシャットダウンは実行しません。"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"アプリケーションの切り替えを禁止する"</string>
@@ -273,6 +327,10 @@
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"いつでもアニメーション全般の速度を変更する(速くする、または遅くする)ことをアプリに許可します。"</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"アプリのトークンの管理"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"通常のZ-orderingを回避して独自のトークンを作成、管理することをアプリに許可します。通常のアプリでは不要です。"</string>
+    <!-- no translation found for permlab_freezeScreen (4708181184441880175) -->
+    <skip />
+    <!-- no translation found for permdesc_freezeScreen (8558923789222670064) -->
+    <skip />
     <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>
@@ -385,6 +443,14 @@
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"SurfaceFlingerの低レベルの機能の使用をアプリに許可します。"</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"フレームバッファの読み取り"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"フレームバッファの内容の読み取りをアプリに許可します。"</string>
+    <!-- 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">"音声設定の変更"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"音声全般の設定(音量、出力に使用するスピーカーなど)の変更をアプリに許可します。"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"録音"</string>
@@ -534,6 +600,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 +632,10 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"保存したアプリデータが暗号化されるようにします。"</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"カメラを無効にする"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"すべての端末カメラを使用できないようにします。"</string>
+    <!-- no translation found for policylab_disableKeyguardWidgets (1794894613389073926) -->
+    <skip />
+    <!-- no translation found for policydesc_disableKeyguardWidgets (7254624892984033592) -->
+    <skip />
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"自宅"</item>
     <item msgid="869923650527136615">"携帯"</item>
@@ -760,7 +832,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 +1002,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>
@@ -1033,6 +1105,13 @@
     <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_title" msgid="1666863092640877318">"ショートコードへのSMSの送信"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"プレミアムSMSを送信しますか?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;が、SMSショートコードと思われる&lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;にテキストメッセージを送信しようとしています。&lt;p&gt;一部のショートコードにテキストメッセージを送信すると、プレミアムサービスの料金がモバイルアカウントが請求される場合があります。&lt;p&gt;このアプリにメッセージの送信を許可しますか?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;が、プレミアムSMSショートコード&lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;にテキストメッセージを送信しようとしています。&lt;p&gt;&lt;b&gt;この宛先にメッセージを送信すると、プレミアムサービスの料金がモバイルアカウントに請求されます。&lt;/b&gt;&lt;p&gt;このアプリにメッセージの送信を許可しますか?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"メッセージを送信"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"送信しない"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"悪意のあるアプリを報告"</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 +1122,9 @@
     <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_description_app" msgid="5139836143293299417">"<xliff:g id="APP_NAME">%1$s</xliff:g>で提供されます。"</string>
+    <string name="no_permissions" msgid="7283357728219338112">"権限の許可は必要ありません"</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 +1223,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>
@@ -1290,4 +1370,45 @@
     <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="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="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="5183097160254244459">"PUKコード"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"新しい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="5216603185442368307">"PUKは8桁以上で入力してください。"</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"PUKと新しいPINコードを入力"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"入力したPUKは正しくありません。"</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="8849589033659332457">"チェックしています…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..8377e56 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"단거리 네트워크"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"NFC와 같은 단거리 네트워크를 통해 기기에 액세스"</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"키가드에서 위젯 사용 중지"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"키가드에서 일부 또는 전체 위젯을 사용하지 못하도록 합니다."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"집"</item>
     <item msgid="869923650527136615">"모바일"</item>
@@ -781,7 +843,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 +974,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 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"SMS를 단축 코드로 보내시겠습니까?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"프리미엄 SMS를 보내시겠습니까?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;이(가) SMS 단축 코드로 추정되는 문자 메시지를 &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;(으)로 보내려 합니다.&lt;p&gt;문자 메시지를 단축 코드로 보내면 사용자의 모바일 계정에 프리미엄 서비스 요금이 청구될 수 있습니다.&lt;p&gt;해당 앱이 메시지를 보내도록 하시겠습니까?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;이(가) 문자 메시지를 프리미엄 SMS 단축 코드인 &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;(으)로 보내려 합니다.&lt;p&gt;&lt;b&gt;메시지를 보내면 사용자의 모바일 계정에 프리미엄 서비스 요금이 청구됩니다.&lt;/b&gt;&lt;p&gt;해당 앱이 메시지를 보내도록 하시겠습니까?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"메시지 보내기"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"보내지 않음"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"악성 앱 신고"</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 +1112,9 @@
     <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_description_app" msgid="5139836143293299417">"<xliff:g id="APP_NAME">%1$s</xliff:g> 제공"</string>
+    <string name="no_permissions" msgid="7283357728219338112">"권한 필요 없음"</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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"PUK 코드"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"새 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="5216603185442368307">"8자리 이상의 숫자 PUK를 입력합니다."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"PUK 및 새 PIN 코드 입력"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"입력한 PUK가 올바르지 않습니다."</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="8849589033659332457">"확인 중…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</string>
 </resources>
diff --git a/core/res/res/values-land/arrays.xml b/core/res/res/values-land/arrays.xml
index 6db3a508..1cd9e74 100644
--- a/core/res/res/values-land/arrays.xml
+++ b/core/res/res/values-land/arrays.xml
@@ -69,11 +69,4 @@
         <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>
-    </array>
-
 </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..7284a8a 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Artimojo lauko tinklai"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Pasiekti įrenginius per artimojo lauko tinklus, pvz., ALR."</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Neleisti vald. klav. apsaug."</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Neleisti naudoti kelių ar visų valdiklių klaviatūros apsaugoje."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Pagrindinis"</item>
     <item msgid="869923650527136615">"Mobilusis"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Siųsti SMS trumpuoju numeriu?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Siųsti brangesnį SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"Naudojant &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prašoma išsiųsti teksto pranešimą &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, o tai yra trumpasis SMS numeris.&lt;p&gt;&lt;b&gt;Siųsdami pranešimus kai kuriais trumpaisiais numeriais galite būti apmokestinti mobiliojo ryšio sąskaitoje už brangesnes paslaugas.&lt;/b&gt;&lt;p&gt;Ar norite leisti šiai programai siųsti pranešimą?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"Naudojant &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prašoma išsiųsti teksto pranešimą &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, o tai yra brangesnis trumpasis SMS numeris.&lt;p&gt;&lt;b&gt;Siųsdami pranešimą šiam gavėjui mobiliojo ryšio sąskaitoje būsite apmokestinti už brangesnes paslaugas.&lt;/b&gt;&lt;p&gt;Ar norite leisti šiai programai siųsti pranešimą?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Siųsti pranešimą"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Nesiųsti"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Pranešti apie kenkėj. programą"</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 +1112,9 @@
     <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_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="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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"PUK kodas"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Naujas PIN kodas"</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="5216603185442368307">"Įveskite 8 skaitmenų ar ilgesnį PUK kodą."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Įveskite PUK ir naują PIN kodus"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"Įvestas PUK kodas netinkamas."</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="8849589033659332457">"Tikrinama…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..1007777 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Tuva darbības lauka tīkli"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Piekļūt ierīcēm, izmantojot tuva darbības lauka tīklus, piemēram, TDLS."</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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">"ekrāna fiksēšana"</string>
+    <string name="permdesc_freezeScreen" msgid="8558923789222670064">"Ļauj lietojumprogrammai īslaicīgi fiksēt ekrānu, 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>
@@ -385,6 +439,10 @@
     <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 izveidot 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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Logrīku atspēj. tast. bloķētājā"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Aizliedziet dažu vai visu logrīku izmantošanu ierīces tastatūras bloķētājā."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Mājas"</item>
     <item msgid="869923650527136615">"Mobilais"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Vai sūtīt īsziņu uz īso kodu?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Vai nosūtīt īpašo īsziņu?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"Lietotne &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vēlas nosūtīt īsziņu uz adresi &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, kas, iespējams, ir īsziņas īsais kods.&lt;p&gt;&lt;b&gt;Sūtot īsziņas uz dažiem īsajiem kodiem, no jūsu mobilā konta var tikt iekasēta maksa par paaugstinātas maksas pakalpojumiem.&lt;/b&gt;&lt;p&gt;Vai vēlaties atļaut šai lietotnei sūtīt šo ziņojumu?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"Lietotne &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vēlas nosūtīt īsziņu uz adresi &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, kas, iespējams, ir paaugstinātas maksas īsziņas īsais kods.&lt;p&gt;&lt;b&gt;Sūtot ziņojumu uz šo galamērķi, no jūsu mobilā konta tiks iekasēta maksa par paaugstinātas maksas pakalpojumiem.&lt;/b&gt;&lt;p&gt;Vai vēlaties atļaut šai lietotnei sūtīt šo ziņojumu?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Sūtīt ziņojumu"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Nesūtīt"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Ziņot par ļaunprātīgu lietotni"</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 +1112,9 @@
     <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_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="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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"PUK kods"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Jauns PIN kods"</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="5216603185442368307">"Ievadiet PUK, kas sastāv no vismaz 8 cipariem."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Ievadiet PUK kodu un jaunu PIN kodu"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"Ievadītais PUK nav pareizs."</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="8849589033659332457">"Notiek 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_temp_back_string" msgid="5812983904056640466">"&lt;"</string>
 </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..f5d9de7 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Rangkaian jarak-dekat"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Akses peranti melalui rangkaian jarak dekat seperti NFC."</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 +222,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 +257,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 +289,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_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>
+    <!-- no translation found for permlab_magnify_display (5973626738170618775) -->
+    <skip />
+    <!-- no translation found for permdesc_magnify_display (7121235684515003792) -->
+    <skip />
     <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>
@@ -273,6 +327,10 @@
     <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>
+    <!-- no translation found for permlab_freezeScreen (4708181184441880175) -->
+    <skip />
+    <!-- no translation found for permdesc_freezeScreen (8558923789222670064) -->
+    <skip />
     <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>
@@ -385,6 +443,14 @@
     <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>
+    <!-- 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">"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>
@@ -534,6 +600,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 +632,10 @@
     <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>
+    <!-- no translation found for policylab_disableKeyguardWidgets (1794894613389073926) -->
+    <skip />
+    <!-- no translation found for policydesc_disableKeyguardWidgets (7254624892984033592) -->
+    <skip />
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Laman Utama"</item>
     <item msgid="869923650527136615">"Mudah alih"</item>
@@ -930,8 +1002,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>
@@ -1033,6 +1105,13 @@
     <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_title" msgid="1666863092640877318">"Hantar SMS ke kod pendek?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Hantar SMS premium?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ingin menghantar mesej teks kepada &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, yang merupakan kod pendek SMS.&lt;p&gt;Menghantar mesej teks ke sesetengah kod pendek boleh menyebabkan akaun mudah alih anda dikenakan bayaran perkhidmatan premium.&lt;p&gt;Adakah anda mahu membenarkan apl ini menghantar mesej itu?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ingin menghantar mesej teks ke &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, yang merupakan kod pendek SMS premium.&lt;p&gt;&lt;b&gt;Menghantar mesej ke destinasi ini akan menyebabkan akaun mudah alih anda dikenakan bayaran untuk perkhidmatan premium.&lt;/b&gt;&lt;p&gt;Adakah anda mahu membenarkan apl ini menghantar mesej itu?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Hantar mesej"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Jangan hantar"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Laporkan aplikasi hasad"</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 +1122,9 @@
     <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_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="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 +1223,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>
@@ -1290,4 +1370,45 @@
     <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="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="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="5183097160254244459">"Kod PUK"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Kod PIN Baharu"</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="5216603185442368307">"Taipkan PUK yang mempunyai 8 nombor atau lebih panjang."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Taip PUK dan kod PIN baharu"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"Kod PUK yang anda taipkan tidak betul."</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="8849589033659332457">"Menyemak…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..5d7c6fa 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Nettverk med kort rekkevidde"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Bruke enheter via nettverk med kort rekkevidde, som NFC."</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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>
@@ -534,6 +592,8 @@
     <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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Deaktivere moduler under bruk av tastelås"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Forhindre bruk av noen eller alle modulene under bruk av tastelåsen."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Hjemmenummer"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Vil du sende SMS til kortkoden?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Vil du sende premium-SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vil sende en tekstmelding til &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, som ser ut til å være en SMS-kortkode.&lt;p&gt;Hvis du sender en melding til denne destinasjonen, kan mobilkontoen din komme til å belastes for premium-tjenester.&lt;p&gt;Vil du la denne meldingen sendes av appen?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vil sende en tekstmelding til &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, som er en premium SMS-kortkode.&lt;p&gt;&lt;b&gt;Hvis du sender en melding til denne destinasjonen, belastes mobilkontoen din for premium-tjenester.&lt;/b&gt;&lt;p&gt;Vil du la denne meldingen sendes av appen?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Send melding"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Ikke send"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Rapportér skadelig app"</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 +1112,9 @@
     <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_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="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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"PUK-kode"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Ny 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="5216603185442368307">"Skriv inn en PUK-kode på åtte sifre eller mer."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Skriv inn PUK-koden og en ny PIN-kode"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"PUK-koden du har skrevet inn er ikke riktig."</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="8849589033659332457">"Kontrollerer …"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..916c018 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Netwerken op korte afstand"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Toegang tot apparaten via netwerken op korte afstand zoals NFC."</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Widgets uitschakelen bij toetsblokkering"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Gebruik van sommige of alle widgets uitschakelen bij toetsblokkering."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Thuis"</item>
     <item msgid="869923650527136615">"Mobiel"</item>
@@ -820,7 +882,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 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Sms verzenden naar shortcode?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Premium-sms verzenden?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; wil een sms-bericht verzenden naar &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;. Dit is waarschijnlijk een sms-shortcode.&lt;p&gt;Als u sms-berichten naar bepaalde shortcodes verzendt, worden mogelijk kosten voor premiumservices in rekening gebracht op uw mobiele account.&lt;p&gt;Wilt u toestaan dat deze app het bericht verzendt?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; wil een sms-bericht verzenden naar &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;. Dit is premium sms-shortcode.&lt;p&gt;&lt;b&gt;Als u een bericht naar deze bestemming verzendt, kosten voor premiumservices in rekening gebracht op uw mobiele account.&lt;/b&gt;&lt;p&gt;Wilt u toestaan dat deze app het bericht verzendt?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Bericht verzenden"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Niet verzenden"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Kwaadaardige app melden"</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 +1112,9 @@
     <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_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="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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"PUK-code"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Nieuwe pincode"</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="5216603185442368307">"Typ een PUK-code die 8 cijfers of langer is."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Geef de PUK-code en de nieuwe pincode op"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"De PUK-code die u heeft ingevoerd, is onjuist."</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="8849589033659332457">"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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..8793e0c 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Sieci krótkiego zasięgu"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Dostęp do urządzeń przez sieci krótkiego zasięgu, takie jak NFC."</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Wył. widżety przy blokadzie klawiszy"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Uniemożliwiaj użycie części lub wszystkich widżetów przy blokadzie klawiszy."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Dom"</item>
     <item msgid="869923650527136615">"Komórka"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Wysłać droższego SMS-a?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Wysłać droższego SMS-a?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; chce wysłać SMS-a pod numer &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, który wygląda na dodatkowo płatny.&lt;p&gt;Może to spowodować doliczenie do Twojego rachunku za komórkę opłaty za usługę dodatkową.&lt;p&gt;Chcesz pozwolić tej aplikacji na wysłanie SMS-a?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; chce wysłać SMS-a pod numer &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, który jest dodatkowo płatny.&lt;p&gt;&lt;b&gt;To spowoduje doliczenie do Twojego rachunku za komórkę opłaty za usługę dodatkową.&lt;/b&gt;&lt;p&gt;Chcesz pozwolić tej aplikacji na wysłanie SMS-a?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Wyślij wiadomość"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Nie wysyłaj"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Zgłoś złośliwą aplikację"</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 +1112,9 @@
     <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_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="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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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 swój 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="5183097160254244459">"PUK"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Nowy 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="5216603185442368307">"Wpisz PUK składający się z co najmniej 8 cyfr."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Wpisz PUK i nowy PIN"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"Podany PUK jest nieprawidłowy."</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="8849589033659332457">"Sprawdzam…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</string>
 </resources>
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..bb4e265 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 um relatório de erros"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Isto irá recolher informações sobre o estado atual do seu dispositivo para enviar através de uma mensagem de email. Demorará um pouco desde o início do relatório de erro até que este se encontre 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Redes de Curto Alcance"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Aceder a dispositivos através de redes de curto alcance tal como a NFC."</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 +222,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 +257,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 +289,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_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>
+    <!-- no translation found for permlab_magnify_display (5973626738170618775) -->
+    <skip />
+    <!-- no translation found for permdesc_magnify_display (7121235684515003792) -->
+    <skip />
     <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>
@@ -273,6 +327,10 @@
     <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>
+    <!-- no translation found for permlab_freezeScreen (4708181184441880175) -->
+    <skip />
+    <!-- no translation found for permdesc_freezeScreen (8558923789222670064) -->
+    <skip />
     <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>
@@ -385,6 +443,14 @@
     <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>
+    <!-- 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">"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>
@@ -534,6 +600,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 +625,17 @@
     <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>
+    <!-- no translation found for policylab_disableKeyguardWidgets (1794894613389073926) -->
+    <skip />
+    <!-- no translation found for policydesc_disableKeyguardWidgets (7254624892984033592) -->
+    <skip />
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Residência"</item>
     <item msgid="869923650527136615">"Móvel"</item>
@@ -930,8 +1002,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>
@@ -1033,6 +1105,13 @@
     <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_title" msgid="1666863092640877318">"Enviar SMS ao código pequeno?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Enviar SMS premium?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pretende enviar um SMS para &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, que parece ser um código SMS pequeno.&lt;p&gt;Enviar esta mensagem a alguns códigos pequenos pode fazer com que sejam faturados serviços premium na sua conta de telemóvel.&lt;p&gt;Pretende autorizar que a aplicação envie a mensagem?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pretende enviar um SMS a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, que é um pequeno código de SMS premium.&lt;p&gt;&lt;b&gt;Enviar uma mensagem para este destino irá fazer com que sejam faturados serviços premium na sua conta de telemóvel.&lt;/b&gt;&lt;p&gt;Pretende autorizar que a aplicação envie a mensagem?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Enviar mensagem"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Não enviar"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Comunicar aplicação maliciosa"</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 +1122,9 @@
     <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_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="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>
@@ -1114,7 +1190,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 +1223,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>
@@ -1290,4 +1370,45 @@
     <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="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="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="5183097160254244459">"Código PUK"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Novo código PIN"</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="5216603185442368307">"Introduza um PUK que tenha 8 ou mais algarismos."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Introduzir PUK e o novo código PIN"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"O PUK que introduziu não está correto."</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="8849589033659332457">"A verificar…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..3aaa3a2 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Redes de curto alcance"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Acessar dispositivos por meio de redes de curto alcance de redes como a NFC."</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 +222,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 +257,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 +289,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_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>
+    <!-- no translation found for permlab_magnify_display (5973626738170618775) -->
+    <skip />
+    <!-- no translation found for permdesc_magnify_display (7121235684515003792) -->
+    <skip />
     <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>
@@ -273,6 +327,10 @@
     <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>
+    <!-- no translation found for permlab_freezeScreen (4708181184441880175) -->
+    <skip />
+    <!-- no translation found for permdesc_freezeScreen (8558923789222670064) -->
+    <skip />
     <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>
@@ -385,6 +443,14 @@
     <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>
+    <!-- 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">"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>
@@ -534,6 +600,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 +632,10 @@
     <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>
+    <!-- no translation found for policylab_disableKeyguardWidgets (1794894613389073926) -->
+    <skip />
+    <!-- no translation found for policydesc_disableKeyguardWidgets (7254624892984033592) -->
+    <skip />
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Residencial"</item>
     <item msgid="869923650527136615">"Celular"</item>
@@ -695,8 +767,8 @@
     <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>
@@ -930,8 +1002,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>
@@ -1033,6 +1105,13 @@
     <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_title" msgid="1666863092640877318">"Enviar SMS para código curto?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Enviar SMS premium?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; deseja enviar uma mensagem de texto para &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, que parece ser um código curto SMS.&lt;p&gt;O envio de mensagens de texto a alguns códigos curtos pode fazer com que a conta seja cobrada por serviços premium.&lt;p&gt;Deseja permitir que este aplicativo envie a mensagem?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; deseja enviar uma mensagem de texto para &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, que é um código curto SMS premium.&lt;p&gt;&lt;b&gt;O envio de uma mensagem a esse destino fará com que a conta seja cobrada por serviços premium.&lt;/b&gt;&lt;p&gt;Deseja permitir que este aplicativo envie a mensagem?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Enviar mensagem"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Não enviar"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Denunciar aplicativo malicioso"</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 +1122,9 @@
     <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_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="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 +1223,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>
@@ -1290,4 +1370,45 @@
     <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="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="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="5183097160254244459">"Código PUK"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Novo código PIN"</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="5216603185442368307">"Digite um PUK com oito números ou mais."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Insira o PUK e o novo código PIN"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"O PUK digitado está incorreto."</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="8849589033659332457">"Verificando..."</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..50583f3 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,86 @@
     <!-- 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_shortrangeNetwork (130808676377486118) -->
+    <skip />
+    <!-- no translation found for permgroupdesc_shortrangeNetwork (1884069062653436007) -->
+    <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 +306,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 +370,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 +432,18 @@
     <skip />
     <!-- no translation found for permdesc_retrieve_window_content (3193269069469700265) -->
     <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>
@@ -388,6 +493,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 />
@@ -597,6 +706,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 />
@@ -865,6 +982,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 +1042,10 @@
     <skip />
     <!-- no translation found for policydesc_disableCamera (2306349042834754597) -->
     <skip />
+    <!-- no translation found for policylab_disableKeyguardWidgets (1794894613389073926) -->
+    <skip />
+    <!-- no translation found for policydesc_disableKeyguardWidgets (7254624892984033592) -->
+    <skip />
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Privat"</item>
     <item msgid="869923650527136615">"Telefonin"</item>
@@ -1414,9 +1539,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>
@@ -1576,6 +1701,20 @@
     <skip />
     <!-- no translation found for sms_control_no (625438561395534982) -->
     <skip />
+    <!-- no translation found for sms_short_code_confirm_title (1666863092640877318) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_title (3811263856304367838) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_message (5616409294907295407) -->
+    <skip />
+    <!-- no translation found for sms_premium_short_code_confirm_message (6214083016284738667) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_allow (8957573662645722940) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_deny (6374609298084435887) -->
+    <skip />
+    <!-- no translation found for sms_short_code_confirm_report (2588793956061677070) -->
+    <skip />
     <!-- no translation found for sim_removed_title (6227712319223226185) -->
     <skip />
     <!-- no translation found for sim_removed_message (2333164559970958645) -->
@@ -1595,14 +1734,11 @@
     <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 usb_storage_activity_title (4465055157209648641) -->
     <skip />
     <string name="usb_storage_title" msgid="5901459041398751495">"Connectà cun agid d\'in cabel USB"</string>
@@ -1759,6 +1895,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>
@@ -2028,4 +2172,86 @@
     <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 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 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 (5183097160254244459) -->
+    <skip />
+    <!-- no translation found for kg_puk_enter_pin_hint (597821135578014901) -->
+    <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 (5216603185442368307) -->
+    <skip />
+    <!-- no translation found for kg_sim_puk_recovery_hint (5577753137718442566) -->
+    <skip />
+    <!-- no translation found for kg_invalid_puk (5809955359950817326) -->
+    <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 (8849589033659332457) -->
+    <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_temp_back_string (5812983904056640466) -->
+    <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..4f7558a 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Reţele cu distanţă scurtă"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Accesează dispozitive prin intermediul reţelelor cu distanţă scurtă, cum ar fi NFC."</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 +222,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 +257,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 +289,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_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>
+    <!-- no translation found for permlab_magnify_display (5973626738170618775) -->
+    <skip />
+    <!-- no translation found for permdesc_magnify_display (7121235684515003792) -->
+    <skip />
     <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>
@@ -273,6 +327,10 @@
     <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>
+    <!-- no translation found for permlab_freezeScreen (4708181184441880175) -->
+    <skip />
+    <!-- no translation found for permdesc_freezeScreen (8558923789222670064) -->
+    <skip />
     <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>
@@ -385,6 +443,14 @@
     <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>
+    <!-- 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">"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>
@@ -534,6 +600,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 +632,10 @@
     <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>
+    <!-- no translation found for policylab_disableKeyguardWidgets (1794894613389073926) -->
+    <skip />
+    <!-- no translation found for policydesc_disableKeyguardWidgets (7254624892984033592) -->
+    <skip />
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Domiciliu"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -930,8 +1002,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>
@@ -1033,6 +1105,13 @@
     <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_title" msgid="1666863092640877318">"Trimiteţi SMS la codul scurt?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Trimiteţi SMS premium?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; intenţionează să trimită un mesaj text la &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, care pare a fi un cod scurt SMS.&lt;p&gt;Trimiterea de mesaje text la unele coduri scurte poate determina taxarea contului dvs. mobil pentru servicii premium.&lt;p&gt;Permiteţi acestei aplicaţii să trimită mesajul?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; intenţionează să trimită un mesaj text la &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, care este un cod scurt SMS premium.&lt;p&gt;&lt;b&gt;Trimiterea unui mesaj la această destinaţie va determina taxarea contului dvs. mobil pentru servicii premium.&lt;/b&gt;&lt;p&gt;Permiteţi acestei aplicaţii să trimită mesajul?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Trimiteţi mesajul"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Nu trimiteţi"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Raport. aplic.rău intenţionată"</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 +1122,9 @@
     <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_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="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 +1223,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>
@@ -1290,4 +1370,45 @@
     <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="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="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="5183097160254244459">"Codul PUK"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Noul cod PIN"</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="5216603185442368307">"Introduceţi un cod PUK format din 8 cifre sau mai mult."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Introduceţi codul PUK şi noul cod PIN"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"Codul PUK introdus nu este corect."</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="8849589033659332457">"Se verifică..."</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..d002eae 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Сети малого радиуса действия"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Доступ к устройствам с помощью сетей малого радиуса действия, например NFC."</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Отключить виджеты блокировки"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Запретить использование всех или некоторых виджетов блокировки клавиатуры"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Домашний"</item>
     <item msgid="869923650527136615">"Мобильный"</item>
@@ -695,7 +757,7 @@
     <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>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Отправить SMS?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Отправить SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; собирается отправить SMS-сообщение на короткий номер &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;&lt;p&gt; За отправку сообщений на некоторые короткие номера с вашего счета могут списываться дополнительные средства.&lt;p&gt;Разрешить отправку?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; собирается отправить SMS на короткий номер &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;.&lt;p&gt;&lt;b&gt; Если это произойдет, с вашего счета будут списаны дополнительные средства.&lt;/b&gt;&lt;p&gt;Разрешить отправку?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Отправить сообщение"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Не отправлять"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Сообщить о вредоносном ПО"</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 +1112,9 @@
     <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_description_app" msgid="5139836143293299417">"Источник: <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Не требуется разрешений"</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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"PUK-код"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Новый 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="5216603185442368307">"Введите PUK-код из 8 или более цифр."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Введите PUK-код и новый PIN-код"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"Введен неверный PUK-код."</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="8849589033659332457">"Проверка…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..dac472e 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Siete krátkeho dosahu"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Prístup k zariadeniam prostredníctvom sietí krátkeho dosahu (napr. NFC)."</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 +222,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 +257,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 +289,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_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>
+    <!-- no translation found for permlab_magnify_display (5973626738170618775) -->
+    <skip />
+    <!-- no translation found for permdesc_magnify_display (7121235684515003792) -->
+    <skip />
     <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>
@@ -273,6 +327,10 @@
     <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>
+    <!-- no translation found for permlab_freezeScreen (4708181184441880175) -->
+    <skip />
+    <!-- no translation found for permdesc_freezeScreen (8558923789222670064) -->
+    <skip />
     <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>
@@ -385,6 +443,14 @@
     <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>
+    <!-- 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">"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>
@@ -534,6 +600,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 +632,10 @@
     <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>
+    <!-- no translation found for policylab_disableKeyguardWidgets (1794894613389073926) -->
+    <skip />
+    <!-- no translation found for policydesc_disableKeyguardWidgets (7254624892984033592) -->
+    <skip />
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Domovská stránka"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -930,8 +1002,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>
@@ -1033,6 +1105,13 @@
     <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_title" msgid="1666863092640877318">"Odoslať SMS na skrátené číslo?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Odoslať prémiovú správu SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"Aplikácia &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; chce odoslať textovú správu na číslo &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, ktoré sa zdá byť skráteným číslom SMS.&lt;p&gt;Odoslanie správy na skrátené číslo môže spôsobiť, že na účet vášho mobilného zariadenia budú účtované poplatky za prémiové služby.&lt;p&gt;Chcete aplikácií povoliť túto správu odoslať?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"Aplikácia &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; chce odoslať textovú správu na číslo &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, ktoré je prémiovým skráteným číslom SMS.&lt;p&gt;&lt;b&gt;Odoslanie správy na toto číslo spôsobí, že na účet vášho mobilného zariadenia budú účtované poplatky za prémiové služby.&lt;/b&gt;&lt;p&gt;Chcete aplikácii povoliť túto správu odoslať?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Odoslať správu"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Neodoslať"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Nahlásiť škodlivú aplikáciu"</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 +1122,9 @@
     <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_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="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 +1223,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>
@@ -1290,4 +1370,45 @@
     <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="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="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="5183097160254244459">"Kód PUK"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Nový 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="5216603185442368307">"Zadajte kód PUK, ktorý má 8 alebo viac číslic."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Zadajte kód PUK a nový kód PIN"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"Zadaný kód PUK nie je správny."</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="8849589033659332457">"Prebieha kontrola..."</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..c073243 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Omrežja kratkega dosega"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Dostop do naprav z omrežji kratkega dosega, kot je NFC."</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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 Wi-Fi zaslonov"</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 Wi-Fi zaslonov"</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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Onem. pripom. na varov. tipk."</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Preprečevanje uporabe nekaterih ali vseh pripomočkov na varovalu tipkovnice"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Začetna stran"</item>
     <item msgid="869923650527136615">"Mobilni"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Pošljem SMS na kratko štev.?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Pošljem SMS za plačlj. stor.?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; želi poslati SMS na številko &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, kar je videti kot kratka številka za plačljive storitve SMS.&lt;p&gt;S pošiljanjem sporočil na to številko bo vaš račun za mobilni telefon bremenjen za plačljive storitve.&lt;p&gt;Ali želite aplikaciji dovoliti, da pošlje sporočilo?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; želi poslati SMS na številko &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, kar je kratka številka za plačljive storitve SMS.&lt;p&gt;&lt;b&gt;S pošiljanjem sporočil na to številko bo vaš račun za mobilni telefon bremenjen za plačljive storitve.&lt;/b&gt;&lt;p&gt;Ali želite aplikaciji dovoliti, da pošlje sporočilo?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Pošlji sporočilo"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Ne pošlji"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Prijavi zlonamerno aplikacijo"</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 +1112,9 @@
     <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_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="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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"Koda PUK"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Nova koda 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="5216603185442368307">"Vnesite 8- ali več mestni PUK."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Vnesite kodo PUK in novo kodo PIN"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"Vneseni PUK ni pravilen."</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="8849589033659332457">"Preverjanje ..."</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..e6d14c8 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Мреже кратког домета"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Приступање уређајима преко мрежа кратког домета, као што је NFC."</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Онемогућавање виџета закључане тастатуре."</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Онемогућавање употребе неког или свих виџета на закључаној тастатури."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Кућа"</item>
     <item msgid="869923650527136615">"Мобилни"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Пошаљи SMS на кратак кôд?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Желите да пошаљете премијум SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&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;, која можда представља кратак кôд SMS-а.&lt;p&gt;Слање порука на неке кратке кодове може да се наплаћује као премијум услуга са налога за мобилни уређај.&lt;p&gt;Желите ли да дозволите овој апликацији да пошаље поруку?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&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;, која представља кратак кôд премијум SMS-а.&lt;p&gt;&lt;b&gt;Ако се пошаље порука на ово одредиште, биће вам наплаћена премијум услуга са налога за мобилни уређај.&lt;/b&gt;&lt;p&gt;Желите ли да дозволите овој апликацији да пошаље поруку?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Пошаљи поруку"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Не шаљи"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Пријави злонамерну апликацију"</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 +1112,9 @@
     <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_description_app" msgid="5139836143293299417">"Омогућава <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Није потребна ниједна дозвола"</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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"PUK кôд"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Нови 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="5216603185442368307">"Унесите PUK који се састоји од 8 бројева или више."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Унесите PUK и нови PIN кôд"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"PUK који сте унели није тачан."</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="8849589033659332457">"Проверавање..."</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..16d7dce 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Nätverk för kommunikation på nära håll"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Få åtkomst till enheter via nätverk för kommunikation på nära håll, som NFC."</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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 +453,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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Inaktivera widgets vid knapplås"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Förhindra användning av vissa eller alla widgets vid knapplås."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Hem"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Skicka SMS till kortkod?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Skicka premium-SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vill skicka ett SMS till &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; som verkar vara en kortkod för SMS.&lt;p&gt;När du skickar SMS till kortkoder kan mobilkontot debiteras för premiumtjänster.&lt;p&gt;Vill du tillåta att appen skickar meddelandet?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vill skicka ett SMS till &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; som är en kortkod för SMS.&lt;p&gt;&lt;b&gt;Om du skickar ett meddelande till den här mottagaren kommer ditt mobilkonto att debiteras för premiumtjänster.&lt;/b&gt;&lt;p&gt;Vill du tillåta att appen skickar meddelandet?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Skicka meddelande"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Skicka inte"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Rapportera skadlig app"</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 +1112,9 @@
     <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_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="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 +1213,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>
@@ -1282,7 +1352,7 @@
     <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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"PUK-kod"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Ny 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="5216603185442368307">"Ange en PUK-kod med minst 8 siffror."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Ange PUK-koden och en ny PIN-kod"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"PUK-koden som du angav är felaktig."</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="8849589033659332457">"Kontrollerar …"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..a1ecc65 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Mitandao ya Masafa mafupi"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Fikia vifaa kupitia mitandao ya masafa mafupi kama vile NFC."</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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 +528,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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Lemaza wijeti kwenye kingamsingi"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Zuia matumizi ya baadhi ya au wijeti zote kwenye kibodi."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Nyumbani"</item>
     <item msgid="869923650527136615">"Simu ya mkononi"</item>
@@ -737,7 +799,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>
@@ -901,7 +963,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 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Tuma SMS kwa msimbo mfupi?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Tuma SMS ya ada?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ingependa kutuma ujumbe kwa  &lt;b&gt;i<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, ambayo inaonekana kama msimbo mfupi wa ujumbe mfupi.&lt;p&gt;Kutuma ujumbe mfupi kwa baadhi ya misimbo mifupi kunaweza kusababisha akaunti yako ya simu kulipishwa huduma ya ada.&lt;p&gt;Je, unataka kuruhusu programu hii kutuma ujumbe?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ingetaka kutuma ujumbe wa maandishi kwa &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, ambayo ni msimbo mfupi wa SMS ya ada.&lt;p&gt;&lt;b&gt;Kutuma ujumbe mahali hapa kutasababisha akaunti yako ya simu kulipishwa kwa huduma ya ada.&lt;/b&gt;&lt;p&gt;Je, unataka kuruhusu programu hii kutuma ujumbe?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Tuma ujumbe"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Usitume"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Ripoti programu hasidi"</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 +1112,9 @@
     <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_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="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 +1213,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 +1229,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">
@@ -1193,7 +1263,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"Msimbo wa PUK"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Msimbo mpya wa PIN"</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="5216603185442368307">"Andika PUK iliyo na urefu wa tarakimu 8 au zaidi."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Charaza PUK na msimbo mpya wa PIN"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"PUK uliyoicharaza siyo sahihi."</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="8849589033659332457">"Inakagua..."</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_temp_back_string" msgid="5812983904056640466">"&lt;"</string>
 </resources>
diff --git a/core/res/res/values-sw600dp/config.xml b/core/res/res/values-sw600dp/config.xml
index 1486d9c..afb9485 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">30mm</dimen>
+
 </resources>
 
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index 8937c2a..4e202ac 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>
 
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-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/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 7049c52..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..af41066 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"เครือข่ายระยะใกล้"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"เข้าถึงอุปกรณ์ผ่านเครือข่ายระยะใกล้ เช่น NFC"</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"ปิดใช้งานวิดเจ็ตเมื่อล็อกจอ"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"ป้องกันการใช้วิดเจ็ตบางส่วนหรือทั้งหมดเมื่อล็อกหน้าจอ"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"บ้าน"</item>
     <item msgid="869923650527136615">"มือถือ"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"ส่ง SMS เป็นรหัสสั้นหรือไม่"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"ส่ง SMS พรีเมียมหรือไม่"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&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; ซึ่งเป็น SMS รหัสสั้น&lt;p&gt;การส่งข้อความเป็นรหัสสั้นบางอย่างอาจทำให้มีการเรียกเก็บเงินในบัญชีมือถือของคุณสำหรับบริการพรีเมียม&lt;p&gt;คุณต้องการอนุญาตให้แอปพลิเคชันนี้ส่งข้อความหรือไม่"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&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; ซึ่งเป็น SMS รหัสสั้นแบบพรีเมียม&lt;p&gt;&lt;b&gt;การส่งข้อความไปยังปลายทางนี้จะทำให้มีการเรียกเก็บเงินในบัญชีมือถือของคุณสำหรับบริการพรีเมียม&lt;/b&gt;&lt;p&gt;คุณต้องการอนุญาตให้แอปพลิเคชันนี้ส่งข้อความหรือไม่"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"ส่งข้อความ"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"ไม่ส่ง"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"รายงานแอปที่เป็นอันตราย"</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 +1112,9 @@
     <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_description_app" msgid="5139836143293299417">"โดย <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="no_permissions" msgid="7283357728219338112">"ไม่ต้องการการอนุญาต"</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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"รหัส PUK"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"รหัส 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="5216603185442368307">"พิมพ์ PUK ซึ่งต้องเป็นตัวเลขอย่างน้อย 8 หลัก"</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"พิมพ์ PUK และรหัส PIN ใหม่"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"PUK ที่คุณพิมพ์ไม่ถูกต้อง"</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="8849589033659332457">"กำลังตรวจสอบ…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..a28b60c 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Mga Network na May Maikling Saklaw"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"I-access ang mga device sa pamamagitan ng mga network na may maikling saklaw gaya ng NFC."</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"I-disable widget sa keyguard"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Pigilan ang paggamit ng ilan sa o lahat ng widget sa keyguard."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Home"</item>
     <item msgid="869923650527136615">"Mobile"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Magpadala SMS sa short code?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Ipadala ang premium na SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"Ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ay gustong magpadala ng text message sa &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, na lumilitaw na isang SMS na short code.&lt;p&gt;Ang pagpapadala ng mga text message sa ilang short code ay maaaring magdulot ng pagsingil sa iyong mobile account para sa mga premium na serbisyo.&lt;p&gt;Gusto mo bang payagan ang app na ito na ipadala ang mensahe?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"Ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ay gustong magpadala ng text message sa &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, na isang premium na SMS na short code.&lt;p&gt;&lt;b&gt;Ang pagpapadala ng mensahe sa patutunguhang ito ay magdudulot ng pagsingil sa iyong mobile account para sa mga premium na serbisyo.&lt;/b&gt;&lt;p&gt;Gusto mo bang payagan ang app na ito na ipadala ang mensahe?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Ipadala ang mensahe"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Huwag ipadala"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Mag-ulat ng nakakapahamak na app"</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 +1112,9 @@
     <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_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="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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"PUK code"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Bagong 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="5216603185442368307">"Mag-type ng PUK na may 8 numbero o mas mahaba."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"I-type ang PUK at bagong PIN code"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"Hindi tama ang na-type mong PUK."</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="8849589033659332457">"Sinusuri…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..bed7243 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Kısa Mesafeli Ağlar"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Cihazlara NFC gibi kısa mesafeli ağları kullanarak 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 +222,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 +257,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 +289,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_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>
+    <!-- no translation found for permlab_magnify_display (5973626738170618775) -->
+    <skip />
+    <!-- no translation found for permdesc_magnify_display (7121235684515003792) -->
+    <skip />
     <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>
@@ -273,6 +327,10 @@
     <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>
+    <!-- no translation found for permlab_freezeScreen (4708181184441880175) -->
+    <skip />
+    <!-- no translation found for permdesc_freezeScreen (8558923789222670064) -->
+    <skip />
     <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>
@@ -385,6 +443,14 @@
     <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>
+    <!-- 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">"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>
@@ -534,6 +600,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 +632,10 @@
     <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>
+    <!-- no translation found for policylab_disableKeyguardWidgets (1794894613389073926) -->
+    <skip />
+    <!-- no translation found for policydesc_disableKeyguardWidgets (7254624892984033592) -->
+    <skip />
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Ev"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -930,8 +1002,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>
@@ -1033,6 +1105,13 @@
     <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_title" msgid="1666863092640877318">"Kısa koda SMS gönderilsin mi?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Premium SMS gönderilsin mi?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;, SMS kısa koduna sahip olduğu anlaşılan &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; hedefine bir kısa mesaj göndermek istiyor.&lt;p&gt;Bazı kısa kodlara kısa mesaj göndermek mobil hesabınızın premium hizmetle faturalandırılmasına neden olabilir.&lt;/b&gt;&lt;p&gt;Bu uygulamanın mesaj göndermesine izin vermek istiyor musunuz?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; premium SMS kısa koduna sahip &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; hedefine kısa mesaj göndermek istiyor.&lt;p&gt;&lt;b&gt;Bu hedefe mesaj göndermek mobil hesabınızın premium hizmetle faturalandırılmasına neden olur.&lt;/b&gt;&lt;p&gt;Bu uygulamanın mesaj göndermesine izin vermek istiyor musunuz?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Mesajı gönder"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Gönderme"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Kötü amaçlı uygulamayı bildir"</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 +1122,9 @@
     <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_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="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 +1223,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>
@@ -1290,4 +1370,45 @@
     <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="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="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="5183097160254244459">"PUK kodu"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Yeni PIN kodu"</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="5216603185442368307">"8 veya daha uzun basamaklı bir PUK kodu yazın."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"PUK ve yeni PIN kodunu yazın"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"Yazdığınız PUK doğru değil."</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="8849589033659332457">"Kontrol ediliyor…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..229027a 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Мережі короткого діапазону"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Отримувати доступ до пристроїв через мережі короткого діапазону, як-от NFC."</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Блок. клавіш: вимикати віджети"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Вимикати деякі чи всі віджети під час блокування клавіш."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Дом."</item>
     <item msgid="869923650527136615">"Мобільний"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Надіслати SMS на короткий код?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Надіслати спеціальне SMS?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"Програма &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;, яка є коротким кодом SMS.&lt;p&gt;&lt;b&gt;Якщо надсилати текстові повідомлення на певні короткі коди, з вашого мобільного рахунку буде стягнено плату за спеціальні послуги.&lt;/b&gt;&lt;p&gt;Дозволити цій програмі надіслати повідомлення?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"Програма &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;, яка є коротким кодом спеціальних SMS.&lt;p&gt;&lt;b&gt;Якщо надіслати повідомлення на цю адресу, з вашого мобільного рахунку буде стягнено плату за спеціальні послуги.&lt;/b&gt;&lt;p&gt;Дозволити цій програмі надіслати повідомлення?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Надіслати повідомлення"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Не надсилати"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Повідом. про шкідливу програму"</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 +1112,9 @@
     <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_description_app" msgid="5139836143293299417">"Надано <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Дозвіл не потрібний"</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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"PUK-код"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Новий 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="5216603185442368307">"Введіть PUK-код із 8 або більше цифр."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Введіть PUK-код і новий PIN-код"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"Введений PUK-код не правильний."</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="8849589033659332457">"Перевірка…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..6b171b2 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Mạng phạm vi ngắn"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Truy cập vào các thiết bị thông qua mạng phạm vi ngắn như NFC."</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 +222,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 +257,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 +289,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_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>
+    <!-- no translation found for permlab_magnify_display (5973626738170618775) -->
+    <skip />
+    <!-- no translation found for permdesc_magnify_display (7121235684515003792) -->
+    <skip />
     <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>
@@ -273,6 +327,10 @@
     <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>
+    <!-- no translation found for permlab_freezeScreen (4708181184441880175) -->
+    <skip />
+    <!-- no translation found for permdesc_freezeScreen (8558923789222670064) -->
+    <skip />
     <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>
@@ -385,6 +443,14 @@
     <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>
+    <!-- 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">"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>
@@ -534,6 +600,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 +632,10 @@
     <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>
+    <!-- no translation found for policylab_disableKeyguardWidgets (1794894613389073926) -->
+    <skip />
+    <!-- no translation found for policydesc_disableKeyguardWidgets (7254624892984033592) -->
+    <skip />
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Nhà riêng"</item>
     <item msgid="869923650527136615">"ĐT di động"</item>
@@ -930,8 +1002,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>
@@ -1033,6 +1105,13 @@
     <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_title" msgid="1666863092640877318">"Gửi SMS cho mã ngắn?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Gửi tin nhắn SMS trả phí?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; muốn gửi tin nhắn văn bản cho &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, dường như là một mã ngắn SMS.&lt;p&gt;Việc gửi tin nhắn văn bản cho một số mã ngắn có thể khiến cho tài khoản di động của bạn bị lập hóa đơn cho dịch vụ trả phí.&lt;p&gt;Bạn có muốn cho phép ứng dụng này gửi tin nhắn không?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; muốn gửi tin nhắn văn bản cho &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, là một mã ngắn SMS trả phí.&lt;p&gt;&lt;b&gt;Gửi tin nhắn tới địa chỉ này sẽ khiến cho tài khoản di động của bạn bị lập hóa đơn cho dịch vụ trả phí.&lt;/b&gt;&lt;p&gt;Bạn có muốn cho phép ứng dụng này gửi tin nhắn không?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Gửi tin nhắn"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Không gửi"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Báo cáo ứng dụng độc hại"</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 +1122,9 @@
     <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_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="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 +1223,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>
@@ -1290,4 +1370,45 @@
     <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="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="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="5183097160254244459">"Mã PUK"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Mã PIN mới"</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="5216603185442368307">"Nhập PUK có từ 8 số trở lên."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Nhập PUK và mã PIN mới"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"PUK bạn đã nhập không đúng."</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="8849589033659332457">"Đang kiểm tra…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</string>
 </resources>
diff --git a/core/res/res/values-w720dp/bools.xml b/core/res/res/values-w720dp/bools.xml
index c87f689..cd595ad 100644
--- a/core/res/res/values-w720dp/bools.xml
+++ b/core/res/res/values-w720dp/bools.xml
@@ -16,5 +16,5 @@
 
 <resources>
     <bool name="action_bar_expanded_action_views_exclusive">false</bool>
-    <bool name="show_ongoing_ime_switcher">false</bool>
+    <bool name="show_ongoing_ime_switcher">true</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..fe5be5d 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"近距离网络"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"通过 NFC 等近距离网络访问设备。"</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 +222,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 +257,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 +289,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_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>
+    <!-- no translation found for permlab_magnify_display (5973626738170618775) -->
+    <skip />
+    <!-- no translation found for permdesc_magnify_display (7121235684515003792) -->
+    <skip />
     <string name="permlab_shutdown" msgid="7185747824038909016">"部分关机"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"使活动管理器进入关闭状态。不执行彻底关机。"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"禁止切换应用"</string>
@@ -273,6 +327,10 @@
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"允许该应用随时更改全局动画速度(加快或减慢)。"</string>
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"管理应用令牌"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"允许应用绕过其正常的 Z 排序创建和管理自己的令牌。普通应用绝不需要此权限。"</string>
+    <!-- no translation found for permlab_freezeScreen (4708181184441880175) -->
+    <skip />
+    <!-- no translation found for permdesc_freezeScreen (8558923789222670064) -->
+    <skip />
     <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>
@@ -385,6 +443,14 @@
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"允许应用使用 SurfaceFlinger 低级功能。"</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"读取帧缓冲区"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"允许应用读取帧缓冲区的内容。"</string>
+    <!-- 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">"更改您的音频设置"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"允许该应用修改全局音频设置,例如音量和用于输出的扬声器。"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"录音"</string>
@@ -534,6 +600,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 +632,10 @@
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"要求对存储的应用数据进行加密。"</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"停用相机"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"禁止使用所有设备摄像头。"</string>
+    <!-- no translation found for policylab_disableKeyguardWidgets (1794894613389073926) -->
+    <skip />
+    <!-- no translation found for policydesc_disableKeyguardWidgets (7254624892984033592) -->
+    <skip />
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"住宅"</item>
     <item msgid="869923650527136615">"手机"</item>
@@ -930,8 +1002,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>
@@ -1033,6 +1105,13 @@
     <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_title" msgid="1666863092640877318">"是否向短码发送短信?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"是否发送付费短信?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&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;(这似乎是一个短信短码)发送短信。&lt;p&gt;向某些短码发送短信可能会导致您的移动帐户因使用付费服务而扣费。&lt;p&gt;是否允许该应用发送短信?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&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;(这是一个付费短信短码)发送短信。&lt;p&gt;&lt;b&gt;向该地址发送短信会导致您的移动帐户因使用付费服务而扣费&lt;/b&gt;。&lt;p&gt;是否允许该应用发送短信?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"发送短信"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"不发送"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"举报恶意应用"</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 +1122,17 @@
     <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_description_app" msgid="5139836143293299417">"由“<xliff:g id="APP_NAME">%1$s</xliff:g>”提供。"</string>
+    <string name="no_permissions" msgid="7283357728219338112">"不需要任何权限"</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>
@@ -1147,6 +1223,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>
@@ -1290,4 +1370,45 @@
     <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="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="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="5183097160254244459">"PUK 码"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"新的 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="5216603185442368307">"请输入至少 8 位数的 PUK。"</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"请输入 PUK 和新的 PIN 码"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"您输入的 PUK 不正确。"</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="8849589033659332457">"正在检查..."</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..3eaecfa 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"短距離網路"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"透過短距離網路 (例如 NFC) 存取裝置。"</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 +222,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 +257,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 +289,12 @@
     <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_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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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 Display"</string>
+    <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"允許應用程式設定及連接 WiFi Display。"</string>
+    <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"控制 WiFi Display"</string>
+    <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"允許應用程式控制 WiFi Display 的低階功能。"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"變更音訊設定"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"允許應用程式修改全域音訊設定,例如音量和用來輸出的喇叭。"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"錄製音訊"</string>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"停用鍵盤保護框上的小工具"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"禁止使用鍵盤保護框上的部分或所有小工具。"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"住家電話"</item>
     <item msgid="869923650527136615">"行動電話"</item>
@@ -719,7 +781,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 +801,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>
@@ -930,8 +992,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 +1003,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 +1032,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"傳送簡訊給短碼?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"傳送付費簡訊?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"&lt;b&gt;&lt;/b&gt;「<xliff:g id="APP_NAME">%1$s</xliff:g>」想要傳送簡訊給簡訊短碼 &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;。&lt;p&gt;將簡訊傳送給對方之後,系統即會從您的行動帳戶收取付費服務的費用。&lt;p&gt;您要允許這個應用程式傳送簡訊嗎?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"&lt;b&gt;&lt;/b&gt;「<xliff:g id="APP_NAME">%1$s</xliff:g>」想要傳送簡訊給付費簡訊短碼 &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;。&lt;p&gt;&lt;b&gt;將簡訊傳送給對方之後,系統即會從您的行動帳戶收取付費服務的費用。&lt;/b&gt;&lt;p&gt;您要允許這個應用程式傳送簡訊嗎?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"傳送簡訊"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"不要傳送"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"檢舉惡意應用程式"</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 +1112,9 @@
     <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_description_app" msgid="5139836143293299417">"由「<xliff:g id="APP_NAME">%1$s</xliff:g>」提供。"</string>
+    <string name="no_permissions" msgid="7283357728219338112">"無須許可"</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 +1213,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 +1239,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>
@@ -1277,7 +1347,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"PUK 碼"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"新 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="5216603185442368307">"請輸入 8 碼以上的 PUK。"</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"輸入 PUK 碼和新 PIN 碼"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"您輸入的 PUK 不正確。"</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="8849589033659332457">"檢查中…"</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_temp_back_string" msgid="5812983904056640466">"&lt;"</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..6cca404 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,47 @@
     <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_shortrangeNetwork" msgid="130808676377486118">"Amanethiwekhi ebanga elifushane"</string>
+    <string name="permgroupdesc_shortrangeNetwork" msgid="1884069062653436007">"Finyelela amadivayisi ngamanethiwekhi ebanga elifushane njenge-NFC."</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 +222,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 +257,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 +289,12 @@
     <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_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,7 +306,7 @@
     <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>
@@ -273,6 +325,8 @@
     <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>
@@ -385,6 +439,10 @@
     <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 +486,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 +539,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>
@@ -534,6 +592,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 +624,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_disableKeyguardWidgets" msgid="1794894613389073926">"Khubaza izinqunjwana kukhiye wokuqapha"</string>
+    <string name="policydesc_disableKeyguardWidgets" msgid="7254624892984033592">"Vikela ukusebenza kwesinqunjwana noma kokhe kukhiye wokuqapha."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Ekhaya"</item>
     <item msgid="869923650527136615">"Iselula"</item>
@@ -930,8 +992,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>
@@ -1033,6 +1095,13 @@
     <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_title" msgid="1666863092640877318">"Thumela i-SMS kukhodi emfushane?"</string>
+    <string name="sms_premium_short_code_confirm_title" msgid="3811263856304367838">"Ukuthumela i-SMS ye-premium?"</string>
+    <string name="sms_short_code_confirm_message" msgid="5616409294907295407">"I-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ithanda ukuthumela umlayezo wombhalo ku-&lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, okubonakala sengathi ikhodi ye-SMS emfushane.&lt;p&gt;Ukuthumela umlayezo wombhalo kungabangela i-akhawunti yeselula yakho ukuthi ikhokheliswe amasevisi e-premium.&lt;p&gt;Ufuna ukuvumela uhlelo lokusebenza ukuthumela umlayezo?"</string>
+    <string name="sms_premium_short_code_confirm_message" msgid="6214083016284738667">"I-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ithanda ukuthumela umlayezo wombhalo ku-&lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;, okuyikhodi emfushane ye-SMS ye-premium.&lt;p&gt;&lt;b&gt;Ukuthumela umlayezo kule ndawo kuzobangela i-akhawunti yeselula yakho ukuthi ikhokheliswe amasevisi e-premium.&lt;/b&gt;&lt;p&gt;Ufuna ukuvumela lolu hlelo lokusebenza ukuthumela umlayezo?"</string>
+    <string name="sms_short_code_confirm_allow" msgid="8957573662645722940">"Thumela umlayezo"</string>
+    <string name="sms_short_code_confirm_deny" msgid="6374609298084435887">"Ungathumeli"</string>
+    <string name="sms_short_code_confirm_report" msgid="2588793956061677070">"Bika uhlelo lokusebenza olungalungile"</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 +1112,9 @@
     <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_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="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 +1213,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>
@@ -1290,4 +1360,45 @@
     <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="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="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="5183097160254244459">"Ikhodi le-PUK"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="597821135578014901">"Iphinikhodi entsha"</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="5216603185442368307">"Thayipha i-PUK enezinombolo ezingu-8 noma ngaphezulu."</string>
+    <string name="kg_sim_puk_recovery_hint" msgid="5577753137718442566">"Faka i-PUK nephinikhodi entsha"</string>
+    <string name="kg_invalid_puk" msgid="5809955359950817326">"I-PUK oyithayiphile ayilungile."</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="8849589033659332457">"Iyahlola..."</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_temp_back_string" msgid="5812983904056640466">"&lt;"</string>
 </resources>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index b425ad7..8615476 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,4 @@
         <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>
-
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index aa8b643..0755038 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 -->
         <!-- ============= -->
@@ -763,11 +768,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" />
 
@@ -2154,39 +2163,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 +2380,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
@@ -3668,6 +3655,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 +4085,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 +5186,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 +5198,26 @@
              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>
+        <!-- Optional parameter which indicates any feature(s) that this widget
+             supports. Supports combined values using | operator. -->
+        <attr name="widgetFeatures" format="integer">
+            <flag name="none" value="0x0" />
+            <flag name="clock" value="0x1" />
+            <flag name="status" value="0x2" />
+        </attr>
     </declare-styleable>
 
     <!-- =============================== -->
@@ -5513,6 +5538,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 +5742,22 @@
         <attr name="minHeight" />
     </declare-styleable>
 
+    <!-- PagedView specific attributes. These attributes are used to customize
+         a PagedView view in XML files. -->
+    <declare-styleable name="PagedView">
+        <!-- A spacing override for the icons within a page -->
+        <attr name="pageLayoutWidthGap" format="dimension" />
+        <attr name="pageLayoutHeightGap" format="dimension" />
+        <!-- The padding of the pages that are dynamically created per page -->
+        <attr name="pageLayoutPaddingTop" format="dimension" />
+        <attr name="pageLayoutPaddingBottom" format="dimension" />
+        <attr name="pageLayoutPaddingLeft" format="dimension" />
+        <attr name="pageLayoutPaddingRight" format="dimension" />
+        <!-- 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>
+
 </resources>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index f971d39..7209e4e 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,
@@ -627,6 +648,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" />
@@ -880,6 +903,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 +927,7 @@
         <attr name="icon" />
         <attr name="logo" />
         <attr name="description" />
+        <attr name="permissionGroupFlags" />
         <attr name="priority" />
     </declare-styleable>
     
@@ -1194,6 +1219,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 +1301,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 +1335,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
@@ -1362,6 +1390,7 @@
         <attr name="hardwareAccelerated" />
         <attr name="uiOptions" />
         <attr name="parentActivityName" />
+        <attr name="singleUser" />
     </declare-styleable>
     
     <!-- The <code>activity-alias</code> tag declares a new
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 41f902f..eba354b 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">#ffffb060</color>
+    
     <!-- For search-related UIs -->
     <color name="search_url_text_normal">#7fa87f</color>
     <color name="search_url_text_selected">@android:color/black</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4d54fd2..297e72a 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
@@ -466,6 +474,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 +485,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 +539,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 +589,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 +597,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 +624,30 @@
     <!-- 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(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.
+         Platforms should overlay additional packages in
+         config_overlay_locationProviderPackageNames, instead of overlaying
+         this config, if they only want to append packages and not replace
+         the entire array.
+         -->
+    <string-array name="config_locationProviderPackageNames" translatable="false">
+        <item>com.android.location.fused</item>
+    </string-array>
 
-    <!-- Package name providing geocoder API support. -->
-    <string name="config_geocodeProviderPackageName" translatable="false">@null</string>
+    <!-- Pacakge name(s) supplied by overlay, and appended to
+         config_locationProviderPackageNames. -->
+    <string-array name="config_overlay_locationProviderPackageNames" translatable="false" />
 
     <!-- Boolean indicating if current platform supports bluetooth SCO for off call
     use cases -->
@@ -847,9 +903,7 @@
     <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>
+    <bool name="config_enableDreams">true</bool>
 
     <!-- Base "touch slop" value used by ViewConfiguration as a
          movement threshold where scrolling should begin. -->
@@ -871,4 +925,25 @@
 
     <!-- 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">25mm</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>
+
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index f30943a..3be3b0b 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,20 @@
     <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 -->
+    <!-- Width of security view in keyguard. -->
+    <dimen name="kg_security_view_width">500dp</dimen>
+
+    <!-- Height of security view in keyguard. -->
+    <dimen name="kg_security_view_height">0dp</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>
+
+    <!-- Padding surrounding each widget page -->
+    <dimen name="kg_widget_page_padding">10dp</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..7834997
--- /dev/null
+++ b/core/res/res/values/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_security_flip_duration">150</integer>
+    <integer name="kg_security_fade_duration">150</integer>
+</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 6334f88..f28fab1 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,7 +1977,6 @@
      =============================================================== -->
   <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" />
@@ -3661,4 +1989,34 @@
   <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" />
+  <public type="attr" name="textDirection" />
+  <public type="attr" name="textAlignment" />
+  <public type="attr" name="layoutDirection" />
+  <public type="attr" name="paddingStart"/>
+  <public type="attr" name="paddingEnd"/>
+  <public type="attr" name="layout_marginStart"/>
+  <public type="attr" name="layout_marginEnd"/>
+  <public type="attr" name="layout_toStartOf" />
+  <public type="attr" name="layout_toEndOf" />
+  <public type="attr" name="layout_alignStart" />
+  <public type="attr" name="layout_alignEnd" />
+  <public type="attr" name="layout_alignParentStart" />
+  <public type="attr" name="layout_alignParentEnd" />
+  <public type="attr" name="listPreferredItemPaddingStart" />
+  <public type="attr" name="listPreferredItemPaddingEnd" />
+  <public type="attr" name="singleUser" />
+  <public type="attr" name="presentationTheme" />
+  <public type="attr" name="subtypeId"/>
+  <public type="attr" name="initialKeyguardLayout" />
+  <public type="attr" name="widgetFeatures" />
+  <public type="attr" name="widgetCategory" />
+  <public type="attr" name="permissionGroupFlags" />
+  <public type="attr" name="labelFor" />
+  <public type="attr" name="permissionFlags" />
+  
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 3582768..b904c60 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,27 @@
         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_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 +822,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 +855,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 +873,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 +1003,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 +1258,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 +1290,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 +1635,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 +1704,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>
@@ -1573,6 +1732,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 +1809,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_disableKeyguardWidgets">Disable widgets on keyguard</string>
+    <!-- Description of policy access to disable all device cameras [CHAR LIMIT=110]-->
+    <string name="policydesc_disableKeyguardWidgets">Prevent use of some or all widgets on 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. -->
@@ -2693,10 +2861,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>
@@ -2924,20 +3092,22 @@
     <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 may cause charges 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">This will cause charges on your mobile account.</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 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 +3134,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>
     <!-- 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 +3391,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>
@@ -3592,4 +3763,136 @@
 
     <!-- "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>
+
+    <!-- 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>
+
+    <!-- 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 unlock screen PUK TextView -->
+    <string name="kg_puk_enter_puk_hint">PUK code</string>
+    <!-- Hint shown in the PUK unlock screen PIN TextView -->
+    <string name="kg_puk_enter_pin_hint">New 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">Type a PUK that is 8 numbers or longer.</string>
+    <!-- Instructions for PUK unlock screen -->
+    <string name="kg_sim_puk_recovery_hint">Type PUK and new PIN code</string>
+    <!-- Message shown when the user enters an invalid PUK code -->
+    <string name="kg_invalid_puk">The PUK you typed isn\'t correct.</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\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>
+
+    <!-- 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>
+
+    <string name="kg_temp_back_string"> &lt; </string> <!-- TODO: remove this -->
+
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index e4fc26b..74e2425 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>
 
@@ -476,7 +473,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 +584,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 +925,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 +980,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 +1037,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 +1079,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 +1088,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 +1125,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 +1163,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 +1182,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 +1259,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 +1392,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 +1537,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 +1568,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>
@@ -1732,8 +1736,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 +1776,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 +1821,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 +1830,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 +1876,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 +1893,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 +1974,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">
@@ -2320,7 +2324,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 +2423,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 +2455,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 +2464,8 @@
         <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>
 
 </resources>
diff --git a/core/res/res/values/styles_device_defaults.xml b/core/res/res/values/styles_device_defaults.xml
index 28fed45..d465356 100644
--- a/core/res/res/values/styles_device_defaults.xml
+++ b/core/res/res/values/styles_device_defaults.xml
@@ -673,7 +673,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..0360224
--- /dev/null
+++ b/core/res/res/values/symbols.xml
@@ -0,0 +1,1713 @@
+<?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="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="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_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="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="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="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="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="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_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_disableKeyguardWidgets" />
+  <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_disableKeyguardWidgets" />
+  <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="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="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="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="string" name="safe_media_volume_warning" />
+
+  <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_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_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="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" />
+
+  <java-symbol type="dimen" name="config_minScalingSpan" />
+
+  <!-- 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="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="dimen" name="kg_widget_page_padding" />
+  <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_overscroll_layer_left" />
+  <java-symbol type="drawable" name="kg_widget_overscroll_layer_right" />
+  <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="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="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_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="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="sim_pin_entry" />
+  <java-symbol type="id" name="delete_button" />
+  <java-symbol type="id" name="sim_puk_entry" />
+  <java-symbol type="id" name="sim_pin_entry" />
+  <java-symbol type="id" name="puk_delete_button" />
+  <java-symbol type="id" name="pin_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_users_grid" />
+  <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="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_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="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="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_sim_puk_recovery_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" />
+
+  <!-- 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="array" name="config_overlay_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="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="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="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..215551b 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>
@@ -637,6 +646,8 @@
 
         <item name="listPreferredItemPaddingLeft">10dip</item>
         <item name="listPreferredItemPaddingRight">10dip</item>
+        <item name="listPreferredItemPaddingStart">10dip</item>
+        <item name="listPreferredItemPaddingEnd">10dip</item>
     </style>
 
     <!-- Variant of {@link Theme_Dialog} that does not include a frame (or background).
@@ -962,6 +973,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 +1019,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>
@@ -1267,6 +1286,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 +1332,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>
@@ -1576,6 +1603,8 @@
 
         <item name="listPreferredItemPaddingLeft">16dip</item>
         <item name="listPreferredItemPaddingRight">16dip</item>
+        <item name="listPreferredItemPaddingStart">16dip</item>
+        <item name="listPreferredItemPaddingEnd">16dip</item>
     </style>
 
     <!-- Variant of Theme.Holo.Dialog that has a nice minimum width for
@@ -1653,6 +1682,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 +1717,8 @@
 
         <item name="listPreferredItemPaddingLeft">16dip</item>
         <item name="listPreferredItemPaddingRight">16dip</item>
+        <item name="listPreferredItemPaddingStart">16dip</item>
+        <item name="listPreferredItemPaddingEnd">16dip</item>
     </style>
 
     <!-- Variant of Theme.Holo.Light.Dialog that has a nice minimum width for
@@ -1748,6 +1783,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..2a2b9e0 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>
@@ -239,9 +244,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>
@@ -460,6 +470,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/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/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
index f01562c..561e33e 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;
@@ -94,7 +95,6 @@
      * Control Wifi States
      */
     public WifiManager mWifiManager;
-    public WifiManager.Channel mChannel;
 
     /*
      * Verify connectivity state
@@ -242,7 +242,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 +501,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());
     }
 
     /**
@@ -599,7 +594,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 +653,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 +697,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/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..fe4dd8e
--- /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_loc">
+
+    <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/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..5881aa1 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,51 @@
         }
     }
 
-    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);
+            observer.waitForCompletion(MAX_WAIT_TIME);
+
+            assertUninstalled(info);
+
+            // Verify we received the broadcast
+            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 +1036,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 +1056,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 +1114,7 @@
 
     class SdUnMountReceiver extends GenericReceiver {
         String pkgNames[];
+
         boolean status = true;
 
         SdUnMountReceiver(String[] pkgNames) {
@@ -1081,14 +1226,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 +1246,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 +1273,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 +1286,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 +1306,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 +1315,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, 0);
+        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 +1354,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, 0);
+                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 +1383,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 +1408,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 +1425,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 +1452,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 +1474,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 +1502,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 +1530,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 +1580,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 +1606,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 +1629,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 +1643,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,7 +1668,8 @@
     private int getDefaultInstallLoc() {
         int origDefaultLoc = PackageInfo.INSTALL_LOCATION_AUTO;
         try {
-            origDefaultLoc = Settings.System.getInt(mContext.getContentResolver(), Settings.Secure.DEFAULT_INSTALL_LOCATION);
+            origDefaultLoc = Settings.System.getInt(mContext.getContentResolver(),
+                    Settings.Secure.DEFAULT_INSTALL_LOCATION);
         } catch (SettingNotFoundException e1) {
         }
         return origDefaultLoc;
@@ -1499,6 +1679,7 @@
         Settings.System.putInt(mContext.getContentResolver(),
                 Settings.Secure.DEFAULT_INSTALL_LOCATION, loc);
     }
+
     /*
      * Tests for moving apps between internal and external storage
      */
@@ -1509,9 +1690,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 +1708,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 +1716,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 +1740,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 +1763,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 +1772,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 +1786,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 +1800,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 +1814,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 +1836,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 +1854,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 +1884,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 +1907,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 +1930,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 +1943,7 @@
      * Install an app forward-locked.
      */
     @LargeTest
-    public void testFlagF() {
+    public void testFlagF() throws Exception {
         sampleInstallFromRawResource(PackageManager.INSTALL_FORWARD_LOCK, true);
     }
 
@@ -1771,7 +1951,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 +1963,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 +1972,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 +1987,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 +1996,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 +2073,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 +2091,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 +2104,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 +2122,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 +2135,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 +2144,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 +2162,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 +2185,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 +2208,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 +2231,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 +2249,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 +2279,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 +2288,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 +2302,7 @@
     }
 
     @LargeTest
-    public void testManifestA() {
+    public void testManifestA() throws Exception {
         installFromRawResource("install.apk", R.raw.install_loc_auto,
                 0,
                 true,
@@ -2137,7 +2318,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 +2336,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 +2359,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 +2382,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 +2405,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 +2423,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 +2445,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 +2505,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 +2525,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 +2537,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 +2548,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.System.getInt(mContext.getContentResolver(), Settings.Secure.SET_INSTALL_LOCATION) != 0;
 
-       } catch (SettingNotFoundException e1) {
-       }
-       return false;
-   }
+        } catch (SettingNotFoundException e1) {
+        }
+        return false;
+    }
 
-   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 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) 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 +2605,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 +2635,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 +2687,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 +2716,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 +2813,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 +2845,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 +2894,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 +2924,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 +2941,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 +2983,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 +2998,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 +3065,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";
@@ -2930,8 +3137,9 @@
             }
         }
     }
+
     @LargeTest
-    public void testInstallNoCertificates() {
+    public void testInstallNoCertificates() throws Exception {
         int apk1 = APP1_UNSIGNED;
         String apk1Name = "install1.apk";
         InstallParams ip1 = null;
@@ -2943,18 +3151,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 +3183,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 +3202,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 +3212,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 +3222,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 +3236,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 +3250,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";
@@ -3052,23 +3278,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 +3306,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 +3318,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 +3330,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 +3342,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 +3354,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 +3377,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 +3412,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 +3450,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 +3483,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..105bcba
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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 ManifestDigest MANIFEST_DIGEST = new ManifestDigest(DIGEST_BYTES);
+
+    public void testParcel() throws Exception {
+        VerificationParams expected = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        Parcel parcel = Parcel.obtain();
+        expected.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+
+        VerificationParams actual = VerificationParams.CREATOR.createFromParcel(parcel);
+
+        assertEquals(VERIFICATION_URI, actual.getVerificationURI());
+
+        assertEquals(ORIGINATING_URI, actual.getOriginatingURI());
+
+        assertEquals(REFERRER, actual.getReferrer());
+
+        assertEquals(MANIFEST_DIGEST, actual.getManifestDigest());
+    }
+
+    public void testEquals_Success() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertEquals(params1, params2);
+    }
+
+    public void testEquals_VerificationUri_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+            REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse("http://a.different.uri/"), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_OriginatingUri_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse("http://a.different.uri/"),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_Referrer_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse("http://a.different.uri/"), new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_ManifestDigest_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest("a different digest".getBytes()));
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_InstallerUid_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(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, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertEquals(params1.hashCode(), params2.hashCode());
+    }
+
+    public void testHashCode_VerificationUri_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(null, Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_OriginatingUri_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse("http://a.different.uri/"),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_Referrer_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING), null,
+                new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_ManifestDigest_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest("a different digest".getBytes()));
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_InstallerUid_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest("a different digest".getBytes()));
+        params2.setInstallerUid(INSTALLER_UID);
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+}
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/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/data/etc/platform.xml b/data/etc/platform.xml
index 833064e..a19b9b4 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -42,6 +42,10 @@
         <group gid="net_bt" />
     </permission>
 
+    <permission name="android.permission.NET_TUNNELING" >
+        <group gid="vpn" />
+    </permission>
+
     <permission name="android.permission.INTERNET" >
         <group gid="inet" />
     </permission>
@@ -169,7 +173,10 @@
     <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.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..7bc172c 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -76,14 +76,6 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT)/fonts
 include $(BUILD_PREBUILT)
 
-include $(CLEAR_VARS)
-LOCAL_MODULE := fallback_fonts-ja.xml
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
-include $(BUILD_PREBUILT)
-
 droidsans_fallback_src := DroidSansFallbackFull.ttf
 extra_font_files := \
 	DroidSans.ttf \
@@ -91,8 +83,7 @@
 	DroidSansEthiopic-Regular.ttf \
 	DroidSansTamil-Regular.ttf \
 	DroidSansTamil-Bold.ttf \
-	MTLmr3m.ttf \
-	fallback_fonts-ja.xml
+	MTLmr3m.ttf
 endif  # SMALLER_FONT_FOOTPRINT
 
 ################################
diff --git a/data/fonts/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/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..2c9a0c8 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,11 +93,6 @@
     </family>
     <family>
         <fileset>
-            <file>Lohit-Telugu.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
             <file>AndroidEmoji.ttf</file>
         </fileset>
     </family>
@@ -106,7 +103,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/vendor_fonts.xml b/data/fonts/vendor_fonts.xml
index 5850f94..8690ee1 100644
--- a/data/fonts/vendor_fonts.xml
+++ b/data/fonts/vendor_fonts.xml
@@ -7,8 +7,7 @@
     that in your makefile, this directory should be referenced as $(TARGET_COPY_OUT_VENDOR)/etc/:
 
         PRODUCT_COPY_FILES += \
-            frameworks/base/data/fonts/vendor_fonts.xml:$(TARGET_COPY_OUT_VENDOR)/etc/fallback_fonts.xml \
-            frameworks/base/data/fonts/vendor_fonts-ja.xml:$(TARGET_COPY_OUT_VENDOR)/etc/fallback_fonts-ja.xml
+            frameworks/base/data/fonts/vendor_fonts.xml:$(TARGET_COPY_OUT_VENDOR)/etc/fallback_fonts.xml
 
     For example, vendors might want to build configurations for locales that are
     better served by fonts which either handle glyphs not supported in the default fonts or which
@@ -32,32 +31,9 @@
 
     Han languages (Chinese, Japanese, and Korean) share a common range of unicode characters;
     their ordering in the fallback or vendor files gives priority to the first in the list.
-    Locale-specific ordering can be configured by adding language and region codes to the end
-    of the filename (e.g. /vendor/etc/fallback_fonts-ja.xml). When no region code is used,
-    as with this example, all regions are matched. Use separate files for each supported locale.
-    The standard fallback file (fallback_fonts.xml) is used when a locale does not have its own
-    file. All fallback files must contain the same complete set of fonts; only their ordering
-    can differ. For example, on a device supporting Japanese, but with English as the default,
-    /vendor/etc/fallback_fonts.xml might contain:
-
-        <familyset>
-            <family>
-                <fileset>
-                    <file>DroidSansJapanese.ttf</file>
-                </fileset>
-            </family>
-        </familyset>
-
-    placing the Japanese font at the end of the fallback sequence for English, with a corresponding
-    /system/vendor/etc/fallback_fonts-ja.xml, placing it at the front of the list.
-
-        <familyset>
-            <family order="0">
-                <fileset>
-                    <file>DroidSansJapanese.ttf</file>
-                </fileset>
-            </family>
-        </familyset>
+    Language-specific ordering can be configured by adding a BCP 47-style "lang" attribute to
+    a "file" element; fonts matching the language of text being drawn will be prioritised over
+    all others.
 
     The sample configuration below is an example of how one might provide two families of fonts
     that get inserted at the first and second (0  and 1) position in the overall fallback fonts.
@@ -82,4 +58,4 @@
         </fileset>
     </family>
 </familyset>
--->
\ No newline at end of file
+--->
diff --git a/docs/html/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 c6f1a4e..c4dfecf 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>
@@ -691,8 +693,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>
@@ -704,7 +708,7 @@
   </tr>
 </table>
 
-<p>If you want to test your request (either JSON or plain text) without delivering the message to the devices, you can set an optional HTTP parameter called <code>dry_run</code> with the value <code>true</code>. The result will be almost identical to running the request without this parameter, except that the message will not be delivered to the devices. Consequently, the response will contain fake IDs for the message and multicast fields (see <a href="#response">Response format</a>).</p>
+
 
   <h4 id="example-requests">Example requests</h4>
   <p>Here is the smallest possible request (a message without any parameters and just one recipient) using JSON:</p>
@@ -897,13 +901,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/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/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..749e458 100644
--- a/docs/html/guide/topics/resources/providing-resources.jd
+++ b/docs/html/guide/topics/resources/providing-resources.jd
@@ -329,6 +329,31 @@
 indicates the current locale.</p>
       </td>
     </tr>
+    <tr id="LayoutDirectionQualifier">
+      <td>Layout Direction</td>
+      <td>Examples:<br/>
+        <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 like layouts or values or drawables.
+      </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>(This is the default layout)
+    layout-ar/  <span style="color:black">
+        main.xml  </span>(This is the specific layout for Arabic)
+    layout-ldrtl/  <span style="color:black">
+        main.xml  </span>(This applies to any "right-to-left" language, except for Arabic, because the ar language qualifier has a higher precedence.)
+</pre>
+      </td>
+    </tr>
     <tr id="SmallestScreenWidthQualifier">
       <td>smallestWidth</td>
       <td><code>sw&lt;N&gt;dp</code><br/><br/>
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..6ba57809 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");
@@ -347,11 +346,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 +385,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 +405,7 @@
             throw new RuntimeException("unsupported Buffer subclass");
         }
 
-        long bufferBytes = (long)elements << shift;
+        long bufferBytes = (long) elements << shift;
         long bitmapBytes = getByteCount();
 
         if (bufferBytes < bitmapBytes) {
@@ -622,6 +625,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 +653,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 +712,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 +751,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 +775,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 +873,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;
@@ -926,7 +1040,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 +1058,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 +1070,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 +1090,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 +1146,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 +1168,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 +1183,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 +1191,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();
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/Paint.java b/graphics/java/android/graphics/Paint.java
index f9b8a5f..f68f9dc 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1055,7 +1055,6 @@
      * Get the text Locale.
      *
      * @return the paint's Locale used for drawing text, never null.
-     * @hide
      */
     public Locale getTextLocale() {
         return mLocale;
@@ -1086,7 +1085,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..7a4a1ca 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -80,6 +80,7 @@
     @Deprecated
     public BitmapDrawable() {
         mBitmapState = new BitmapState((Bitmap) null);
+        mMutated = true;
     }
 
     /**
@@ -90,6 +91,7 @@
     public BitmapDrawable(Resources res) {
         mBitmapState = new BitmapState((Bitmap) null);
         mBitmapState.mTargetDensity = mTargetDensity;
+        mMutated = true;
     }
 
     /**
@@ -100,6 +102,7 @@
     @Deprecated
     public BitmapDrawable(Bitmap bitmap) {
         this(new BitmapState(bitmap), null);
+        mMutated = true;
     }
 
     /**
@@ -109,6 +112,7 @@
     public BitmapDrawable(Resources res, Bitmap bitmap) {
         this(new BitmapState(bitmap), res);
         mBitmapState.mTargetDensity = mTargetDensity;
+        mMutated = true;
     }
 
     /**
@@ -122,6 +126,7 @@
         if (mBitmap == null) {
             android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
         }
+        mMutated = true;
     }
 
     /**
@@ -134,6 +139,7 @@
         if (mBitmap == null) {
             android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
         }
+        mMutated = true;
     }
 
     /**
@@ -147,6 +153,7 @@
         if (mBitmap == null) {
             android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
         }
+        mMutated = true;
     }
 
     /**
@@ -159,6 +166,7 @@
         if (mBitmap == null) {
             android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
         }
+        mMutated = true;
     }
 
     /**
@@ -385,7 +393,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;
@@ -552,6 +560,7 @@
         } else {
             mTargetDensity = state.mTargetDensity;
         }
+        mMutated = false;
         setBitmap(state != null ? state.mBitmap : null);
     }
 }
diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java
index c41dd07..723db6e 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,11 @@
         return null;
     }
 
-    
+    @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..f8e3944 100644
--- a/graphics/java/android/graphics/drawable/ColorDrawable.java
+++ b/graphics/java/android/graphics/drawable/ColorDrawable.java
@@ -36,12 +36,14 @@
 public class ColorDrawable extends Drawable {
     private ColorState mState;
     private final Paint mPaint = new Paint();
+    private boolean mMutated;
 
     /**
      * Creates a new black ColorDrawable.
      */
     public ColorDrawable() {
         this(null);
+        mMutated = true;
     }
 
     /**
@@ -52,6 +54,7 @@
     public ColorDrawable(int color) {
         this(null);
         setColor(color);
+        mMutated = true;
     }
 
     private ColorDrawable(ColorState state) {
@@ -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) {
@@ -165,6 +183,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..020a54f 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -124,6 +124,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 +298,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 +374,27 @@
     }
 
     /**
-     * Get the resolved layout direction of this Drawable.
-     * @hide
+     * 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}
      */
-    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},
+     *
+     */
+    public void setLayoutDirection(int layoutDirection) {
+        if (getLayoutDirection() != layoutDirection) {
+            mLayoutDirection = layoutDirection;
         }
-        return ((Callback2) callback).getResolvedLayoutDirection(this);
     }
 
     /**
@@ -777,7 +778,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..486390c 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;
                 }
             }
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 5b50beb..21344f4 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -124,7 +124,7 @@
     
     private Paint mLayerPaint;    // internal, used if we use saveLayer()
     private boolean mRectIsDirty;   // internal state
-    private boolean mMutated;
+    private boolean mMutated = true;
     private Path mRingPath;
     private boolean mPathIsDirty = true;
 
@@ -1202,6 +1202,7 @@
         mGradientState = state;
         initializeWithState(state);
         mRectIsDirty = true;
+        mMutated = false;
     }
 
     private void initializeWithState(GradientState state) {
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 383fe71..03531ac 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -590,6 +590,18 @@
         return this;
     }
 
+    @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..7a43496 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -77,6 +77,7 @@
     @Deprecated
     public NinePatchDrawable(Bitmap bitmap, byte[] chunk, Rect padding, String srcName) {
         this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding), null);
+        mMutated = true;
     }
 
     /**
@@ -87,6 +88,7 @@
             Rect padding, String srcName) {
         this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding), res);
         mNinePatchState.mTargetDensity = mTargetDensity;
+        mMutated = true;
     }
 
     /**
@@ -99,6 +101,7 @@
             Rect padding, Rect layoutInsets, String srcName) {
         this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding, layoutInsets), res);
         mNinePatchState.mTargetDensity = mTargetDensity;
+        mMutated = true;
     }
 
     /**
@@ -109,6 +112,7 @@
     @Deprecated
     public NinePatchDrawable(NinePatch patch) {
         this(new NinePatchState(patch, new Rect()), null);
+        mMutated = true;
     }
 
     /**
@@ -118,6 +122,7 @@
     public NinePatchDrawable(Resources res, NinePatch patch) {
         this(new NinePatchState(patch, new Rect()), res);
         mNinePatchState.mTargetDensity = mTargetDensity;
+        mMutated = true;
     }
 
     private void setNinePatchState(NinePatchState state, Resources res) {
@@ -181,7 +186,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 +301,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..a5c3614 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -261,6 +261,15 @@
         return this;
     }
 
+    @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..af8b0c2 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -561,6 +561,12 @@
         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  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/ScriptGroup.java b/graphics/java/android/renderscript/ScriptGroup.java
new file mode 100644
index 0000000..c4064b5
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptGroup.java
@@ -0,0 +1,391 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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;
+
+/**
+ * @hide
+ **/
+public class ScriptGroup extends BaseObj {
+    Node mNodes[];
+    Connection mConnections[];
+    Node mFirstNode;
+    IO mOutputs[];
+    IO mInputs[];
+
+    static class IO {
+        Script mScript;
+        Allocation mAllocation;
+        String mName;
+
+        IO(Script s) {
+            mScript = s;
+        }
+        IO(Script s, String n) {
+            mScript = s;
+            mName = n;
+        }
+    }
+
+    static class Connection {
+        Node mTo[];
+        String mToName[];
+        Node mFrom;
+        Type mAllocationType;
+        Allocation mInternalAllocation;
+
+        Connection(Node out, Type t) {
+            mFrom = out;
+            mAllocationType = t;
+        }
+
+        void addTo(Node n, String name) {
+            if (mTo == null) {
+                mTo = new Node[1];
+                mToName = new String[1];
+            } else {
+                Node nt[] = new Node[mTo.length + 1];
+                String ns[] = new String[mTo.length + 1];
+                System.arraycopy(mTo, 0, nt, 0, mTo.length);
+                System.arraycopy(mToName, 0, ns, 0, mTo.length);
+                mTo = nt;
+                mToName = ns;
+            }
+            mTo[mTo.length - 1] = n;
+            mToName[mTo.length - 1] = name;
+        }
+    }
+
+    static class Node {
+        Script mScript;
+        Connection mInput[] = new Connection[8];
+        Connection mOutput[] = new Connection[1];
+        int mInputCount;
+        int mOutputCount;
+        int mDepth;
+        boolean mSeen;
+
+        Node mNext;
+
+        Node(Script s) {
+            mScript = s;
+        }
+
+        void addInput(Connection c) {
+            if (mInput.length <= mInputCount) {
+                Connection[] nc = new Connection[mInput.length + 8];
+                System.arraycopy(mInput, 0, nc, 0, mInputCount);
+                mInput = nc;
+            }
+            mInput[mInputCount++] = c;
+        }
+
+        void addOutput(Connection c) {
+            if (mOutput.length <= mOutputCount) {
+                Connection[] nc = new Connection[mOutput.length + 8];
+                System.arraycopy(mOutput, 0, nc, 0, mOutputCount);
+                mOutput = nc;
+            }
+            mOutput[mOutputCount++] = c;
+        }
+    }
+
+
+    ScriptGroup(int id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    void init(int nodeCount, int connectionCount) {
+        mNodes = new Node[nodeCount];
+        mConnections = new Connection[connectionCount];
+
+        android.util.Log.v("RSR", "init" + nodeCount + ", " + connectionCount);
+
+        // Count outputs and create array.
+        Node n = mFirstNode;
+        int outputCount = 0;
+        int inputCount = 0;
+        int connectionIndex = 0;
+        int nodeNum = 0;
+        while (n != null) {
+            mNodes[nodeNum++] = n;
+
+            // Look for unattached kernel inputs
+            boolean hasInput = false;
+            for (int ct=0; ct < n.mInput.length; ct++) {
+                if (n.mInput[ct] != null) {
+                    if (n.mInput[ct].mToName == null) {
+                        hasInput = true;
+                    }
+                }
+            }
+            if (!hasInput) {
+                if (mInputs == null) {
+                    mInputs = new IO[1];
+                }
+                if (mInputs.length <= inputCount) {
+                    IO t[] = new IO[mInputs.length + 1];
+                    System.arraycopy(mInputs, 0, t, 0, mInputs.length);
+                    mInputs = t;
+                }
+                mInputs[inputCount++] = new IO(n.mScript);
+            }
+
+            // Look for unattached kernel outputs
+            boolean hasOutput = false;
+            for (int ct=0; ct < n.mOutput.length; ct++) {
+                if (n.mOutput[ct] != null) {
+                    hasOutput = true;
+                }
+            }
+            if (!hasOutput) {
+                if (mOutputs == null) {
+                    mOutputs = new IO[1];
+                }
+                if (mOutputs.length <= outputCount) {
+                    IO t[] = new IO[mOutputs.length + 1];
+                    System.arraycopy(mOutputs, 0, t, 0, mOutputs.length);
+                    mOutputs = t;
+                }
+                mOutputs[outputCount++] = new IO(n.mScript);
+            }
+
+            // Make allocations for internal connections
+            // Since script outputs are unique, use those to avoid duplicates.
+            for (int ct=0; ct < n.mOutput.length; ct++) {
+                android.util.Log.v("RSR", "init out2 " + n.mOutput[ct]);
+                if (n.mOutput[ct] != null) {
+                    Connection t = n.mOutput[ct];
+                    mConnections[connectionIndex++] = t;
+                    t.mInternalAllocation = Allocation.createTyped(mRS, t.mAllocationType);
+                }
+            }
+
+            n = n.mNext;
+        }
+    }
+
+    public void setInput(Script s, Allocation a) {
+        for (int ct=0; ct < mInputs.length; ct++) {
+            if (mInputs[ct].mScript == s) {
+                mInputs[ct].mAllocation = a;
+                return;
+            }
+        }
+        throw new RSIllegalArgumentException("Script not found");
+    }
+
+    public void setOutput(Script s, Allocation a) {
+        for (int ct=0; ct < mOutputs.length; ct++) {
+            if (mOutputs[ct].mScript == s) {
+                mOutputs[ct].mAllocation = a;
+                return;
+            }
+        }
+        throw new RSIllegalArgumentException("Script not found");
+    }
+
+    public void execute() {
+        android.util.Log.v("RSR", "execute");
+        boolean more = true;
+        int depth = 0;
+        while (more) {
+            more = false;
+            for (int ct=0; ct < mNodes.length; ct++) {
+                if (mNodes[ct].mDepth == depth) {
+                    more = true;
+
+                    Allocation kernelIn = null;
+                    for (int ct2=0; ct2 < mNodes[ct].mInputCount; ct2++) {
+                        android.util.Log.v("RSR", " kin " + ct2 + ", to " + mNodes[ct].mInput[ct2].mTo[0] + ", name " + mNodes[ct].mInput[ct2].mToName[0]);
+                        if (mNodes[ct].mInput[ct2].mToName[0] == null) {
+                            kernelIn = mNodes[ct].mInput[ct2].mInternalAllocation;
+                            break;
+                        }
+                    }
+
+                    Allocation kernelOut= null;
+                    for (int ct2=0; ct2 < mNodes[ct].mOutputCount; ct2++) {
+                        android.util.Log.v("RSR", " kout " + ct2 + ", from " + mNodes[ct].mOutput[ct2].mFrom);
+                        if (mNodes[ct].mOutput[ct2].mFrom != null) {
+                            kernelOut = mNodes[ct].mOutput[ct2].mInternalAllocation;
+                            break;
+                        }
+                    }
+                    if (kernelOut == null) {
+                        for (int ct2=0; ct2 < mOutputs.length; ct2++) {
+                            if (mOutputs[ct2].mScript == mNodes[ct].mScript) {
+                                kernelOut = mOutputs[ct2].mAllocation;
+                                break;
+                            }
+                        }
+                    }
+
+                    android.util.Log.v("RSR", "execute calling " + mNodes[ct] + ", with " + kernelIn);
+                    if (kernelIn != null) {
+                        try {
+
+                            Method m = mNodes[ct].mScript.getClass().getMethod("forEach_root",
+                                          new Class[] { Allocation.class, Allocation.class });
+                            m.invoke(mNodes[ct].mScript, new Object[] {kernelIn, kernelOut} );
+                        } catch (Throwable t) {
+                            android.util.Log.e("RSR", "execute error " + t);
+                        }
+                    } else {
+                        try {
+                            Method m = mNodes[ct].mScript.getClass().getMethod("forEach_root",
+                                          new Class[] { Allocation.class });
+                            m.invoke(mNodes[ct].mScript, new Object[] {kernelOut} );
+                        } catch (Throwable t) {
+                            android.util.Log.e("RSR", "execute error " + t);
+                        }
+                    }
+
+                }
+            }
+            depth ++;
+        }
+
+    }
+
+
+    public static class Builder {
+        RenderScript mRS;
+        Node mFirstNode;
+        int mConnectionCount = 0;
+        int mNodeCount = 0;
+
+        public Builder(RenderScript rs) {
+            mRS = rs;
+        }
+
+        private void validateRecurse(Node n, int depth) {
+            n.mSeen = true;
+            if (depth > n.mDepth) {
+                n.mDepth = depth;
+            }
+
+            android.util.Log.v("RSR", " validateRecurse outputCount " + n.mOutputCount);
+            for (int ct=0; ct < n.mOutputCount; ct++) {
+                for (int ct2=0; ct2 < n.mOutput[ct].mTo.length; ct2++) {
+                    if (n.mOutput[ct].mTo[ct2].mSeen) {
+                        throw new RSInvalidStateException("Loops in group not allowed.");
+                    }
+                    validateRecurse(n.mOutput[ct].mTo[ct2], depth + 1);
+                }
+            }
+        }
+
+        private void validate() {
+            android.util.Log.v("RSR", "validate");
+            Node n = mFirstNode;
+            while (n != null) {
+                n.mSeen = false;
+                n.mDepth = 0;
+                n = n.mNext;
+            }
+
+            n = mFirstNode;
+            while (n != null) {
+                android.util.Log.v("RSR", "validate n= " + n);
+                if ((n.mSeen == false) && (n.mInputCount == 0)) {
+                    android.util.Log.v("RSR", " recursing " + n);
+                    validateRecurse(n, 0);
+                }
+                n = n.mNext;
+            }
+        }
+
+        private Node findScript(Script s) {
+            Node n = mFirstNode;
+            while (n != null) {
+                if (n.mScript == s) {
+                    return n;
+                }
+                n = n.mNext;
+            }
+            return null;
+        }
+
+        private void addNode(Node n) {
+            n.mNext = mFirstNode;
+            mFirstNode = n;
+        }
+
+        public Builder addConnection(Type t, Script output, Script input, String inputName) {
+            android.util.Log.v("RSR", "addConnection " + t +", " + output + ", " + input);
+
+            // Look for existing output
+            Node nout = findScript(output);
+            Connection c;
+            if (nout == null) {
+                // Make new node
+                android.util.Log.v("RSR", "addConnection new output node");
+                nout = new Node(output);
+                mNodeCount++;
+                c = new Connection(nout, t);
+                mConnectionCount++;
+                nout.addOutput(c);
+                addNode(nout);
+            } else {
+                // Add to existing node
+                android.util.Log.v("RSR", "addConnection reuse output node");
+                if (nout.mOutput[0] != null) {
+                    if (nout.mOutput[0].mFrom.mScript != output) {
+                        throw new RSInvalidStateException("Changed output of existing node");
+                    }
+                    if (nout.mOutput[0].mAllocationType != t) {
+                        throw new RSInvalidStateException("Changed output type of existing node");
+                    }
+                }
+                c = nout.mOutput[0];
+            }
+            // At this point we should have a connection attached to a script ouput.
+
+            // Find input
+            Node nin = findScript(input);
+            if (nin == null) {
+                android.util.Log.v("RSR", "addConnection new input node");
+                nin = new Node(input);
+                mNodeCount++;
+                addNode(nin);
+            }
+            c.addTo(nin, inputName);
+            nin.addInput(c);
+
+            validate();
+            return this;
+        }
+
+        public ScriptGroup create() {
+            ScriptGroup sg = new ScriptGroup(0, mRS);
+            sg.mFirstNode = mFirstNode;
+            mFirstNode = null;
+
+            android.util.Log.v("RSR", "create nodes= " + mNodeCount + ", Connections= " + mConnectionCount);
+
+            sg.init(mNodeCount, mConnectionCount);
+            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/ScriptIntrinsicBlur.java b/graphics/java/android/renderscript/ScriptIntrinsicBlur.java
new file mode 100644
index 0000000..8d093a7
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicBlur.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 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;
+        bindAllocation(ain, 1);
+    }
+
+    /**
+     * Set the radius of the Blur.
+     *
+     * Supported range 0-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-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);
+    }
+
+}
+
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java b/graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java
new file mode 100644
index 0000000..933a4dd
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.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.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);
+    }
+
+}
+
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java b/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java
new file mode 100644
index 0000000..fb2948d
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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;
+        bindAllocation(ain, 1);
+    }
+
+    /**
+     * 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);
+    }
+
+}
+
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicConvolve5x5.java b/graphics/java/android/renderscript/ScriptIntrinsicConvolve5x5.java
new file mode 100644
index 0000000..8599426
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicConvolve5x5.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.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;
+        bindAllocation(ain, 1);
+    }
+
+    /**
+    * 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);
+    }
+
+}
+
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicLUT.java b/graphics/java/android/renderscript/ScriptIntrinsicLUT.java
new file mode 100644
index 0000000..e45c0fd
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicLUT.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 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;
+        }
+        bindAllocation(mTables, 0);
+    }
+
+    /**
+     * 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);
+    }
+
+}
+
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicYuvToRGB.java b/graphics/java/android/renderscript/ScriptIntrinsicYuvToRGB.java
new file mode 100644
index 0000000..b4a228b
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicYuvToRGB.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 android.renderscript;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map.Entry;
+import java.util.HashMap;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+/**
+ * @hide
+ **/
+public class ScriptIntrinsicYuvToRGB extends ScriptIntrinsic {
+    ScriptIntrinsicYuvToRGB(int id, RenderScript rs) {
+        super(id, rs);
+    }
+
+
+
+    public static class Builder {
+        RenderScript mRS;
+
+        public Builder(RenderScript rs) {
+            mRS = rs;
+        }
+
+        public void setInputFormat(int inputFormat) {
+
+        }
+
+        public void setOutputFormat(Element e) {
+
+        }
+
+        public ScriptIntrinsicYuvToRGB create() {
+            return 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..2109a01 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,13 @@
     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
@@ -1412,6 +1419,7 @@
 {"rsnScriptSetVarObj",               "(IIII)V",                               (void*)nScriptSetVarObj },
 
 {"rsnScriptCCreate",                 "(ILjava/lang/String;Ljava/lang/String;[BI)I",  (void*)nScriptCCreate },
+{"rsnScriptIntrinsicCreate",         "(III)I",                                (void*)nScriptIntrinsicCreate },
 
 {"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/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/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/hwui/Android.mk b/libs/hwui/Android.mk
index 5ec3983..e032ae4 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -6,13 +6,17 @@
 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 \
@@ -27,6 +31,7 @@
 		SkiaColorFilter.cpp \
 		SkiaShader.cpp \
 		Snapshot.cpp \
+		Stencil.cpp \
 		TextureCache.cpp \
 		TextDropShadowCache.cpp
 	
@@ -40,12 +45,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..1de0f9d 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() {
@@ -74,6 +72,8 @@
 
     mTexCoordsArrayEnabled = false;
 
+    glDisable(GL_SCISSOR_TEST);
+    scissorEnabled = false;
     mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0;
 
     glActiveTexture(gTextureUnits[0]);
@@ -89,6 +89,10 @@
     mInitialized = true;
 }
 
+void Caches::initFont() {
+    fontRenderer = GammaFontRenderer::createRenderer();
+}
+
 void Caches::initExtensions() {
     if (extensions.hasDebugMarker()) {
         eventMark = glInsertEventMarkerEXT;
@@ -119,6 +123,16 @@
     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;
+    }
+}
+
 void Caches::terminate() {
     if (!mInitialized) return;
 
@@ -169,8 +183,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 +204,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");
@@ -244,10 +258,11 @@
             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();
@@ -306,6 +321,10 @@
     return false;
 }
 
+///////////////////////////////////////////////////////////////////////////////
+// Meshes and textures
+///////////////////////////////////////////////////////////////////////////////
+
 void Caches::bindPositionVertexPointer(bool force, GLuint slot, GLvoid* vertices, GLsizei stride) {
     if (force || vertices != mCurrentPositionPointer) {
         glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, stride, vertices);
@@ -351,14 +370,49 @@
     }
 }
 
-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)) {
+
         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;
+        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 +420,26 @@
     mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0;
 }
 
+///////////////////////////////////////////////////////////////////////////////
+// Tiling
+///////////////////////////////////////////////////////////////////////////////
+
+void Caches::startTiling(GLuint x, GLuint y, GLuint width, GLuint height, bool opaque) {
+    if (extensions.hasTiledRendering()) {
+
+    }
+}
+
+void Caches::endTiling() {
+    if (extensions.hasTiledRendering()) {
+
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// 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..50e9e75 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;
@@ -197,13 +200,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
@@ -221,6 +231,7 @@
     GLenum lastSrcMode;
     GLenum lastDstMode;
     Program* currentProgram;
+    bool scissorEnabled;
 
     // VBO to draw with
     GLuint meshBuffer;
@@ -230,6 +241,7 @@
 
     // Misc
     GLint maxTextureSize;
+    bool debugLayersUpdates;
 
     TextureCache textureCache;
     LayerCache layerCache;
@@ -244,9 +256,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 +274,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) { }
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..cc72df6 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",
@@ -149,6 +149,7 @@
     delete mTransformMatrix3D;
     delete mStaticMatrix;
     delete mAnimationMatrix;
+
     mTransformMatrix = NULL;
     mTransformCamera = NULL;
     mTransformMatrix3D = NULL;
@@ -156,51 +157,60 @@
     mAnimationMatrix = NULL;
 
     Caches& caches = Caches::getInstance();
+    caches.resourceCache.lock();
 
     for (size_t i = 0; i < mBitmapResources.size(); i++) {
-        caches.resourceCache.decrementRefcount(mBitmapResources.itemAt(i));
+        caches.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);
-        caches.resourceCache.destructor(bitmap);
+        caches.resourceCache.decrementRefcountLocked(bitmap);
+        caches.resourceCache.destructorLocked(bitmap);
     }
-    mOwnedBitmapResources.clear();
 
     for (size_t i = 0; i < mFilterResources.size(); i++) {
-        caches.resourceCache.decrementRefcount(mFilterResources.itemAt(i));
+        caches.resourceCache.decrementRefcountLocked(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));
+        caches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i));
+        caches.resourceCache.destructorLocked(mShaders.itemAt(i));
     }
-    mShaders.clear();
+
+    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);
     }
-    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);
     }
+
+    mBitmapResources.clear();
+    mOwnedBitmapResources.clear();
+    mFilterResources.clear();
+    mShaders.clear();
+    mSourcePaths.clear();
+    mPaints.clear();
+    mPaths.clear();
     mMatrices.clear();
+    mLayers.clear();
 }
 
 void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing) {
@@ -223,35 +233,50 @@
     mReader.setMemory(buffer, mSize);
 
     Caches& caches = Caches::getInstance();
+    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.incrementRefcount(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.incrementRefcount(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.incrementRefcount(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.incrementRefcount(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));
@@ -262,12 +287,6 @@
         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));
@@ -486,7 +505,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 +591,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 +611,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]);
             }
@@ -851,11 +874,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 +889,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 +905,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 +1023,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 +1129,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 +1228,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 +1253,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,7 +1338,8 @@
 // Base structure
 ///////////////////////////////////////////////////////////////////////////////
 
-DisplayListRenderer::DisplayListRenderer() : mWriter(MIN_WRITER_SIZE),
+DisplayListRenderer::DisplayListRenderer():
+        mCaches(Caches::getInstance()), mWriter(MIN_WRITER_SIZE),
         mTranslateX(0.0f), mTranslateY(0.0f), mHasTranslate(false), mHasDrawOps(false) {
 }
 
@@ -1304,34 +1350,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,6 +1394,8 @@
 
     mMatrices.clear();
 
+    mLayers.clear();
+
     mHasDrawOps = false;
 }
 
@@ -1373,8 +1429,12 @@
     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
 }
 
@@ -1496,7 +1556,7 @@
 
 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;
@@ -1570,6 +1630,10 @@
 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) {
+    int alpha;
+    SkXfermode::Mode mode;
+    OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode);
+
     const bool reject = quickReject(left, top, right, bottom);
     uint32_t* location = addOp(DisplayList::DrawPatch, reject);
     addBitmap(bitmap);
@@ -1577,7 +1641,8 @@
     addInts(yDivs, height);
     addUInts(colors, numColors);
     addBounds(left, top, right, bottom);
-    addPaint(paint);
+    addInt(alpha);
+    addInt(mode);
     addSkip(location);
     return DrawGlInfo::kStatusDone;
 }
@@ -1668,8 +1733,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
@@ -1692,39 +1787,19 @@
     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..a0b1630 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,
@@ -496,6 +496,7 @@
     SortedVector<SkPath*> mSourcePaths;
     Vector<SkMatrix*> mMatrices;
     Vector<SkiaShader*> mShaders;
+    Vector<Layer*> mLayers;
 
     mutable SkFlattenableReadBuffer mReader;
 
@@ -599,12 +600,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,6 +653,10 @@
         return mSourcePaths;
     }
 
+    const Vector<Layer*>& getLayers() const {
+        return mLayers;
+    }
+
     const Vector<SkMatrix*>& getMatrices() const {
         return mMatrices;
     }
@@ -763,17 +768,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 +790,8 @@
         }
 
         addInt((int) paintCopy);
+
+        return paintCopy;
     }
 
     inline void addDisplayList(DisplayList* displayList) {
@@ -802,6 +809,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 +822,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 +844,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 +853,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,15 +873,18 @@
 
     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;
 
     friend class DisplayList;
diff --git a/libs/hwui/Dither.cpp b/libs/hwui/Dither.cpp
new file mode 100755
index 0000000..5817977
--- /dev/null
+++ b/libs/hwui/Dither.cpp
@@ -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.
+ */
+
+#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();
+
+    glUniform1i(program->getUniform("ditherSampler"), textureSlot);
+    glUniform1f(program->getUniform("ditherSize"), 1.0f / DITHER_KERNEL_SIZE);
+}
+
+}; // 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..86667ee 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,35 @@
 
     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;
+    // 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()) {
             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);
+            uint32_t width = cacheTexture->getWidth();
+            uint32_t height = cacheTexture->getHeight();
+            void* textureData = cacheTexture->getTexture();
 
-            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("glTextSubimage for cacheTexture %d: xOff, width height = %d, %d, %d",
+                    i, xOffset, width, height);
+#endif
+            glTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, 0, 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,7 +367,7 @@
     Caches& caches = Caches::getInstance();
     caches.bindIndicesBuffer(mIndexBufferID);
     if (!mDrawn) {
-        float* buffer = mTextMeshPtr;
+        float* buffer = mTextMesh;
         int offset = 2;
 
         bool force = caches.unbindMeshBuffer();
@@ -875,7 +396,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 +464,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 +480,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 +501,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 +515,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 +546,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 +609,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 +709,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 +742,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..76b274b
--- /dev/null
+++ b/libs/hwui/Layer.cpp
@@ -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.
+ */
+
+#define LOG_TAG "OpenGLRenderer"
+
+#include <utils/Log.h>
+
+#include "Layer.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;
+    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);
+    if (fbo) Caches::getInstance().fboCache.put(fbo);
+    deleteTexture();
+}
+
+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..420073a 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -45,25 +45,9 @@
  * 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() {
-        if (mesh) delete mesh;
-        if (meshIndices) delete meshIndices;
-    }
+    Layer(const uint32_t layerWidth, const uint32_t layerHeight);
+    ~Layer();
 
     /**
      * Sets this layer's region to a rectangle. Computes the appropriate
@@ -106,6 +90,8 @@
         texture.height = height;
     }
 
+    ANDROID_API void setPaint(SkPaint* paint);
+
     inline void setBlend(bool blend) {
         texture.blend = blend;
     }
@@ -191,9 +177,7 @@
         return colorFilter;
     }
 
-    inline void setColorFilter(SkiaColorFilter* filter) {
-        colorFilter = filter;
-    }
+    ANDROID_API void setColorFilter(SkiaColorFilter* filter);
 
     inline void bindTexture() {
         glBindTexture(renderTarget, texture.id);
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..b57d806 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -45,7 +45,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 +57,6 @@
     }
 
     return OpenGLRenderer::prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, opaque);
-#else
-    return OpenGLRenderer::prepareDirty(0.0f, 0.0f, width, height, opaque);
-#endif
 }
 
 void LayerRenderer::finish() {
@@ -87,14 +83,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 +97,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 +163,6 @@
             indices[index + 5] = quad + 3;   // bottom-right
         }
     }
-#endif
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -221,10 +211,8 @@
                     fbo, width, height);
 
             glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
-            caches.fboCache.put(fbo);
 
-            layer->deleteTexture();
-            delete layer;
+            Caches::getInstance().resourceCache.decrementRefcount(layer);
 
             return NULL;
         }
@@ -233,9 +221,8 @@
     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
             layer->getTexture(), 0);
 
-    glDisable(GL_SCISSOR_TEST);
+    caches.disableScissor();
     glClear(GL_COLOR_BUFFER_BIT);
-    glEnable(GL_SCISSOR_TEST);
 
     glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
 
@@ -251,8 +238,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;
         }
     }
@@ -314,8 +300,7 @@
 
         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
@@ -343,10 +328,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);
         }
@@ -411,6 +396,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 +418,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 +447,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);
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index 8f3a0a3..531aa5b 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -61,12 +61,13 @@
             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);
 
 private:
     void generateMesh();
 
+    static void flushLayer(Layer* layer);
+
     Layer* mLayer;
 }; // class LayerRenderer
 
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 9a90bfd..4aefcba 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -45,8 +45,7 @@
 #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)
 
@@ -140,10 +139,6 @@
 // Setup
 ///////////////////////////////////////////////////////////////////////////////
 
-uint32_t OpenGLRenderer::getStencilSize() {
-    return STENCIL_BUFFER_SIZE;
-}
-
 bool OpenGLRenderer::isDeferred() {
     return false;
 }
@@ -158,7 +153,6 @@
     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);
@@ -179,9 +173,19 @@
     mSnapshot->setClip(left, top, right, bottom);
     mDirtyClip = opaque;
 
+    // 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();
 
     if (!opaque) {
+        mCaches.enableScissor();
         mCaches.setScissor(left, mSnapshot->height - bottom, right - left, bottom - top);
         glClear(GL_COLOR_BUFFER_BIT);
         return DrawGlInfo::kStatusDrew;
@@ -251,7 +255,8 @@
     glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 
-    glEnable(GL_SCISSOR_TEST);
+    mCaches.scissorEnabled = glIsEnabled(GL_SCISSOR_TEST);
+    mCaches.enableScissor();
     mCaches.resetScissor();
     dirtyClip();
 
@@ -303,10 +308,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 +321,7 @@
     interrupt();
     detachFunctor(functor);
 
+    mCaches.enableScissor();
     if (mDirtyClip) {
         setScissorFromClip();
     }
@@ -321,13 +329,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;
@@ -441,7 +447,7 @@
             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 +455,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 +515,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;
     }
 
@@ -564,23 +582,23 @@
     layer->setBlend(true);
 
     // 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,37 +609,20 @@
     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);
-
-    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);
+    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);
 
     // Bind texture to FBO
     glBindFramebuffer(GL_FRAMEBUFFER, layer->getFbo());
@@ -642,16 +643,15 @@
         ALOGE("Framebuffer incomplete (GL error code 0x%x)", status);
 
         glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
-        layer->deleteTexture();
-        mCaches.fboCache.put(layer->getFbo());
 
-        delete layer;
+        Caches::getInstance().resourceCache.decrementRefcount(layer);
 
         return false;
     }
 #endif
 
     // 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);
@@ -730,8 +730,7 @@
     // 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);
     }
 }
 
@@ -825,7 +824,6 @@
 }
 
 void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
-#if RENDER_LAYERS_AS_REGIONS
     if (layer->region.isRect()) {
         layer->setRegionAsRect();
 
@@ -906,9 +904,6 @@
 
         layer->region.clear();
     }
-#else
-    composeLayerRect(layer, rect);
-#endif
 }
 
 void OpenGLRenderer::drawRegionRects(const Region& region) {
@@ -939,27 +934,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 +957,6 @@
             region->orSelf(dirty);
         }
     }
-#endif
 }
 
 void OpenGLRenderer::clearLayerRegions() {
@@ -982,7 +971,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 +999,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,16 +1056,31 @@
     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::quickRejectNoScissor(float left, float top, float right, float bottom) {
+    if (mSnapshot->isIgnored()) {
+        return true;
+    }
+
+    Rect r(left, top, right, bottom);
+    mSnapshot->transform->mapRect(r);
+    r.snapToPixelBoundaries();
+
+    Rect clipRect(*mSnapshot->clipRect);
+    clipRect.snapToPixelBoundaries();
+
+    return !clipRect.intersects(r);
+}
+
 bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) {
     if (mSnapshot->isIgnored()) {
         return true;
@@ -1089,7 +1093,12 @@
     Rect clipRect(*mSnapshot->clipRect);
     clipRect.snapToPixelBoundaries();
 
-    return !clipRect.intersects(r);
+    bool rejected = !clipRect.intersects(r);
+    if (!isDeferred() && !rejected) {
+        mCaches.setScissorEnabled(!clipRect.contains(r));
+    }
+
+    return rejected;
 }
 
 bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
@@ -1109,6 +1118,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();
@@ -1138,6 +1149,10 @@
     mDescription.isAA = true;
 }
 
+void OpenGLRenderer::setupDrawAARect() {
+    mDescription.isAARect = true;
+}
+
 void OpenGLRenderer::setupDrawPoint(float pointSize) {
     mDescription.isPoint = true;
     mDescription.pointSize = pointSize;
@@ -1171,6 +1186,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;
@@ -1298,6 +1317,10 @@
     }
 }
 
+void OpenGLRenderer::setupDrawTextGammaUniforms() {
+    mCaches.fontRenderer->setupProgram(mDescription, mCaches.currentProgram);
+}
+
 void OpenGLRenderer::setupDrawSimpleMesh() {
     bool force = mCaches.bindMeshBuffer();
     mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position, 0);
@@ -1385,10 +1408,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) {
@@ -1554,11 +1573,7 @@
     float right = FLT_MIN;
     float bottom = FLT_MIN;
 
-#if RENDER_LAYERS_AS_REGIONS
     const bool hasActiveLayer = hasLayer();
-#else
-    const bool hasActiveLayer = false;
-#endif
 
     // TODO: Support the colors array
     TextureVertex mesh[count];
@@ -1589,7 +1604,6 @@
             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])));
@@ -1597,15 +1611,12 @@
                 right = fmaxf(right, fmaxf(vertices[ax], fmaxf(vertices[bx], vertices[cx])));
                 bottom = fmaxf(bottom, fmaxf(vertices[ay], fmaxf(vertices[by], vertices[cy])));
             }
-#endif
         }
     }
 
-#if RENDER_LAYERS_AS_REGIONS
     if (hasActiveLayer) {
         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 +1685,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 +1709,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 +1731,6 @@
                 }
             }
         }
-#endif
 
         if (CC_LIKELY(pureTranslate)) {
             const float x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f);
@@ -1735,82 +1753,103 @@
 
 /**
  * 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.
+ * We expand the rectangle by a half pixel in screen space on all sides. 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 into the region.
  */
 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 m11 = mat->data[Matrix4::kScaleY];
         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;
     }
 
-    setupDraw();
-    setupDrawNoTexture();
-    setupDrawAALine();
-    setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha);
-    setupDrawColorFilter();
-    setupDrawShader();
-    setupDrawBlending(true, mode);
-    setupDrawProgram();
-    setupDrawModelViewIdentity(true);
-    setupDrawColorUniforms();
-    setupDrawColorFilterUniforms();
-    setupDrawShaderIdentityUniforms();
-
-    AAVertex rects[4];
-    AAVertex* aaVertices = &rects[0];
-    void* widthCoords = ((GLbyte*) aaVertices) + gVertexAAWidthOffset;
-    void* lengthCoords = ((GLbyte*) aaVertices) + gVertexAALengthOffset;
-
     float boundarySizeX = .5 * inverseScaleX;
     float boundarySizeY = .5 * inverseScaleY;
 
+    float innerLeft = left + boundarySizeX;
+    float innerRight = right - boundarySizeX;
+    float innerTop = top + boundarySizeY;
+    float innerBottom = bottom - boundarySizeY;
+
     // 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);
-    }
+        setupDraw();
+        setupDrawNoTexture();
+        setupDrawAARect();
+        setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha);
+        setupDrawColorFilter();
+        setupDrawShader();
+        setupDrawBlending(true, mode);
+        setupDrawProgram();
+        setupDrawModelViewIdentity(true);
+        setupDrawColorUniforms();
+        setupDrawColorFilterUniforms();
+        setupDrawShaderIdentityUniforms();
 
-    finishDrawAALine(widthSlot, lengthSlot);
+        AlphaVertex rects[14];
+        AlphaVertex* aVertices = &rects[0];
+        void* alphaCoords = ((GLbyte*) aVertices) + gVertexAlphaOffset;
+
+        bool force = mCaches.unbindMeshBuffer();
+        mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position,
+                aVertices, gAlphaVertexStride);
+        mCaches.resetTexCoordsVertexPointer();
+        mCaches.unbindIndicesBuffer();
+
+        int alphaSlot = mCaches.currentProgram->getAttrib("vtxAlpha");
+        glEnableVertexAttribArray(alphaSlot);
+        glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, gAlphaVertexStride, alphaCoords);
+
+        // draw left
+        AlphaVertex::set(aVertices++, left, bottom, 0);
+        AlphaVertex::set(aVertices++, innerLeft, innerBottom, 1);
+        AlphaVertex::set(aVertices++, left, top, 0);
+        AlphaVertex::set(aVertices++, innerLeft, innerTop, 1);
+
+        // draw top
+        AlphaVertex::set(aVertices++, right, top, 0);
+        AlphaVertex::set(aVertices++, innerRight, innerTop, 1);
+
+        // draw right
+        AlphaVertex::set(aVertices++, right, bottom, 0);
+        AlphaVertex::set(aVertices++, innerRight, innerBottom, 1);
+
+        // draw bottom
+        AlphaVertex::set(aVertices++, left, bottom, 0);
+        AlphaVertex::set(aVertices++, innerLeft, innerBottom, 1);
+
+        // draw inner rect (repeating last vertex to create degenerate bridge triangles)
+        // TODO: also consider drawing the inner rect without the blending-forced shader, if
+        // blending is expensive. Note: can't use drawColorRect() since it doesn't use vertex
+        // buffers like below, resulting in slightly different transformed coordinates.
+        AlphaVertex::set(aVertices++, innerLeft, innerBottom, 1);
+        AlphaVertex::set(aVertices++, innerLeft, innerTop, 1);
+        AlphaVertex::set(aVertices++, innerRight, innerBottom, 1);
+        AlphaVertex::set(aVertices++, innerRight, innerTop, 1);
+
+        dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
+
+        glDrawArrays(GL_TRIANGLE_STRIP, 0, 14);
+
+        glDisableVertexAttribArray(alphaSlot);
+    }
 }
 
 /**
@@ -1864,10 +1903,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,6 +1919,9 @@
     }
 
     getAlphaAndMode(paint, &alpha, &mode);
+
+    mCaches.enableScissor();
+
     setupDraw();
     setupDrawNoTexture();
     if (isAA) {
@@ -1924,7 +1964,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 +1973,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 +1986,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 +2014,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 +2028,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 +2050,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 +2076,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 +2149,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);
@@ -2254,6 +2290,44 @@
     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 +2348,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 +2356,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 +2369,7 @@
 
     mCaches.activeTexture(0);
     setupDraw();
+    setupDrawTextGamma(paint);
     setupDrawDirtyRegionsDisabled();
     setupDrawWithTexture(true);
     setupDrawAlpha8Color(paint->getColor(), alpha);
@@ -2302,33 +2382,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 +2436,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 +2449,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 +2462,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 +2477,29 @@
     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.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 (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 +2514,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 +2524,7 @@
 
     mCaches.activeTexture(0);
     setupDraw();
+    setupDrawTextGamma(paint);
     setupDrawDirtyRegionsDisabled();
     setupDrawWithTexture(true);
     setupDrawAlpha8Color(paint->getColor(), alpha);
@@ -2485,24 +2537,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;
@@ -2531,6 +2578,8 @@
         return DrawGlInfo::kStatusDone;
     }
 
+    bool debugLayerUpdate = false;
+
     if (layer->deferredUpdateScheduled && layer->renderer && layer->displayList) {
         OpenGLRenderer* renderer = layer->renderer;
         Rect& dirty = layer->dirtyRect;
@@ -2546,23 +2595,19 @@
         layer->deferredUpdateScheduled = false;
         layer->renderer = NULL;
         layer->displayList = NULL;
+
+        debugLayerUpdate = mCaches.debugLayersUpdates;
     }
 
     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())) {
         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;
+            SkiaColorFilter *oldFilter = mColorFilter;
+            mColorFilter = layer->getColorFilter();
 
             setupDraw();
             setupDrawWithTexture();
@@ -2574,12 +2619,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,
@@ -2592,15 +2637,18 @@
 
             finishDrawTexture();
 
+            mColorFilter = oldFilter;
+
 #if DEBUG_LAYERS_AS_REGIONS
             drawRegionRects(layer->region);
 #endif
         }
+
+        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
 
     return DrawGlInfo::kStatusDrew;
 }
@@ -2723,23 +2771,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 +2901,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 +2954,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..7f9405f 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -63,16 +63,68 @@
     ANDROID_API OpenGLRenderer();
     virtual ~OpenGLRenderer();
 
+    /**
+     * 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);
 
+    /**
+     * 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 int 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 int 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);
@@ -90,10 +142,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 +153,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 +172,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 +186,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,11 +207,52 @@
 
     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:
     /**
      * Compose the layer defined in the current snapshot with the layer
@@ -213,6 +306,28 @@
      */
     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;
+    }
+
 private:
     /**
      * Ensures the state of the renderer is the same as the state of
@@ -259,7 +374,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 +385,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 +434,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);
@@ -446,6 +559,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 +586,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 +602,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 +625,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,6 +640,7 @@
      * Invoked before any drawing operation. This sets required state.
      */
     void setupDraw(bool clear = true);
+
     /**
      * Various methods to setup OpenGL rendering.
      */
@@ -532,11 +648,13 @@
     void setupDrawWithExternalTexture();
     void setupDrawNoTexture();
     void setupDrawAALine();
+    void setupDrawAARect();
     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 +679,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,6 +689,10 @@
     void finishDrawTexture();
     void accountForClear(SkXfermode::Mode mode);
 
+    /**
+     * Renders the specified region as a series of rectangles. This method
+     * is used for debugging only.
+     */
     void drawRegionRects(const Region& region);
 
     /**
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index 27f530c..abc88fa 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
@@ -268,6 +266,11 @@
     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 DEBUG_PATCHES_EMPTY_VERTICES
@@ -278,13 +281,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/Program.h b/libs/hwui/Program.h
index eb9ee7b..a821a9c 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_AA_RECT_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 isAARect;
 
     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;
+        isAARect = 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 (isAARect) key |= programid(0x1) << PROGRAM_IS_AA_RECT_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;
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index a7f1277..2d13f60 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -43,6 +43,8 @@
 const char* gVS_Header_Attributes_AAParameters =
         "attribute float vtxWidth;\n"
         "attribute float vtxLength;\n";
+const char* gVS_Header_Attributes_AARectParameters =
+        "attribute float vtxAlpha;\n";
 const char* gVS_Header_Uniforms_TextureTransform =
         "uniform mat4 mainTextureTransform;\n";
 const char* gVS_Header_Uniforms =
@@ -65,25 +67,24 @@
 const char* gVS_Header_Varyings_IsAA =
         "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_IsAARect =
+        "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 float linear;\n",
+
         // Circular
-        "varying vec2 circular;\n",
+        "varying highp vec2 circular;\n",
+        "varying highp vec2 circular;\n",
+
         // Sweep
-        "varying vec2 sweep;\n"
+        "varying highp vec2 sweep;\n",
+        "varying highp vec2 sweep;\n",
 };
 const char* gVS_Main =
         "\nvoid main(void) {\n";
@@ -91,13 +92,18 @@
         "    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 = (screenSpace * position).x;\n",
+
         // Circular
         "    circular = (screenSpace * position).xy;\n",
+        "    circular = (screenSpace * position).xy;\n",
+
         // Sweep
-        "    sweep = (screenSpace * position).xy;\n"
+        "    sweep = (screenSpace * position).xy;\n",
+        "    sweep = (screenSpace * position).xy;\n",
 };
 const char* gVS_Main_OutBitmapTexCoords =
         "    outBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n";
@@ -110,6 +116,8 @@
 const char* gVS_Main_AA =
         "    widthProportion = vtxWidth;\n"
         "    lengthProportion = vtxLength;\n";
+const char* gVS_Main_AARect =
+        "    alpha = vtxAlpha;\n";
 const char* gVS_Footer =
         "}\n\n";
 
@@ -127,23 +135,32 @@
         "uniform vec4 color;\n";
 const char* gFS_Uniforms_AA =
         "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 ditherSize;\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 +176,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, gl_FragCoord.xy * ditherSize).a * ditherSize * ditherSize"
+const char* gFS_Main_AddDitherToGradient =
+        "    gradientColor += " FS_MAIN_DITHER ";\n";
+
 // Fast cases
 const char* gFS_Fast_SingleColor =
         "\nvoid main(void) {\n"
@@ -174,28 +199,44 @@
         "}\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 =
@@ -203,37 +244,42 @@
 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";
+        "    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_AccountForAARect =
+        "    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 +289,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",
+        " * fragColor.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 * fragColor.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 * fragColor.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";
@@ -388,8 +443,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) {
@@ -398,7 +456,9 @@
     if (description.hasTexture || description.hasExternalTexture) {
         shader.append(gVS_Header_Attributes_TexCoords);
     }
-    if (description.isAA) {
+    if (description.isAARect) {
+        shader.append(gVS_Header_Attributes_AARectParameters);
+    } else if (description.isAA) {
         shader.append(gVS_Header_Attributes_AAParameters);
     }
     // Uniforms
@@ -419,17 +479,18 @@
     if (description.hasTexture || description.hasExternalTexture) {
         shader.append(gVS_Header_Varyings_HasTexture);
     }
-    if (description.isAA) {
+    if (description.isAARect) {
+        shader.append(gVS_Header_Varyings_IsAARect);
+    } else if (description.isAA) {
         shader.append(gVS_Header_Varyings_IsAA);
     }
     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
@@ -439,11 +500,13 @@
         } else if (description.hasTexture || description.hasExternalTexture) {
             shader.append(gVS_Main_OutTexCoords);
         }
-        if (description.isAA) {
+        if (description.isAARect) {
+            shader.append(gVS_Main_AARect);
+        } else if (description.isAA) {
             shader.append(gVS_Main_AA);
         }
         if (description.hasGradient) {
-            shader.append(gVS_Main_OutGradient[description.gradientType]);
+            shader.append(gVS_Main_OutGradient[gradientIndex(description)]);
         }
         if (description.hasBitmap) {
             shader.append(description.isPoint ?
@@ -464,6 +527,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;
 
@@ -481,17 +552,18 @@
     if (description.hasTexture || description.hasExternalTexture) {
         shader.append(gVS_Header_Varyings_HasTexture);
     }
-    if (description.isAA) {
+    if (description.isAARect) {
+        shader.append(gVS_Header_Varyings_IsAARect);
+    } else if (description.isAA) {
         shader.append(gVS_Header_Varyings_IsAA);
     }
     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
@@ -512,15 +584,19 @@
         shader.append(gFS_Uniforms_AA);
     }
     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.isAARect) {
         bool fast = false;
 
         const bool noShader = !description.hasGradient && !description.hasBitmap;
@@ -544,16 +620,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 +678,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 +706,36 @@
         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.isAARect) {
+            shader.append(gFS_Main_AccountForAARect);
+        } else if (description.isAA) {
+            shader.append(gFS_Main_AccountForAA);
+        }
+
         // Output the fragment
         if (!blendFramebuffer) {
             shader.append(gFS_Main_FragColor);
@@ -676,13 +765,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..0e3268e 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
 
@@ -43,9 +40,10 @@
 #define STENCIL_BUFFER_SIZE 0
 
 /**
- * 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,12 @@
     kDebugMoreCaches = kDebugMemory | kDebugCaches
 };
 
+/**
+ * Used to enable/disbale 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"
+
 // 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 +74,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..80f39ff 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..1c83ea4 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);
     }
 }
 
+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()) {
@@ -146,7 +207,12 @@
 
 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()) {
@@ -163,7 +229,12 @@
 
 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;
@@ -177,7 +248,12 @@
 
 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;
@@ -189,6 +265,29 @@
     }
 }
 
+void ResourceCache::recycle(SkBitmap* resource) {
+    Mutex::Autolock _l(mLock);
+    recycleLocked(resource);
+}
+
+void 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;
+    }
+    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;
+    }
+    ref->recycled = true;
+    if (ref->refCount == 0) {
+        deleteResourceReference(resource, ref);
+    }
+}
+
 /**
  * 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).
@@ -197,7 +296,7 @@
     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 +324,11 @@
                 delete filter;
             }
             break;
+            case kLayer: {
+                Layer* layer = (Layer*) resource;
+                delete layer;
+            }
+            break;
         }
     }
     mCache->removeItem(resource);
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index 8cf466b..2053d96 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);
+
+    void recycle(SkBitmap* resource);
+    void recycleLocked(SkBitmap* resource);
+
 private:
     void deleteResourceReference(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/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..4484676 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,7 +171,7 @@
     clipRect->set(left, top, right, bottom);
 #if STENCIL_BUFFER_SIZE
     if (clipRegion) {
-        clipRegion->clear();
+        clipRegion->setEmpty();
         clipRegion = NULL;
     }
 #endif
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 30b03fc..a89b740 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -198,7 +198,7 @@
      *
      * This field is used only if STENCIL_BUFFER_SIZE is > 0.
      */
-    Region* clipRegion;
+    SkRegion* clipRegion;
 
     /**
      * The ancestor layer's dirty region.
@@ -223,17 +223,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..9d2c86f
--- /dev/null
+++ b/libs/hwui/Stencil.cpp
@@ -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.
+ */
+
+#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_LESS, 0x0, 0x1);
+        // We only want to test, let's keep everything
+        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+        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);
+        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..67ccc78
--- /dev/null
+++ b/libs/hwui/Stencil.h
@@ -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.
+ */
+
+#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();
+
+    /**
+     * 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/font/CacheTexture.cpp b/libs/hwui/font/CacheTexture.cpp
new file mode 100644
index 0000000..4a3af12
--- /dev/null
+++ b/libs/hwui/font/CacheTexture.cpp
@@ -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.
+ */
+
+#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;
+            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..bf1f4a9
--- /dev/null
+++ b/libs/hwui/font/CacheTexture.h
@@ -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.
+ */
+
+#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"
+
+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() {
+        if (mTexture) {
+            delete[] mTexture;
+        }
+        if (mTextureId) {
+            glDeleteTextures(1, &mTextureId);
+        }
+        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) {
+            glDeleteTextures(1, &mTextureId);
+            delete[] mTexture;
+            mTexture = NULL;
+            mTextureId = 0;
+        }
+    }
+
+    /**
+     * This method assumes that the proper texture unit is active.
+     */
+    void allocateTexture() {
+        int width = mWidth;
+        int height = mHeight;
+
+        mTexture = new uint8_t[width * height];
+
+        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, width, height, 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 uint8_t* getTexture() const {
+        return mTexture;
+    }
+
+    inline GLuint getTextureId() const {
+        return mTextureId;
+    }
+
+    inline bool isDirty() const {
+        return mDirty;
+    }
+
+    inline void setDirty(bool dirty) {
+        mDirty = dirty;
+    }
+
+    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;
+};
+
+}; // 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..6e205b8
--- /dev/null
+++ b/libs/hwui/font/Font.cpp
@@ -0,0 +1,441 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <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/location/java/android/location/Criteria.java b/location/java/android/location/Criteria.java
index 1f3fb7a..68fb4a0 100644
--- a/location/java/android/location/Criteria.java
+++ b/location/java/android/location/Criteria.java
@@ -24,7 +24,11 @@
  * location provider.  Providers maybe ordered according to accuracy,
  * power usage, ability to report altitude, speed,
  * and bearing, and monetary cost.
+ *
+ * @deprecated use {@link LocationRequest} instead, and also see notes
+ * at {@link LocationManager}
  */
+@Deprecated
 public class Criteria implements Parcelable {
     /**
      * A constant indicating that the application does not choose to
@@ -326,6 +330,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 +345,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 +368,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..03cca84
--- /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, but this object
+ * is opaque so could be used in the future to represent polygons or other
+ * shapes.
+ */
+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 horizontal, circular geofence.
+     *
+     * @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..40cb1a8 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 {
     /**
@@ -59,6 +61,7 @@
 
     private String mProvider;
     private long mTime = 0;
+    private long mElapsedRealtimeNano = 0;
     private double mLatitude = 0.0;
     private double mLongitude = 0.0;
     private boolean mHasAltitude = false;
@@ -82,31 +85,20 @@
     // Scratchpad
     private 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 +110,7 @@
     public void set(Location l) {
         mProvider = l.mProvider;
         mTime = l.mTime;
+        mElapsedRealtimeNano = l.mElapsedRealtimeNano;
         mLatitude = l.mLatitude;
         mLongitude = l.mLongitude;
         mHasAltitude = l.mHasAltitude;
@@ -137,6 +130,7 @@
     public void reset() {
         mProvider = null;
         mTime = 0;
+        mElapsedRealtimeNano = 0;
         mLatitude = 0;
         mLongitude = 0;
         mHasAltitude = false;
@@ -452,9 +446,19 @@
     }
 
     /**
-     * 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.
+     *
+     * <p class="note">At API version 17 we deprecated {@link LocationProvider}
+     * and all API methods that request a provider by name. The new API methods
+     * will produce locations that could come from different sources, and even
+     * locations that are fused from several sources. So you should generally
+     * not care what provider is associated with a location object.
+     *
+     * @return the provider, or null if it has not been set
+     *
+     * @deprecated locations can now be sourced from many providers, or even fused
      */
+    @Deprecated
     public String getProvider() {
         return mProvider;
     }
@@ -467,68 +471,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 #getElapsedRealtimeNano} 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#elapsedRealtimeNano},
+     * 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 getElapsedRealtimeNano() {
+        return mElapsedRealtimeNano;
+    }
+
+    /**
+     * 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 setElapsedRealtimeNano(long time) {
+        mElapsedRealtimeNano = 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 +590,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 +601,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 +627,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 +638,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 +677,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 +688,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 +736,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 +747,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 (mElapsedRealtimeNano == 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 (mElapsedRealtimeNano == 0) mElapsedRealtimeNano = SystemClock.elapsedRealtimeNano();
+    }
+
+    /**
      * 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 +811,50 @@
         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 (mElapsedRealtimeNano == 0) {
+            s.append(" et=?!?");
+        } else {
+            s.append(" et=");
+            TimeUtils.formatDuration(mElapsedRealtimeNano / 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();
+    }
+
+    /**
+     * @deprecated Use {@link #toString} instead
+     */
+    @Deprecated
+    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.mElapsedRealtimeNano = in.readLong();
             l.mLatitude = in.readDouble();
             l.mLongitude = in.readDouble();
             l.mHasAltitude = in.readInt() != 0;
@@ -714,18 +869,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(mElapsedRealtimeNano);
         parcel.writeDouble(mLatitude);
         parcel.writeDouble(mLongitude);
         parcel.writeInt(mHasAltitude ? 1 : 0);
@@ -737,5 +896,5 @@
         parcel.writeInt(mHasAccuracy ? 1 : 0);
         parcel.writeFloat(mAccuracy);
         parcel.writeBundle(mExtras);
-   }
+    }
 }
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 5c256a3..b127b53 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,47 @@
  * {@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>At API version 17 the Location API's were simplified.
+ * Previously applications would need to explicitly enumerate, select, and
+ * track Location Providers (such as GPS or Network).
+ * This has been replaced by the concept of
+ * <em>Fused Location</em>. Now applications just specify the quality of service
+ * required for location updates (using the new {@link LocationRequest} class),
+ * and the system will fuse results from individual location providers
+ * as necessary before returning the result to the application.
+ *
+ * <p>As a result of this change, the {@link LocationProvider} and
+ * {@link Criteria} classes have been deprecated, in favor of
+ * {@link LocationRequest}. Furthermore, all Location Manager
+ * methods involving Criteria or explicitly named Providers have
+ * been deprecated, in favor of new variants that use
+ * {@link LocationRequest}.
+ *
+ * <p>A single {@link LocationRequest} object can trigger the use
+ * of all providers (including GPS, Network, and the passive) provider
+ * as necessary. This should result in a lot less work for your application. You
+ * no longer need to track the status and availability of each
+ * location provider. Just set the quality of locations required
+ * in {@link LocationRequest}, and let the system manage the rest.
+ *
+ * <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 still
+ * receive location results, but the update rate will be throttled and
+ * the exact location will be obfuscated to a coarse level of accuracy.
+ *
+ * <p> class="note">Before API level 17, the use of 'fine' location
+ * providers such as GPS required the fine permission. As of API level
+ * 17, applications with only the coarse permission may use all providers,
+ * including GPS, but the locations are obfuscated (made coarse) before
+ * being sent to the application.
  */
 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,45 +94,74 @@
     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.
+     * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
      */
+    @Deprecated
     public static final String NETWORK_PROVIDER = "network";
 
     /**
-     * Name of the GPS location provider. This provider determines location using
+     * Name of the GPS location provider.
+     *
+     * <p>This provider determines location using
      * satellites. Depending on conditions, this provider may take a while to return
      * a location fix.
      *
-     * Requires the permission android.permission.ACCESS_FINE_LOCATION.
+     * <p>Before API version 17, this provider required the
+     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission.
+     * From API version 17 and onwards, this provider can also be used with
+     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}, however
+     * the locations returned will be obfuscated to a coarse level of accuracy.
      *
      * <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>
+     *
+     * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
      */
+    @Deprecated
     public static final String GPS_PROVIDER = "gps";
 
     /**
      * 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.
+     * <p>Before API version 17, this provider required the
+     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission.
+     * From API version 17 and onwards, this provider can also be used with
+     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}, however
+     * the locations returned will be obfuscated to a coarse level of accuracy.
+     *
+     * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
      */
+    @Deprecated
     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)..
      */
@@ -108,13 +170,19 @@
     /**
      * Key used for a Bundle extra holding an Integer status value
      * when a status change is broadcast using a PendingIntent.
+     *
+     * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
      */
+    @Deprecated
     public static final String KEY_STATUS_CHANGED = "status";
 
     /**
      * Key used for a Bundle extra holding an Boolean status value
      * when a provider enabled/disabled event is broadcast using a PendingIntent.
+     *
+     * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
      */
+    @Deprecated
     public static final String KEY_PROVIDER_ENABLED = "providerEnabled";
 
     /**
@@ -129,7 +197,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";
@@ -137,7 +205,10 @@
     /**
      * Broadcast intent action when the configured location providers
      * change.
+     *
+     * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
      */
+    @Deprecated
     public static final String PROVIDERS_CHANGED_ACTION =
         "android.location.PROVIDERS_CHANGED";
 
@@ -147,7 +218,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 +228,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 +265,7 @@
             }
         }
 
+        @Override
         public void onLocationChanged(Location location) {
             Message msg = Message.obtain();
             msg.what = TYPE_LOCATION_CHANGED;
@@ -203,6 +273,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 +287,7 @@
             mListenerHandler.sendMessage(msg);
         }
 
+        @Override
         public void onProviderEnabled(String provider) {
             Message msg = Message.obtain();
             msg.what = TYPE_PROVIDER_ENABLED;
@@ -223,6 +295,7 @@
             mListenerHandler.sendMessage(msg);
         }
 
+        @Override
         public void onProviderDisabled(String provider) {
             Message msg = Message.obtain();
             msg.what = TYPE_PROVIDER_DISABLED;
@@ -257,6 +330,7 @@
             }
         }
     }
+
     /**
      * @hide - hide this constructor because it has a parameter
      * of type ILocationManager, which is a system private class. The
@@ -268,53 +342,44 @@
         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
+     *
+     * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
      */
+    @Deprecated
     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.
      * @return list of Strings containing names of the providers
+     *
+     * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
      */
+    @Deprecated
     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 +391,23 @@
      * @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.
+     *
+     * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
      */
+    @Deprecated
     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;
     }
@@ -355,15 +421,16 @@
      * @param enabledOnly if true then only the providers which are currently
      * enabled are returned.
      * @return list of Strings containing names of the providers
+     *
+     * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
      */
+    @Deprecated
     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;
     }
@@ -389,78 +456,26 @@
      * @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
+     *
+     * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
      */
+    @Deprecated
     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 (deprecated) method.
      *
      * @param provider the name of the provider with which to register
      * @param minTime minimum time interval between location updates, in milliseconds
@@ -473,77 +488,26 @@
      * 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
+     * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
      */
-    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);
+    @Deprecated
+    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 (deprecated) method.
      *
      * @param provider the name of the provider with which to register
      * @param minTime minimum time interval between location updates, in milliseconds
@@ -552,72 +516,32 @@
      * {@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
+     *
+     * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
      */
-    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);
+    @Deprecated
+    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 (deprecated) method.
      *
      * @param minTime minimum time interval between location updates, in milliseconds
      * @param minDistance minimum distance between location updates, in meters
@@ -627,113 +551,32 @@
      * {@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
+     *
+     * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
      */
-    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);
-    }
+    @Deprecated
+    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 (deprecated) method.
      *
      * @param provider the name of the provider with which to register
      * @param minTime minimum time interval between location updates, in milliseconds
@@ -743,32 +586,44 @@
      * @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
+     *
+     * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
      */
-    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);
+    @Deprecated
+    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> methods involving
+     * an explicit String provider or {@link Criteria} are deprecated.
+     *
+     * <p>They 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 +649,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.
@@ -819,87 +693,58 @@
      *
      * @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
+     *
+     * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
      */
+    @Deprecated
     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 (deprecated) method.
      *
      * @param provider the name of the provider with which to register
      * @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
+     *
+     * @deprecated Use {@link LocationRequest#setNumUpdates} instead
      */
+    @Deprecated
     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 (deprecated) method.
      *
      * @param criteria contains parameters for the location manager to choose the
      * appropriate provider and parameters to compute the location
@@ -907,73 +752,55 @@
      * {@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
+     *
+     * @deprecated Use {@link LocationRequest#setNumUpdates} instead
      */
+    @Deprecated
     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 (deprecated) method.
      *
      * @param provider the name of the provider with which to register
      * @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
+     *
+     * @deprecated Use {@link LocationRequest#setNumUpdates} instead
      */
+    @Deprecated
     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 (deprecated) method.
      *
      * @param criteria contains parameters for the location manager to choose the
      * appropriate provider and parameters to compute the location
@@ -981,68 +808,170 @@
      *
      * @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
+     *
+     * @deprecated Use {@link LocationRequest#setNumUpdates} instead
      */
+    @Deprecated
     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>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.
+     *
+     * @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
+     */
+    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> 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
+     */
+    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 +991,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 +1011,201 @@
      * @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
+     *
+     * @deprecated Use {@link LocationRequest} and {@link Geofence} instead
      */
-    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);
-        }
+    @Deprecated
+    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
+     */
+    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
+     *
+     * @deprecated Use {@link LocationRequest} and {@link Geofence} instead
      */
+    @Deprecated
     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
+     */
+    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
+     */
+    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
+     *
+     * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
      */
+    @Deprecated
     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#getElapsedRealtimeNano} 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
+     */
+    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,51 +1215,57 @@
      * @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
+     *
+     * @deprecated Use {@link #getLastLocation} instead
      */
+    @Deprecated
     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
      * Settings.Secure.ALLOW_MOCK_LOCATION} system setting is not enabled
      * @throws IllegalArgumentException if a provider with the given name already exists
+     *
+     * @deprecated requesting location providers by name is deprecated
      */
+    @Deprecated
     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);
         }
     }
 
@@ -1208,18 +1278,24 @@
      * 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
+     *
+     * @deprecated requesting location providers by name is deprecated
      */
+    @Deprecated
     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 +1304,29 @@
      * 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
+     *
+     * @deprecated requesting location providers by name is deprecated
      */
+    @Deprecated
     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);
         }
     }
 
@@ -1246,12 +1339,15 @@
      * 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
+     *
+     * @deprecated requesting location providers by name is deprecated
      */
+    @Deprecated
     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);
         }
     }
 
@@ -1266,12 +1362,15 @@
      * 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
+     *
+     * @deprecated requesting location providers by name is deprecated
      */
+    @Deprecated
     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);
         }
     }
 
@@ -1284,14 +1383,16 @@
      * 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
+     *
+     * @deprecated requesting location providers by name is deprecated
      */
+    @Deprecated
     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);
         }
-
     }
 
     /**
@@ -1307,12 +1408,15 @@
      * 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
+     *
+     * @deprecated requesting location providers by name is deprecated
      */
+    @Deprecated
     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);
         }
     }
 
@@ -1325,16 +1429,19 @@
      * 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
+     *
+     * @deprecated requesting location providers by name is deprecated
      */
+    @Deprecated
     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 +1474,7 @@
             mNmeaBuffer = new ArrayList<Nmea>();
         }
 
+        @Override
         public void onGpsStarted() {
             if (mListener != null) {
                 Message msg = Message.obtain();
@@ -1375,6 +1483,7 @@
             }
         }
 
+        @Override
         public void onGpsStopped() {
             if (mListener != null) {
                 Message msg = Message.obtain();
@@ -1383,6 +1492,7 @@
             }
         }
 
+        @Override
         public void onFirstFix(int ttff) {
             if (mListener != null) {
                 mGpsStatus.setTimeToFirstFix(ttff);
@@ -1392,6 +1502,7 @@
             }
         }
 
+        @Override
         public void onSvStatusChanged(int svCount, int[] prns, float[] snrs,
                 float[] elevations, float[] azimuths, int ephemerisMask,
                 int almanacMask, int usedInFixMask) {
@@ -1407,6 +1518,7 @@
             }
         }
 
+        @Override
         public void onNmeaReceived(long timestamp, String nmea) {
             if (mNmeaListener != null) {
                 synchronized (mNmeaBuffer) {
@@ -1563,7 +1675,10 @@
      * The provider may optionally fill the extras Bundle with results from the command.
      *
      * @return true if the command succeeds.
+     *
+     * @deprecated Use {@link LocationRequest} instead, see notes on {@link LocationManager}
      */
+    @Deprecated
     public boolean sendExtraCommand(String provider, String command, Bundle extras) {
         try {
             return mService.sendExtraCommand(provider, command, extras);
@@ -1577,7 +1692,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 +1703,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..737e17f 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
@@ -32,35 +32,40 @@
  * characteristics or monetary costs to the user.  The {@link
  * Criteria} class allows providers to be selected based on
  * user-specified criteria.
+ *
+ * @deprecated Use the {@link Criteria} class to request location instead of
+ * enumerating providers.
  */
-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;
-
+@Deprecated
+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 +80,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 +162,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 +172,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 +182,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 +192,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 +203,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..b1863b8
--- /dev/null
+++ b/location/java/android/location/LocationRequest.java
@@ -0,0 +1,585 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.
+ */
+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 = null;  // for deprecated API's 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() { }
+
+    /**
+     * 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) {
+        mExpireAt = millis + SystemClock.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/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..b0e5d2c
--- /dev/null
+++ b/location/lib/java/com/android/location/provider/LocationProviderBase.java
@@ -0,0 +1,196 @@
+/*
+ * 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.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;
+
+    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/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..3605381
--- /dev/null
+++ b/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java
@@ -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.
+ */
+
+package com.android.location.provider;
+
+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<LocationRequest> getLocationRequests() {
+        return mRequest.locationRequests;
+    }
+
+    @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..ea00ec8 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";
 
     /**
@@ -412,6 +413,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 +466,7 @@
                  * responsive to the user.
                  */
                 int flags = FLAG_SHOW_UI | FLAG_VIBRATE;
+
                 if (mUseMasterVolume) {
                     adjustMasterVolume(
                             keyCode == KeyEvent.KEYCODE_VOLUME_UP
@@ -502,18 +506,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 +1164,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 +1300,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
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 2e153dd..4459d03 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -57,6 +57,7 @@
 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;
@@ -143,12 +144,16 @@
     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_SET_FORCE_RSX_USE = 24;        // force remote submix audio routing
+    private static final int MSG_CHECK_MUSIC_ACTIVE = 25;
 
     // flags for MSG_PERSIST_VOLUME indicating if current and/or last audible volume should be
     // persisted
@@ -381,7 +386,7 @@
     // message looper for SoundPool listener
     private Looper mSoundPoolLooper = null;
     // volume applied to sound played with playSoundEffect()
-    private static int SOUND_EFFECT_VOLUME_DB;
+    private static int sSoundEffectVolumeDb;
     // getActiveStreamType() will return STREAM_NOTIFICATION during this period after a notification
     // stopped
     private static final int NOTIFICATION_VOLUME_DELAY_MS = 5000;
@@ -426,6 +431,8 @@
         mContentResolver = context.getContentResolver();
         mVoiceCapable = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_voice_capable);
+        mSafeMediaVolumeIndex = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_safe_media_volume_index) * 10;
 
         PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
         mMediaEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleMediaEvent");
@@ -438,7 +445,7 @@
             "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);
@@ -450,6 +457,10 @@
         updateStreamVolumeAlias(false /*updateVolumes*/);
         createStreamStates();
 
+        synchronized (mSafeMediaVolumeEnabled) {
+            enforceSafeMediaVolume();
+        }
+
         mMediaServerOk = true;
 
         // Call setRingerModeInt() to apply correct mute
@@ -734,6 +745,11 @@
         // convert one UI step (+/-1) into a number of internal units on the stream alias
         int step = rescaleIndex(10, streamType, streamTypeAlias);
 
+        if ((direction == AudioManager.ADJUST_RAISE) &&
+                !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
+            return;
+        }
+
         // 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) ||
@@ -811,12 +827,17 @@
         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 */);
 
         index = rescaleIndex(index * 10, streamType, mStreamVolumeAlias[streamType]);
 
+        if (!checkSafeMediaVolume(mStreamVolumeAlias[streamType], index, device)) {
+            return;
+        }
+
         // setting volume on master stream type also controls silent mode
         if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
                 (mStreamVolumeAlias[streamType] == getMasterStreamType())) {
@@ -929,6 +950,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)) {
@@ -943,7 +982,7 @@
         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);
+        sendBroadcastToAll(intent);
     }
 
     // UI update and Broadcast Intent
@@ -953,7 +992,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 +1006,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);
     }
 
     /**
@@ -1661,6 +1698,10 @@
 
         checkAllAliasStreamVolumes();
 
+        synchronized (mSafeMediaVolumeEnabled) {
+            enforceSafeMediaVolume();
+        }
+
         // apply new ringer mode
         setRingerModeInt(getRingerMode(), false);
     }
@@ -1701,7 +1742,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 +2032,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 +2132,60 @@
         }
     };
 
+    /** 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*/);
+
+        // Note that we are  currently forcing use of remote submix as soon as corresponding device
+        //   is made available
+        sendMsg(mAudioHandler, MSG_SET_FORCE_RSX_USE, SENDMSG_REPLACE,
+                AudioSystem.FOR_MEDIA,
+                on ? AudioSystem.FORCE_REMOTE_SUBMIX : AudioSystem.FORCE_NONE,
+                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 (mSafeMediaVolumeEnabled) {
+            if (!mSafeMediaVolumeEnabled) {
+                int device = getDeviceForStream(AudioSystem.STREAM_MUSIC);
+
+                if ((device & mSafeMediaVolumeDevices) != 0) {
+                    sendMsg(mAudioHandler,
+                            MSG_CHECK_MUSIC_ACTIVE,
+                            SENDMSG_REPLACE,
+                            device,
+                            0,
+                            null,
+                            MUSIC_ACTIVE_POLL_PERIOD_MS);
+                    if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)) {
+                        // 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();
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     ///////////////////////////////////////////////////////////////////////////
     // Internal methods
     ///////////////////////////////////////////////////////////////////////////
@@ -2276,9 +2377,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 +2386,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);
         }
     }
 
@@ -2346,6 +2445,14 @@
     public void setWiredDeviceConnectionState(int device, int state, String name) {
         synchronized (mConnectedDevices) {
             int delay = checkSendBecomingNoisyIntent(device, state);
+            if ((device & mSafeMediaVolumeDevices) != 0) {
+                setSafeMediaVolumeEnabled(state != 0);
+                // insert delay to allow new volume to apply before switching to headphones
+                if ((delay < SAFE_VOLUME_DELAY_MS) && (state != 0)) {
+                    delay = SAFE_VOLUME_DELAY_MS;
+                }
+            }
+
             queueMsgUnderWakeLock(mAudioHandler,
                     MSG_SET_WIRED_DEVICE_CONNECTION_STATE,
                     device,
@@ -2875,7 +2982,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;
                 }
@@ -3049,6 +3156,8 @@
                     break;
 
                 case MSG_SET_FORCE_USE:
+                case MSG_SET_FORCE_BT_A2DP_USE:
+                case MSG_SET_FORCE_RSX_USE:
                     setForceUse(msg.arg1, msg.arg2);
                     break;
 
@@ -3111,6 +3220,14 @@
                     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;
             }
         }
     }
@@ -3167,7 +3284,7 @@
     }
 
     private void sendBecomingNoisyIntent() {
-        mContext.sendBroadcast(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
+        sendBroadcastToAll(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
     }
 
     // must be called synchronized on mConnectedDevices
@@ -3286,7 +3403,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) {
@@ -3356,7 +3475,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)
@@ -3508,7 +3632,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,7 +3649,7 @@
                 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) {
@@ -3652,9 +3776,10 @@
             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 + " -- client: " + fse.mClientId
                         + " -- duration: " + fse.mFocusChangeType
-                        + " -- uid: " + fse.mCallingUid);
+                        + " -- uid: " + fse.mCallingUid
+                        + " -- stream: " + fse.mStreamType);
             }
         }
     }
@@ -3915,8 +4040,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 +4079,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 +4150,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;
         }
@@ -4350,7 +4486,7 @@
                         "  -- vol: " + rcse.mPlaybackVolume +
                         "  -- volMax: " + rcse.mPlaybackVolumeMax +
                         "  -- volObs: " + rcse.mRemoteVolumeObs);
-                
+
             }
         }
         synchronized (mMainRemote) {
@@ -4646,17 +4782,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;
         }
@@ -5290,10 +5449,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 +5475,109 @@
         }
     }
 
+
+    //==========================================================================================
+    // 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.
+    //==========================================================================================
+
+    // mSafeMediaVolumeEnabled indicates whether the media volume is limited over headphones.
+    // It is true by default when headphones or a headset are inserted and can be overriden by
+    // calling AudioService.disableSafeMediaVolume() (when user opts out).
+    private Boolean mSafeMediaVolumeEnabled = new Boolean(false);
+    // mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property
+    private final 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_DELAY_MS = 500;  // 500ms before switching to headphones
+
+    private void setSafeMediaVolumeEnabled(boolean on) {
+        synchronized (mSafeMediaVolumeEnabled) {
+            if (on && !mSafeMediaVolumeEnabled) {
+                enforceSafeMediaVolume();
+            } else if (!on && mSafeMediaVolumeEnabled) {
+                mMusicActiveMs = 0;
+                sendMsg(mAudioHandler,
+                        MSG_CHECK_MUSIC_ACTIVE,
+                        SENDMSG_REPLACE,
+                        0,
+                        0,
+                        null,
+                        MUSIC_ACTIVE_POLL_PERIOD_MS);
+            }
+            mSafeMediaVolumeEnabled = on;
+        }
+    }
+
+    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 (mSafeMediaVolumeEnabled) {
+            if (mSafeMediaVolumeEnabled &&
+                    (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
+                    ((device & mSafeMediaVolumeDevices) != 0) &&
+                    (index > mSafeMediaVolumeIndex)) {
+                mVolumePanel.postDisplaySafeVolumeWarning();
+                return false;
+            }
+            return true;
+        }
+    }
+
+    public void disableSafeMediaVolume() {
+        synchronized (mSafeMediaVolumeEnabled) {
+            setSafeMediaVolumeEnabled(false);
+        }
+    }
+
+
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 1ca0df4..129e84f 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -188,6 +188,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 +211,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 +230,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 +242,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 +293,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 +328,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 +353,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_REMOTE_SUBMIX = 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
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..7ae61cd 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);
 
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/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/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..04ba348 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -271,7 +271,7 @@
 
     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();
             new_st->incStrong(thiz);
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..cd7fbd3
--- /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..7020246
--- /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/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/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/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/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..b36bd55 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;
@@ -181,6 +182,7 @@
             }
 
             ret.packageName = pkg.packageName;
+            ret.versionCode = pkg.versionCode;
             ret.installLocation = pkg.installLocation;
             ret.verifiers = pkg.verifiers;
 
@@ -268,12 +270,14 @@
         if (PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE.equals(intent.getAction())) {
             IPackageManager pm = IPackageManager.Stub.asInterface(
                     ServiceManager.getService("package"));
-            String pkg = null;
+            PackageCleanItem pkg = null;
             try {
                 while ((pkg=pm.nextPackageToClean(pkg)) != null) {
-                    eraseFiles(Environment.getExternalStorageAppDataDirectory(pkg));
-                    eraseFiles(Environment.getExternalStorageAppMediaDirectory(pkg));
-                    eraseFiles(Environment.getExternalStorageAppObbDirectory(pkg));
+                    eraseFiles(Environment.getExternalStorageAppDataDirectory(pkg.packageName));
+                    eraseFiles(Environment.getExternalStorageAppMediaDirectory(pkg.packageName));
+                    if (pkg.andCode) {
+                        eraseFiles(Environment.getExternalStorageAppObbDirectory(pkg.packageName));
+                    }
                 }
             } catch (RemoteException e) {
             }
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..318782f
--- /dev/null
+++ b/packages/FusedLocation/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 := optional
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_JAVA_LIBRARIES := com.android.location.provider
+
+LOCAL_PACKAGE_NAME := FusedLocation
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
diff --git a/packages/FusedLocation/AndroidManifest.xml b/packages/FusedLocation/AndroidManifest.xml
new file mode 100644
index 0000000..4c57401
--- /dev/null
+++ b/packages/FusedLocation/AndroidManifest.xml
@@ -0,0 +1,45 @@
+<?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"
+            android:process="system">
+
+        <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="version" android:value="1" />
+        </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..1c22c7a
--- /dev/null
+++ b/packages/FusedLocation/src/com/android/location/fused/FusionEngine.java
@@ -0,0 +1,354 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.ProviderRequestUnbundled;
+
+import android.content.Context;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.location.LocationRequest;
+import android.os.Bundle;
+import android.os.Looper;
+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;
+
+    // threshold below which a location is considered stale enough
+    // that we shouldn't use its bearing, altitude, speed etc
+    private static final double WEIGHT_THRESHOLD = 0.5;
+    // accuracy in meters at which a Location's weight is halved (compared to 0 accuracy)
+    private static final double ACCURACY_HALFLIFE_M = 20.0;
+    // age in seconds at which a Location's weight is halved (compared to 0 age)
+    private static final double AGE_HALFLIFE_S = 60.0;
+
+    private static final double ACCURACY_DECAY_CONSTANT_M = Math.log(2) / ACCURACY_HALFLIFE_M;
+    private static final double AGE_DECAY_CONSTANT_S = Math.log(2) / AGE_HALFLIFE_S;
+
+    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 double mNetworkWeight;
+    private double mGpsWeight;
+
+    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() + ")");
+    }
+
+    private boolean isAvailable() {
+        return mStats.get(GPS).available || mStats.get(NETWORK).available;
+    }
+
+    /** 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;
+        public long lastRequestTtff;
+        @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;
+        }
+
+        ProviderStats gpsStats = mStats.get(GPS);
+        ProviderStats networkStats = mStats.get(NETWORK);
+
+        long networkInterval = Long.MAX_VALUE;
+        long gpsInterval = Long.MAX_VALUE;
+        for (LocationRequest request : mRequest.getLocationRequests()) {
+            switch (request.getQuality()) {
+                case LocationRequest.ACCURACY_FINE:
+                case LocationRequest.POWER_HIGH:
+                    if (request.getInterval() < gpsInterval) {
+                        gpsInterval = request.getInterval();
+                    }
+                    if (request.getInterval() < networkInterval) {
+                        networkInterval = request.getInterval();
+                    }
+                    break;
+                case LocationRequest.ACCURACY_BLOCK:
+                case LocationRequest.ACCURACY_CITY:
+                case LocationRequest.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);
+        }
+    }
+
+    private static double weighAccuracy(Location loc) {
+        double accuracy = loc.getAccuracy();
+        return Math.exp(-accuracy * ACCURACY_DECAY_CONSTANT_M);
+    }
+
+    private static double weighAge(Location loc) {
+        long ageSeconds = SystemClock.elapsedRealtimeNano() - loc.getElapsedRealtimeNano();
+        ageSeconds /= 1000000000L;
+        if (ageSeconds < 0) ageSeconds = 0;
+        return Math.exp(-ageSeconds * AGE_DECAY_CONSTANT_S);
+    }
+
+    private double weigh(double gps, double network) {
+        return (gps * mGpsWeight) + (network * mNetworkWeight);
+    }
+
+    private double weigh(double gps, double network, double wrapMin, double wrapMax) {
+        // apply aliasing
+        double wrapWidth = wrapMax - wrapMin;
+        if (gps - network > wrapWidth / 2) network += wrapWidth;
+        else if (network - gps > wrapWidth / 2) gps += wrapWidth;
+
+        double result = weigh(gps, network);
+
+        // remove aliasing
+        if (result > wrapMax) result -= wrapWidth;
+        return result;
+    }
+
+    private void updateFusedLocation() {
+        // naive fusion
+        mNetworkWeight = weighAccuracy(mNetworkLocation) * weighAge(mNetworkLocation);
+        mGpsWeight = weighAccuracy(mGpsLocation) * weighAge(mGpsLocation);
+        // scale mNetworkWeight and mGpsWeight so that they add to 1
+        double totalWeight = mNetworkWeight + mGpsWeight;
+        mNetworkWeight /= totalWeight;
+        mGpsWeight /= totalWeight;
+
+        Location fused = new Location(LocationManager.FUSED_PROVIDER);
+        // fuse lat/long
+        // assumes the two locations are close enough that earth curvature doesn't matter
+        fused.setLatitude(weigh(mGpsLocation.getLatitude(), mNetworkLocation.getLatitude()));
+        fused.setLongitude(weigh(mGpsLocation.getLongitude(), mNetworkLocation.getLongitude(),
+                -180.0, 180.0));
+
+        // fused accuracy
+        //TODO: use some real math instead of this crude fusion
+        // one suggestion is to fuse in a quadratic manner, eg
+        // sqrt(weigh(gpsAcc^2, netAcc^2)).
+        // another direction to explore is to consider the difference in the 2
+        // locations. If the component locations overlap, the fused accuracy is
+        // better than the component accuracies. If they are far apart,
+        // the fused accuracy is much worse.
+        fused.setAccuracy((float)weigh(mGpsLocation.getAccuracy(), mNetworkLocation.getAccuracy()));
+
+        // fused time - now
+        fused.setTime(System.currentTimeMillis());
+        fused.setElapsedRealtimeNano(SystemClock.elapsedRealtimeNano());
+
+        // fuse altitude
+        if (mGpsLocation.hasAltitude() && !mNetworkLocation.hasAltitude() &&
+                mGpsWeight > WEIGHT_THRESHOLD) {
+            fused.setAltitude(mGpsLocation.getAltitude());   // use GPS
+        } else if (!mGpsLocation.hasAltitude() && mNetworkLocation.hasAltitude() &&
+                mNetworkWeight > WEIGHT_THRESHOLD) {
+            fused.setAltitude(mNetworkLocation.getAltitude());   // use Network
+        } else if (mGpsLocation.hasAltitude() && mNetworkLocation.hasAltitude()) {
+            fused.setAltitude(weigh(mGpsLocation.getAltitude(), mNetworkLocation.getAltitude()));
+        }
+
+        // fuse speed
+        if (mGpsLocation.hasSpeed() && !mNetworkLocation.hasSpeed() &&
+                mGpsWeight > WEIGHT_THRESHOLD) {
+            fused.setSpeed(mGpsLocation.getSpeed());   // use GPS if its not too old
+        } else if (!mGpsLocation.hasSpeed() && mNetworkLocation.hasSpeed() &&
+                mNetworkWeight > WEIGHT_THRESHOLD) {
+            fused.setSpeed(mNetworkLocation.getSpeed());   // use Network
+        } else if (mGpsLocation.hasSpeed() && mNetworkLocation.hasSpeed()) {
+            fused.setSpeed((float)weigh(mGpsLocation.getSpeed(), mNetworkLocation.getSpeed()));
+        }
+
+        // fuse bearing
+        if (mGpsLocation.hasBearing() && !mNetworkLocation.hasBearing() &&
+                mGpsWeight > WEIGHT_THRESHOLD) {
+            fused.setBearing(mGpsLocation.getBearing());   // use GPS if its not too old
+        } else if (!mGpsLocation.hasBearing() && mNetworkLocation.hasBearing() &&
+                mNetworkWeight > WEIGHT_THRESHOLD) {
+            fused.setBearing(mNetworkLocation.getBearing());   // use Network
+        } else if (mGpsLocation.hasBearing() && mNetworkLocation.hasBearing()) {
+            fused.setBearing((float)weigh(mGpsLocation.getBearing(), mNetworkLocation.getBearing(),
+                    0.0, 360.0));
+        }
+
+        mFusedLocation = fused;
+
+        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 %.3f %s\n", mGpsWeight, mGpsLocation));
+        s.append("    ").append(mStats.get(GPS)).append('\n');
+        s.append(String.format("net %.3f %s\n", mNetworkWeight, 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-af/defaults.xml b/packages/SettingsProvider/res/values-af/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-af/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-am/defaults.xml b/packages/SettingsProvider/res/values-am/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-am/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-ar/defaults.xml b/packages/SettingsProvider/res/values-ar/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-ar/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-be/defaults.xml b/packages/SettingsProvider/res/values-be/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-be/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-bg/defaults.xml b/packages/SettingsProvider/res/values-bg/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-bg/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-ca/defaults.xml b/packages/SettingsProvider/res/values-ca/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-ca/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-cs/defaults.xml b/packages/SettingsProvider/res/values-cs/defaults.xml
new file mode 100644
index 0000000..f704333
--- /dev/null
+++ b/packages/SettingsProvider/res/values-cs/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Spořič obrazovky"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-da/defaults.xml b/packages/SettingsProvider/res/values-da/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-da/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-de/defaults.xml b/packages/SettingsProvider/res/values-de/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-de/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-el/defaults.xml b/packages/SettingsProvider/res/values-el/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-el/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-en-rGB/defaults.xml b/packages/SettingsProvider/res/values-en-rGB/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-en-rGB/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-es-rUS/defaults.xml b/packages/SettingsProvider/res/values-es-rUS/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-es-rUS/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-es/defaults.xml b/packages/SettingsProvider/res/values-es/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-es/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-et/defaults.xml b/packages/SettingsProvider/res/values-et/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-et/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-fa/defaults.xml b/packages/SettingsProvider/res/values-fa/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-fa/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-fi/defaults.xml b/packages/SettingsProvider/res/values-fi/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-fi/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-fr/defaults.xml b/packages/SettingsProvider/res/values-fr/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-fr/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-hi/defaults.xml b/packages/SettingsProvider/res/values-hi/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-hi/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-hr/defaults.xml b/packages/SettingsProvider/res/values-hr/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-hr/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-hu/defaults.xml b/packages/SettingsProvider/res/values-hu/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-hu/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-in/defaults.xml b/packages/SettingsProvider/res/values-in/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-in/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-it/defaults.xml b/packages/SettingsProvider/res/values-it/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-it/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-iw/defaults.xml b/packages/SettingsProvider/res/values-iw/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-iw/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-ja/defaults.xml b/packages/SettingsProvider/res/values-ja/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-ja/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-ko/defaults.xml b/packages/SettingsProvider/res/values-ko/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-ko/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-lt/defaults.xml b/packages/SettingsProvider/res/values-lt/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-lt/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-lv/defaults.xml b/packages/SettingsProvider/res/values-lv/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-lv/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-ms/defaults.xml b/packages/SettingsProvider/res/values-ms/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-ms/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-nb/defaults.xml b/packages/SettingsProvider/res/values-nb/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-nb/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-nl/defaults.xml b/packages/SettingsProvider/res/values-nl/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-nl/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-pl/defaults.xml b/packages/SettingsProvider/res/values-pl/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-pl/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-pt-rPT/defaults.xml b/packages/SettingsProvider/res/values-pt-rPT/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-pt-rPT/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-pt/defaults.xml b/packages/SettingsProvider/res/values-pt/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-pt/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-ro/defaults.xml b/packages/SettingsProvider/res/values-ro/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-ro/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-ru/defaults.xml b/packages/SettingsProvider/res/values-ru/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-ru/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-sk/defaults.xml b/packages/SettingsProvider/res/values-sk/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-sk/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-sl/defaults.xml b/packages/SettingsProvider/res/values-sl/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-sl/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-sr/defaults.xml b/packages/SettingsProvider/res/values-sr/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-sr/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-sv/defaults.xml b/packages/SettingsProvider/res/values-sv/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-sv/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-sw/defaults.xml b/packages/SettingsProvider/res/values-sw/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-sw/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-th/defaults.xml b/packages/SettingsProvider/res/values-th/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-th/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-tl/defaults.xml b/packages/SettingsProvider/res/values-tl/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-tl/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-tr/defaults.xml b/packages/SettingsProvider/res/values-tr/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-tr/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-uk/defaults.xml b/packages/SettingsProvider/res/values-uk/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-uk/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-vi/defaults.xml b/packages/SettingsProvider/res/values-vi/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-vi/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-zh-rCN/defaults.xml b/packages/SettingsProvider/res/values-zh-rCN/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-zh-rCN/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-zh-rTW/defaults.xml b/packages/SettingsProvider/res/values-zh-rTW/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-zh-rTW/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values-zu/defaults.xml b/packages/SettingsProvider/res/values-zu/defaults.xml
new file mode 100644
index 0000000..f8c3de3
--- /dev/null
+++ b/packages/SettingsProvider/res/values-zu/defaults.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="def_screensaver_component" msgid="2880543806753704722">"com.google.android.deskclock/com.android.deskclock.Screensaver"</string>
+</resources>
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 2c9a6fe..92261da 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -35,6 +35,7 @@
 
     <bool name="def_bluetooth_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 +47,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 +129,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 +163,14 @@
     <!-- 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>
+
+    <!-- Dreams (screen saver) default settings -->
+    <!-- Whether the feature is enabled when charging (Settings.Secure.SCREENSAVER_ENABLED) -->
+    <bool name="def_screensaver_enabled">true</bool>
+    <!-- Whether the feature activates when docked (SCREENSAVER_ACTIVATE_ON_DOCK) -->
+    <bool name="def_screensaver_activate_on_dock">true</bool>
+    <!-- Whether the feature activates when docked (SCREENSAVER_ACTIVATE_ON_SLEEP) -->
+    <bool name="def_screensaver_activate_on_sleep">false</bool>
+    <!-- ComponentName of the default screen saver (Settings.Secure.SCREENSAVER_COMPONENT) -->
+    <string name="def_screensaver_component">com.google.android.deskclock/com.android.deskclock.Screensaver</string>
 </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..8a847e1 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -30,7 +30,9 @@
 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.Secure;
 import android.telephony.TelephonyManager;
@@ -38,7 +40,6 @@
 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 +50,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 +67,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 = 88;
 
     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 +91,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 +124,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 +144,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 +308,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;
         }
 
@@ -638,7 +674,7 @@
                    "lockscreen.lockedoutpermanently",
                    "lockscreen.password_salt"
            };
-           moveFromSystemToSecure(db, settingsToMove);
+           moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_SECURE, settingsToMove, false);
            upgradeVersion = 52;
        }
 
@@ -688,7 +724,7 @@
                     Secure.SET_INSTALL_LOCATION,
                     Secure.DEFAULT_INSTALL_LOCATION
             };
-            moveFromSystemToSecure(db, settingsToMove);
+            moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_SECURE, settingsToMove, false);
             db.beginTransaction();
             SQLiteStatement stmt = null;
             try {
@@ -1014,7 +1050,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 +1126,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 +1155,191 @@
             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,
+                        R.bool.def_screensaver_enabled);
+                loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
+                        R.bool.def_screensaver_activate_on_dock);
+                loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
+                        R.bool.def_screensaver_activate_on_sleep);
+                loadStringSetting(stmt, Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT,
+                        R.string.def_screensaver_component);
+                loadStringSetting(stmt, Settings.Secure.SCREENSAVER_COMPONENTS,
+                        R.string.def_screensaver_component);
+
+                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.Secure.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.Secure.PACKAGE_VERIFIER_ENABLE,
+                            Settings.Secure.PACKAGE_VERIFIER_TIMEOUT,
+                            Settings.Secure.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.Secure.DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS,
+                            Settings.Secure.DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS,
+                            Settings.Secure.GPRS_REGISTER_CHECK_PERIOD_MS
+                    };
+                    moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, true);
+
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                }
+            }
+            upgradeVersion = 88;
+        }
+
         // *** 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 +1360,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);
@@ -1177,7 +1400,7 @@
     }
 
     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 +1417,7 @@
                 }
             }
             c.close();
-            db.delete("system", "name='lock_pattern'", null);
+            db.delete(TABLE_SYSTEM, "name='lock_pattern'", null);
         } else {
             c.close();
         }
@@ -1202,7 +1425,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);
 
@@ -1471,6 +1694,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,10 +1708,6 @@
 
             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);
 
@@ -1503,21 +1726,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);
 
@@ -1541,9 +1749,6 @@
 
             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();
         }
@@ -1598,41 +1803,9 @@
             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);
@@ -1648,10 +1821,6 @@
             }
             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 +1849,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 +1861,33 @@
             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,
+                    R.bool.def_screensaver_enabled);
+            loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
+                    R.bool.def_screensaver_activate_on_dock);
+            loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
+                    R.bool.def_screensaver_activate_on_sleep);
+            loadStringSetting(stmt, Settings.Secure.SCREENSAVER_COMPONENTS,
+                    R.string.def_screensaver_component);
+            loadStringSetting(stmt, Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT,
+                    R.string.def_screensaver_component);
 
-            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);
         } finally {
             if (stmt != null) stmt.close();
         }
@@ -1730,6 +1901,106 @@
                 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);
+
+            // --- 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);
+
+            // --- 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 +2027,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..1096540 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -563,7 +563,7 @@
                 getContentResolver().insert(contentUri, contentValues);
             }
 
-            if (DEBUG) {
+            if (DEBUG || true) {
                 Log.d(TAG, "Restored setting: " + key + "=" + value);
             }
         }
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..a0ae9e3 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -18,53 +18,77 @@
 
 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.ActivityManagerNative;
 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.pm.UserInfo;
 import android.content.res.AssetFileDescriptor;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteException;
 import android.database.sqlite.SQLiteQueryBuilder;
+import android.database.sqlite.SQLiteStatement;
 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.RemoteException;
 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 +101,135 @@
     // 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>();
+        sSecureGlobalKeys.add(Settings.Secure.ADB_ENABLED);
+        sSecureGlobalKeys.add(Settings.Secure.ASSISTED_GPS_ENABLED);
+        sSecureGlobalKeys.add(Settings.Secure.BLUETOOTH_ON);
+        sSecureGlobalKeys.add(Settings.Secure.CDMA_CELL_BROADCAST_SMS);
+        sSecureGlobalKeys.add(Settings.Secure.CDMA_ROAMING_MODE);
+        sSecureGlobalKeys.add(Settings.Secure.CDMA_SUBSCRIPTION_MODE);
+        sSecureGlobalKeys.add(Settings.Secure.DATA_ACTIVITY_TIMEOUT_MOBILE);
+        sSecureGlobalKeys.add(Settings.Secure.DATA_ACTIVITY_TIMEOUT_WIFI);
+        sSecureGlobalKeys.add(Settings.Secure.DATA_ROAMING);
+        sSecureGlobalKeys.add(Settings.Secure.DEVELOPMENT_SETTINGS_ENABLED);
+        sSecureGlobalKeys.add(Settings.Secure.DEVICE_PROVISIONED);
+        sSecureGlobalKeys.add(Settings.Secure.DISPLAY_DENSITY_FORCED);
+        sSecureGlobalKeys.add(Settings.Secure.DISPLAY_SIZE_FORCED);
+        sSecureGlobalKeys.add(Settings.Secure.DOWNLOAD_MAX_BYTES_OVER_MOBILE);
+        sSecureGlobalKeys.add(Settings.Secure.DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE);
+        sSecureGlobalKeys.add(Settings.Secure.INSTALL_NON_MARKET_APPS);
+        sSecureGlobalKeys.add(Settings.Secure.MOBILE_DATA);
+        sSecureGlobalKeys.add(Settings.Secure.NETSTATS_DEV_BUCKET_DURATION);
+        sSecureGlobalKeys.add(Settings.Secure.NETSTATS_DEV_DELETE_AGE);
+        sSecureGlobalKeys.add(Settings.Secure.NETSTATS_DEV_PERSIST_BYTES);
+        sSecureGlobalKeys.add(Settings.Secure.NETSTATS_DEV_ROTATE_AGE);
+        sSecureGlobalKeys.add(Settings.Secure.NETSTATS_ENABLED);
+        sSecureGlobalKeys.add(Settings.Secure.NETSTATS_GLOBAL_ALERT_BYTES);
+        sSecureGlobalKeys.add(Settings.Secure.NETSTATS_POLL_INTERVAL);
+        sSecureGlobalKeys.add(Settings.Secure.NETSTATS_REPORT_XT_OVER_DEV);
+        sSecureGlobalKeys.add(Settings.Secure.NETSTATS_SAMPLE_ENABLED);
+        sSecureGlobalKeys.add(Settings.Secure.NETSTATS_TIME_CACHE_MAX_AGE);
+        sSecureGlobalKeys.add(Settings.Secure.NETSTATS_UID_BUCKET_DURATION);
+        sSecureGlobalKeys.add(Settings.Secure.NETSTATS_UID_DELETE_AGE);
+        sSecureGlobalKeys.add(Settings.Secure.NETSTATS_UID_PERSIST_BYTES);
+        sSecureGlobalKeys.add(Settings.Secure.NETSTATS_UID_ROTATE_AGE);
+        sSecureGlobalKeys.add(Settings.Secure.NETSTATS_UID_TAG_BUCKET_DURATION);
+        sSecureGlobalKeys.add(Settings.Secure.NETSTATS_UID_TAG_DELETE_AGE);
+        sSecureGlobalKeys.add(Settings.Secure.NETSTATS_UID_TAG_PERSIST_BYTES);
+        sSecureGlobalKeys.add(Settings.Secure.NETSTATS_UID_TAG_ROTATE_AGE);
+        sSecureGlobalKeys.add(Settings.Secure.NETWORK_PREFERENCE);
+        sSecureGlobalKeys.add(Settings.Secure.NITZ_UPDATE_DIFF);
+        sSecureGlobalKeys.add(Settings.Secure.NITZ_UPDATE_SPACING);
+        sSecureGlobalKeys.add(Settings.Secure.NTP_SERVER);
+        sSecureGlobalKeys.add(Settings.Secure.NTP_TIMEOUT);
+        sSecureGlobalKeys.add(Settings.Secure.PDP_WATCHDOG_ERROR_POLL_COUNT);
+        sSecureGlobalKeys.add(Settings.Secure.PDP_WATCHDOG_LONG_POLL_INTERVAL_MS);
+        sSecureGlobalKeys.add(Settings.Secure.PDP_WATCHDOG_MAX_PDP_RESET_FAIL_COUNT);
+        sSecureGlobalKeys.add(Settings.Secure.PDP_WATCHDOG_POLL_INTERVAL_MS);
+        sSecureGlobalKeys.add(Settings.Secure.PDP_WATCHDOG_TRIGGER_PACKET_COUNT);
+        sSecureGlobalKeys.add(Settings.Secure.SAMPLING_PROFILER_MS);
+        sSecureGlobalKeys.add(Settings.Secure.SETUP_PREPAID_DATA_SERVICE_URL);
+        sSecureGlobalKeys.add(Settings.Secure.SETUP_PREPAID_DETECTION_REDIR_HOST);
+        sSecureGlobalKeys.add(Settings.Secure.SETUP_PREPAID_DETECTION_TARGET_URL);
+        sSecureGlobalKeys.add(Settings.Secure.TETHER_DUN_APN);
+        sSecureGlobalKeys.add(Settings.Secure.TETHER_DUN_REQUIRED);
+        sSecureGlobalKeys.add(Settings.Secure.TETHER_SUPPORTED);
+        sSecureGlobalKeys.add(Settings.Secure.THROTTLE_HELP_URI);
+        sSecureGlobalKeys.add(Settings.Secure.THROTTLE_MAX_NTP_CACHE_AGE_SEC);
+        sSecureGlobalKeys.add(Settings.Secure.THROTTLE_NOTIFICATION_TYPE);
+        sSecureGlobalKeys.add(Settings.Secure.THROTTLE_POLLING_SEC);
+        sSecureGlobalKeys.add(Settings.Secure.THROTTLE_RESET_DAY);
+        sSecureGlobalKeys.add(Settings.Secure.THROTTLE_THRESHOLD_BYTES);
+        sSecureGlobalKeys.add(Settings.Secure.THROTTLE_VALUE_KBITSPS);
+        sSecureGlobalKeys.add(Settings.Secure.USB_MASS_STORAGE_ENABLED);
+        sSecureGlobalKeys.add(Settings.Secure.USE_GOOGLE_MAIL);
+        sSecureGlobalKeys.add(Settings.Secure.WEB_AUTOFILL_QUERY_URL);
+        sSecureGlobalKeys.add(Settings.Secure.WIFI_COUNTRY_CODE);
+        sSecureGlobalKeys.add(Settings.Secure.WIFI_FRAMEWORK_SCAN_INTERVAL_MS);
+        sSecureGlobalKeys.add(Settings.Secure.WIFI_FREQUENCY_BAND);
+        sSecureGlobalKeys.add(Settings.Secure.WIFI_IDLE_MS);
+        sSecureGlobalKeys.add(Settings.Secure.WIFI_MAX_DHCP_RETRY_COUNT);
+        sSecureGlobalKeys.add(Settings.Secure.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS);
+        sSecureGlobalKeys.add(Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON);
+        sSecureGlobalKeys.add(Settings.Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY);
+        sSecureGlobalKeys.add(Settings.Secure.WIFI_NUM_OPEN_NETWORKS_KEPT);
+        sSecureGlobalKeys.add(Settings.Secure.WIFI_ON);
+        sSecureGlobalKeys.add(Settings.Secure.WIFI_P2P_DEVICE_NAME);
+        sSecureGlobalKeys.add(Settings.Secure.WIFI_SAVED_STATE);
+        sSecureGlobalKeys.add(Settings.Secure.WIFI_SUPPLICANT_SCAN_INTERVAL_MS);
+        sSecureGlobalKeys.add(Settings.Secure.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED);
+        sSecureGlobalKeys.add(Settings.Secure.WIFI_WATCHDOG_NUM_ARP_PINGS);
+        sSecureGlobalKeys.add(Settings.Secure.WIFI_WATCHDOG_ON);
+        sSecureGlobalKeys.add(Settings.Secure.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED);
+        sSecureGlobalKeys.add(Settings.Secure.WIFI_WATCHDOG_RSSI_FETCH_INTERVAL_MS);
+        sSecureGlobalKeys.add(Settings.Secure.WIMAX_NETWORKS_AVAILABLE_NOTIFICATION_ON);
+        sSecureGlobalKeys.add(Settings.Secure.PACKAGE_VERIFIER_ENABLE);
+        sSecureGlobalKeys.add(Settings.Secure.PACKAGE_VERIFIER_TIMEOUT);
+        sSecureGlobalKeys.add(Settings.Secure.PACKAGE_VERIFIER_DEFAULT_RESPONSE);
+        sSecureGlobalKeys.add(Settings.Secure.DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS);
+        sSecureGlobalKeys.add(Settings.Secure.DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS);
+        sSecureGlobalKeys.add(Settings.Secure.GPRS_REGISTER_CHECK_PERIOD_MS);
+        sSecureGlobalKeys.add(Settings.Secure.WTF_IS_FATAL);
+
+        // Keys from the 'system' table now moved to 'global'
+        // These must match Settings.System.MOVED_TO_GLOBAL
+        sSystemGlobalKeys = new HashSet<String>();
+
+        sSystemGlobalKeys.add(Settings.System.AIRPLANE_MODE_ON);
+        sSystemGlobalKeys.add(Settings.System.AIRPLANE_MODE_RADIOS);
+        sSystemGlobalKeys.add(Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
+        sSystemGlobalKeys.add(Settings.System.AUTO_TIME);
+        sSystemGlobalKeys.add(Settings.System.AUTO_TIME_ZONE);
+        sSystemGlobalKeys.add(Settings.System.CAR_DOCK_SOUND);
+        sSystemGlobalKeys.add(Settings.System.CAR_UNDOCK_SOUND);
+        sSystemGlobalKeys.add(Settings.System.DESK_DOCK_SOUND);
+        sSystemGlobalKeys.add(Settings.System.DESK_UNDOCK_SOUND);
+        sSystemGlobalKeys.add(Settings.System.DOCK_SOUNDS_ENABLED);
+        sSystemGlobalKeys.add(Settings.System.LOCK_SOUND);
+        sSystemGlobalKeys.add(Settings.System.UNLOCK_SOUND);
+        sSystemGlobalKeys.add(Settings.System.LOW_BATTERY_SOUND);
+        sSystemGlobalKeys.add(Settings.System.POWER_SOUNDS_ENABLED);
+        sSystemGlobalKeys.add(Settings.System.STAY_ON_WHILE_PLUGGED_IN);
+        sSystemGlobalKeys.add(Settings.System.WIFI_SLEEP_POLICY);
+    }
+
+    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.
      */
@@ -107,7 +256,7 @@
                 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)) {
                     this.where = Settings.NameValueTable.NAME + "=?";
                     this.args = new String[] { url.getPathSegments().get(1) };
                 } else {
@@ -144,7 +293,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,18 +310,22 @@
      * 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")) {
-            property = Settings.System.SYS_PROP_SETTING_VERSION;
+        final boolean isGlobal = table.equals(TABLE_GLOBAL);
+        if (table.equals(TABLE_SYSTEM)) {
+            property = Settings.System.SYS_PROP_SETTING_VERSION + '_' + userHandle;
             backedUpDataChanged = true;
-        } else if (table.equals("secure")) {
-            property = Settings.Secure.SYS_PROP_SETTING_VERSION;
+        } else if (table.equals(TABLE_SECURE)) {
+            property = Settings.Secure.SYS_PROP_SETTING_VERSION + '_' + userHandle;
+            backedUpDataChanged = true;
+        } else if (isGlobal) {
+            property = Settings.Global.SYS_PROP_SETTING_VERSION;    // this one is global
             backedUpDataChanged = true;
         }
 
@@ -188,8 +343,9 @@
 
         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;
+            getContext().getContentResolver().notifyChange(uri, null, true, notifyTarget);
+            if (LOCAL_LOGV) Log.v(TAG, "notifying for " + notifyTarget + ": " + uri);
         } else {
             if (LOCAL_LOGV) Log.v(TAG, "notification suppressed: " + uri);
         }
@@ -201,7 +357,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 +374,160 @@
     // 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);
+
+            String property = Settings.System.SYS_PROP_SETTING_VERSION + '_' + userHandle;
+            SystemProperties.set(property, "");
+            property = Settings.Secure.SYS_PROP_SETTING_VERSION + '_' + userHandle;
+            SystemProperties.set(property, "");
+        }
     }
 
-    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 +558,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 +586,131 @@
         }
     }
 
+    // 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 +729,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 +750,17 @@
 
     @Override
     public Cursor query(Uri url, String[] select, String where, String[] whereArgs, String sort) {
+        return queryForUser(url, select, where, whereArgs, sort, UserHandle.getCallingUserId());
+    }
+
+    public 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
@@ -437,15 +803,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 +828,10 @@
             db.setTransactionSuccessful();
         } finally {
             db.endTransaction();
-            sKnownMutationsInFlight.decrementAndGet();
+            mutationCount.decrementAndGet();
         }
 
-        sendNotify(uri);
+        sendNotify(uri, callingUser);
         return values.length;
     }
 
@@ -538,6 +909,22 @@
 
     @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;
@@ -551,66 +938,92 @@
             if (!parseProviderList(url, initialValues)) return null;
         }
 
-        SettingsCache cache = SettingsCache.forTable(args.table);
+        // 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 +1185,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 +1212,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..44fb49a 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -15,6 +15,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 +46,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" />
@@ -50,6 +57,7 @@
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
 
     <application
+        android:name="com.android.systemui.SystemUIApplication"
         android:persistent="true"
         android:allowClearUserData="false"
         android:allowBackup="false"
@@ -93,6 +101,16 @@
                 android:excludeFromRecents="true">
         </activity>
 
+        <activity android:name=".recent.RecentsActivity"
+                android:theme="@android:style/Theme.Holo.Wallpaper.NoTitleBar"
+                android:excludeFromRecents="true"
+                android:launchMode="singleInstance"
+                android:exported="true">
+          <intent-filter>
+            <action android:name="com.android.systemui.TOGGLE_RECENTS" />
+          </intent-filter>
+        </activity>
+
         <!-- started from UsbDeviceSettingsManager -->
         <activity android:name=".usb.UsbConfirmActivity"
             android:exported="true"
@@ -129,6 +147,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 +171,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 +183,32 @@
 <!--            <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.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.DREAM" />
+            </intent-filter>
+        </service>
+
+        <activity android:name=".Somnambulator"
+            android:label="@string/start_dreams"
+            android:icon="@mipmap/ic_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>
+        </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/drawable-hdpi/ic_qs_airplane_off.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_airplane_off.png
new file mode 100644
index 0000000..bfe0990
--- /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..b2be115
--- /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..904a688
--- /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..d5f1e29
--- /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_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_off.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_bluetooth_off.png
new file mode 100644
index 0000000..2ba62f9
--- /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..7d6fed5
--- /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..464bb6a
--- /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..dbdc524
--- /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_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..e46d8a3
--- /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_mirroring.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_mirroring.png
new file mode 100644
index 0000000..5912301
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_mirroring.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..115bc41
--- /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..97558ff
--- /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..f5f0f74
--- /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..80472e5
--- /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..59af783
--- /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..54be048
--- /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..2495d07
--- /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..7616e17
--- /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..2bd5949
--- /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..ce77c5e
--- /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..7d8d284
--- /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..bf0e995
--- /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..1782c1c
--- /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_signal.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_no_signal.png
new file mode 100644
index 0000000..c97a167
--- /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..f999c6e
--- /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..1431c3d
--- /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..bdba14e
--- /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..b51b0a6
--- /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..e1ac946
--- /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..fec4d2b
--- /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..bf0e995
--- /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..1782c1c
--- /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..ea6d235
--- /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..f999c6e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_out.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..53ef509
--- /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..a20f6b2
--- /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..fa3d127
--- /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..10ae0f0
--- /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_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_off.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_bluetooth_off.png
new file mode 100644
index 0000000..6246ebe
--- /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..ec30791
--- /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..2a530f8
--- /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..9940a65
--- /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_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..10e325d
--- /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_mirroring.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_mirroring.png
new file mode 100644
index 0000000..a5f16e8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_mirroring.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..c410310
--- /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..3bd6001
--- /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..9599611
--- /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..975ac27
--- /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..3c221cf
--- /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..d75ef88
--- /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..d367585
--- /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..97b3dda
--- /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..4d49307
--- /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..6668846
--- /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..2eeff7f
--- /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..c708e00
--- /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..bfa3f12
--- /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..8302636
--- /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_signal.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_no_signal.png
new file mode 100644
index 0000000..90aa923
--- /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..889be88
--- /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..92f7fcc
--- /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..473851b
--- /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..da2fe94
--- /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..44d98be
--- /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..1a06411
--- /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..bfa3f12
--- /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..8302636
--- /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..d392496
--- /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..889be88
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_out.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-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/ic_qs_airplane_off.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_airplane_off.png
new file mode 100644
index 0000000..c05d4d6
--- /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..ef8a7eb
--- /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..475dab8
--- /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..5bceaf5
--- /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_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_off.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_bluetooth_off.png
new file mode 100644
index 0000000..1302a26
--- /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..7ac3015
--- /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..b2b563b
--- /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..b1c8753
--- /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_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..f84e614
--- /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_mirroring.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_mirroring.png
new file mode 100644
index 0000000..eb6d5a6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_mirroring.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..011a0e8
--- /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..ddf4217
--- /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..e237331
--- /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..e074dd3
--- /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..12abe5c
--- /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..8d84c6e
--- /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..0a42598
--- /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..08634e3
--- /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..10f1d09
--- /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..0dc8a58
--- /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..752c3f7
--- /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..7a14016
--- /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..af7f76d
--- /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_signal.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_no_signal.png
new file mode 100644
index 0000000..2af3c24
--- /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..a4e0243
--- /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..16193e7
--- /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..005c6c6
--- /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..a088e83
--- /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..6c2deb2
--- /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..fdb7a9b
--- /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..7a14016
--- /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..af7f76d
--- /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..66c3b92
--- /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..a4e0243
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_out.png
Binary files differ
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..4e2a265
--- /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..83dadd8
--- /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="#252725" />
+    </item>
+    <item>
+        <color android:color="#1B1D1B" />
+    </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/layout-land/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
index 00e3e27..2df9f6c 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,12 +35,6 @@
         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"
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 c8a120d..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..fbbd7e5 100644
--- a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
+++ b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
@@ -143,8 +143,13 @@
 
         <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>
@@ -269,8 +274,13 @@
 
         <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/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index d41040d..33b5dbb 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -147,8 +147,13 @@
 
         <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>
@@ -276,9 +281,14 @@
 
         <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..2dd3b9f
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings.xml
@@ -0,0 +1,53 @@
+<?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 -->
+    <ScrollView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+      <com.android.systemui.statusbar.phone.QuickSettingsContainerView
+          android:id="@+id/quick_settings_container"
+          android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+          android:paddingBottom="@dimen/quick_settings_container_padding"
+          android:paddingLeft="@dimen/quick_settings_container_padding"
+          android:paddingRight="@dimen/quick_settings_container_padding"
+          android:animateLayoutChanges="true"
+          android:columnCount="@integer/quick_settings_num_columns"
+          />
+    </ScrollView>
+    <LinearLayout android:id="@+id/handle"
+        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"
+            />
+    </LinearLayout>
+</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..5f46e96
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
@@ -0,0 +1,40 @@
+<?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"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:padding="16dp">
+
+    <ImageView
+        android:id="@+id/brightness_icon"
+        style="@style/SystemBarPanelSettingsIcon"
+        android:layout_gravity="center_vertical"
+        android:paddingRight="10dp"
+        android:src="@drawable/ic_sysbar_brightness"
+        />
+    <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..6ae10d5
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile_airplane.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/airplane_mode_textview"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:gravity="center"
+    android:text="@string/quick_settings_airplane_mode_label"
+    />
\ 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..565055c
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile_bluetooth.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/bluetooth_textview"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:gravity="center"
+    android:text="@string/quick_settings_bluetooth_label"
+    />
\ 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..ac872e6
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile_brightness.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/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"
+    android:text="@string/quick_settings_brightness_label"
+    />
\ No newline at end of file
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..4dbf6a0
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile_rotation_lock.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/rotation_lock_textview"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:gravity="center"
+    android:text="@string/quick_settings_rotation_unlocked_label"
+    />
\ 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..7026ebc
--- /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:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:gravity="center"
+    android:drawableTop="@drawable/ic_qs_settings"
+    android:text="@string/quick_settings_settings_label"
+    />
\ 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..f09e0cb
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile_time.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.
+-->
+<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">
+    <com.android.systemui.statusbar.policy.Clock
+        android:textAppearance="@style/TextAppearance.QuickSettings.Clock"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:paddingTop="3dp"
+        android:paddingBottom="3dp"
+        android:singleLine="true"
+        />
+    <com.android.systemui.statusbar.policy.QuickSettingsDateView
+        android:textAppearance="@style/TextAppearance.QuickSettings.Date"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        />
+    <TextView
+        android:textAppearance="@style/TextAppearance.QuickSettings.Alarm"
+        android:id="@+id/alarm_textview"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:paddingTop="2dp"
+        android:paddingBottom="4dp"
+        android:drawableLeft="@drawable/ic_qs_alarm_on"
+        android:drawablePadding="4dp"
+        />
+</LinearLayout>
\ No newline at end of file
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..08e8e20
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile_user.xml
@@ -0,0 +1,36 @@
+<?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: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="#33000000"
+        />
+</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..454d54a
--- /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_mirroring"
+    android:text="@string/quick_settings_wifi_display_label"
+    />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 17dbcac..f2e83d8 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -18,33 +18,29 @@
 */
 -->
 
-<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"
+    <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"
         />
 
     <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="true"
         >
 
         <include layout="@layout/status_bar_expanded_header"
@@ -65,9 +61,9 @@
         <ScrollView
             android:id="@+id/scroll"
             android:layout_width="match_parent"
-            android:layout_height="match_parent"
+            android:layout_height="wrap_content"
             android:fadingEdge="none"
-            android:overScrollMode="ifContentScrolls"
+            android:overScrollMode="always"
             >
             <com.android.systemui.statusbar.policy.NotificationRowLayout
                 android:id="@+id/latestItems"
@@ -78,19 +74,10 @@
         </ScrollView>
     </LinearLayout>
 
-    <com.android.systemui.statusbar.phone.CloseDragHandle android:id="@+id/close"
+    <View android:id="@+id/handle"
         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..60896c3 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -65,11 +65,24 @@
         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:scaleType="center"
         android:src="@drawable/ic_notify_clear"
         android:contentDescription="@string/accessibility_clear_all"
-        />            
-</LinearLayout>
\ No newline at end of file
+        />     
+</LinearLayout>
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..50643ab
--- /dev/null
+++ b/packages/SystemUI/res/layout/status_bar_recent_item.xml
@@ -0,0 +1,103 @@
+<?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/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..5e0d1e8 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"
+        android:layout_marginTop="@*android:dimen/status_bar_height"
+        >
+        <include layout="@layout/status_bar_expanded"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            />
+        <include 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..2d1bda4 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"
@@ -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_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/layout/wifi_display_dialog.xml b/packages/SystemUI/res/layout/wifi_display_dialog.xml
new file mode 100644
index 0000000..a78096e
--- /dev/null
+++ b/packages/SystemUI/res/layout/wifi_display_dialog.xml
@@ -0,0 +1,38 @@
+<?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="wrap_content"
+    android:orientation="vertical">
+
+    <ListView android:id="@+id/list"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="2" />
+
+    <Button android:id="@+id/scan"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:text="@string/wifi_display_scan" />
+
+    <Button android:id="@+id/disconnect"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:text="@string/wifi_display_disconnect" />
+</LinearLayout>
diff --git a/packages/SystemUI/res/mipmap-hdpi/ic_dreams.png b/packages/SystemUI/res/mipmap-hdpi/ic_dreams.png
new file mode 100644
index 0000000..56cbac1
--- /dev/null
+++ b/packages/SystemUI/res/mipmap-hdpi/ic_dreams.png
Binary files differ
diff --git a/packages/SystemUI/res/mipmap-mdpi/ic_dreams.png b/packages/SystemUI/res/mipmap-mdpi/ic_dreams.png
new file mode 100644
index 0000000..ea3d991
--- /dev/null
+++ b/packages/SystemUI/res/mipmap-mdpi/ic_dreams.png
Binary files differ
diff --git a/packages/SystemUI/res/mipmap-xhdpi/ic_dreams.png b/packages/SystemUI/res/mipmap-xhdpi/ic_dreams.png
new file mode 100644
index 0000000..ddc7f66
--- /dev/null
+++ b/packages/SystemUI/res/mipmap-xhdpi/ic_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..c085bc2 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Sien"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Gebruik by verstek vir hierdie USB-toestel"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Gebruik by verstek vir hierdie USB-toebehoorsel"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoem om skerm te vul"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Strek om skerm te vul"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Versoenbaarheidszoem"</string>
@@ -138,11 +144,65 @@
     <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>
+    <!-- no translation found for jelly_bean_dream_name (5992026543636816792) -->
+    <skip />
+    <!-- no translation found for start_dreams (870400522982252717) -->
+    <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_brightness_label (6968372297018755815) -->
+    <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 (4393429107095001520) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_no_network (2221993077220856376) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_label (6653501376641018614) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_no_connection_label (6255615315258869136) -->
+    <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 wifi_display_scan (8453135922233546097) -->
+    <skip />
+    <!-- no translation found for wifi_display_disconnect (5450214362789378584) -->
+    <skip />
+    <!-- no translation found for wifi_display_dialog_title (2817993038700218900) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_available (980373281442607096) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connecting (1677010908036241940) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connected (9154375061719151149) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 7c2956c..c36ac1c 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -56,8 +56,14 @@
     <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>
+    <!-- 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 />
     <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>
@@ -138,11 +144,65 @@
     <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>
+    <!-- no translation found for jelly_bean_dream_name (5992026543636816792) -->
+    <skip />
+    <!-- no translation found for start_dreams (870400522982252717) -->
+    <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_brightness_label (6968372297018755815) -->
+    <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 (4393429107095001520) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_no_network (2221993077220856376) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_label (6653501376641018614) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_no_connection_label (6255615315258869136) -->
+    <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 wifi_display_scan (8453135922233546097) -->
+    <skip />
+    <!-- no translation found for wifi_display_disconnect (5450214362789378584) -->
+    <skip />
+    <!-- no translation found for wifi_display_dialog_title (2817993038700218900) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_available (980373281442607096) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connecting (1677010908036241940) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connected (9154375061719151149) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index b2c9ab0..7292f6f 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>
@@ -138,11 +141,40 @@
     <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="870400522982252717">"بدء Dreams"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"وضع الطائرة"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- no translation found for quick_settings_battery_charged_label (8865413079414246081) -->
+    <skip />
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"بلوتوث"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"السطوع"</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="4393429107095001520">"Wifi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"لا تتوفر شبكة"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"شاشة Wifi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"لا يتوفر اتصال بشاشة 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="wifi_display_scan" msgid="8453135922233546097">"فحص"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"قطع الاتصال"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"شاشة Wifi"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"متوفرة"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"جارٍ الاتصال"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"متصلة"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index c4af8d8..8eb0479 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Прагляд"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Выкарыстоўваць налады па змаўчанні для дадзенай USB-прылады"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Выкарыстоўваць налады па змаўчанні для дадзенай USB-прылады"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Павял. на ўвесь экран"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Расцягн. на ўвесь экран"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Маштабаванне для сумяшчальнасцi"</string>
@@ -140,11 +146,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="870400522982252717">"Пачаць мары"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Рэжым палёту"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Яркасць"</string>
+    <!-- no translation found for quick_settings_ime_label (7073463064369468429) -->
+    <skip />
+    <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="4393429107095001520">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Няма сеткi"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Дысплей Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Няма падключэння да дысплея Wi-Fi"</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="wifi_display_scan" msgid="8453135922233546097">"Сканiраваць"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Адключыцца"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Дысплей Wi-Fi"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Даступна"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Падключэнне"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Падключана"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index a4a0e78..68ca044 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Преглед"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Използване по подразб. за това USB устройство"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Използване по подразб. за този аксесоар за USB"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Мащаб – запълва екрана"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Разпъване – запълва екрана"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Промяна на мащаба за съвместимост"</string>
@@ -138,11 +144,65 @@
     <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>
+    <!-- no translation found for jelly_bean_dream_name (5992026543636816792) -->
+    <skip />
+    <!-- no translation found for start_dreams (870400522982252717) -->
+    <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_brightness_label (6968372297018755815) -->
+    <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 (4393429107095001520) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_no_network (2221993077220856376) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_label (6653501376641018614) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_no_connection_label (6255615315258869136) -->
+    <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 wifi_display_scan (8453135922233546097) -->
+    <skip />
+    <!-- no translation found for wifi_display_disconnect (5450214362789378584) -->
+    <skip />
+    <!-- no translation found for wifi_display_dialog_title (2817993038700218900) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_available (980373281442607096) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connecting (1677010908036241940) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connected (9154375061719151149) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 5a2c9cd..038a9d1 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Mostra"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Utilitza de manera predet. per al dispositiu USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Utilitza de manera predet. per a l\'accessori USB"</string>
+    <string name="usb_debugging_title" msgid="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>
@@ -140,11 +143,40 @@
     <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="870400522982252717">"Comença els somnis"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mode d\'avió"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Brillantor"</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="4393429107095001520">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"No hi ha cap xarxa"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Pantalla Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"No hi ha cap connexió de pantalla Wi-Fi"</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="wifi_display_scan" msgid="8453135922233546097">"Explora"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Desconnecta"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Pantalla Wi-Fi"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Disponible"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"S\'està connectant"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Connectada"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 2d1f644..69a8ca9 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Zobrazit"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Pro toto zařízení USB použít jako výchozí"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Pro toto periferní zařízení USB použít jako výchozí"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Přiblížit na celou obrazovku"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Na celou obrazovku"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Úprava velikosti z důvodu kompatibility"</string>
@@ -140,11 +146,65 @@
     <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>
+    <!-- no translation found for jelly_bean_dream_name (5992026543636816792) -->
+    <skip />
+    <!-- no translation found for start_dreams (870400522982252717) -->
+    <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_brightness_label (6968372297018755815) -->
+    <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 (4393429107095001520) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_no_network (2221993077220856376) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_label (6653501376641018614) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_no_connection_label (6255615315258869136) -->
+    <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 wifi_display_scan (8453135922233546097) -->
+    <skip />
+    <!-- no translation found for wifi_display_disconnect (5450214362789378584) -->
+    <skip />
+    <!-- no translation found for wifi_display_dialog_title (2817993038700218900) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_available (980373281442607096) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connecting (1677010908036241940) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connected (9154375061719151149) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 01068ec..68ae9d6 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>
@@ -138,11 +141,40 @@
     <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="870400522982252717">"Start Dreams"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Flytilstand"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Lysstyrke"</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="4393429107095001520">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Intet netværk"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Wi-Fi-skærm"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Ingen forbindelse til Wi-Fi-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="wifi_display_scan" msgid="8453135922233546097">"Scan"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Afbryd forbindelsen"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Wi-Fi-skærm"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Tilgængelig"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Tilslutter"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Tilsluttet"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 011d3a3..3c71009 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -58,6 +58,12 @@
     <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>
+    <!-- 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 />
     <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>
@@ -140,11 +146,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="870400522982252717">"Träume starten"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Flugmodus"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Helligkeit"</string>
+    <!-- no translation found for quick_settings_ime_label (7073463064369468429) -->
+    <skip />
+    <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="4393429107095001520">"WLAN"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Kein Netzwerk"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"WLAN-Anzeige"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Keine Verbindung zur WLAN-Anzeige"</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="wifi_display_scan" msgid="8453135922233546097">"Scannen"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Trennen"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"WLAN-Anzeige"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Verfügbar"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Verbinden"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Verbunden"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 0b87777..02a52fa 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>
@@ -140,11 +143,40 @@
     <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="870400522982252717">"Ενεργ. λειτ. dreams"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Λειτουργία πτήσης"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Φωτεινότητα"</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="4393429107095001520">"Wifi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Κανένα δίκτυο"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Οθόνη Wifi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Δεν υπάρχει σύνδεση οθόνης 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="wifi_display_scan" msgid="8453135922233546097">"Σάρωση"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Αποσύνδεση"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Οθόνη Wifi"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Διαθέσιμη"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Σύνδεση"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Έχει συνδεθεί"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index f02d09ca..0a8226e 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>
@@ -138,11 +141,40 @@
     <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="870400522982252717">"Start dreams"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Aeroplane mode"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Brightness"</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="4393429107095001520">"Wifi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"No Network"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Wifi Display"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"No Wifi Display Connection"</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="wifi_display_scan" msgid="8453135922233546097">"Scan"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Disconnect"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Wifi Display"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Available"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Connecting"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Connected"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index be2bf6e..af5a514 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Ver"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Se usa de forma predeterminada para este dispositivo USB."</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Se usa de forma predeterminada para este accesorio USB."</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom para ocupar la pantalla"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Estirar p/ ocupar la pantalla"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilidad"</string>
@@ -140,11 +146,65 @@
     <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>
+    <!-- no translation found for jelly_bean_dream_name (5992026543636816792) -->
+    <skip />
+    <!-- no translation found for start_dreams (870400522982252717) -->
+    <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_brightness_label (6968372297018755815) -->
+    <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 (4393429107095001520) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_no_network (2221993077220856376) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_label (6653501376641018614) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_no_connection_label (6255615315258869136) -->
+    <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 wifi_display_scan (8453135922233546097) -->
+    <skip />
+    <!-- no translation found for wifi_display_disconnect (5450214362789378584) -->
+    <skip />
+    <!-- no translation found for wifi_display_dialog_title (2817993038700218900) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_available (980373281442607096) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connecting (1677010908036241940) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connected (9154375061719151149) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index afbceff..d5f5d40 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>
@@ -138,11 +141,40 @@
     <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="870400522982252717">"Iniciar Dreams"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modo avión"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Brillo"</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="4393429107095001520">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"No hay red."</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Pantalla Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Sin conexión a pantalla Wi-Fi"</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="wifi_display_scan" msgid="8453135922233546097">"Escanear"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Desconectar"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Pantalla Wi-Fi"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Disponible"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Conectando..."</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Conectada"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 318ed04..e9632ec 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Kuva"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Kasuta vaikimisi selle USB-seadme jaoks"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Vaikimisi kasuta seda USB-lisaseadet"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Suumi ekraani täitmiseks"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Venita ekraani täitmiseks"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Sobivussuum"</string>
@@ -138,11 +144,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="870400522982252717">"Käivita unerežiim"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Lennurežiim"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Heledus"</string>
+    <!-- no translation found for quick_settings_ime_label (7073463064369468429) -->
+    <skip />
+    <string name="quick_settings_location_label" msgid="3292451598267467545">"Kasutatav asukoht"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Meediumiseade"</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="4393429107095001520">"WiFi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Võrku pole"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"WiFi-kuva"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"WiFi-kuva ühendus puudub"</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="wifi_display_scan" msgid="8453135922233546097">"Skannimine"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Katkesta ühendus"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"WiFi-kuva"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Saadaval"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Ühendamine"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Ühendatud"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 104ab038..1251c8f 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,11 +33,11 @@
   </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>
@@ -45,23 +45,29 @@
     <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_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>
+    <!-- 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 />
     <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 +75,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>
@@ -138,11 +144,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="870400522982252717">"شروع رؤیاها"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"حالت هواپیما"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- no translation found for quick_settings_battery_charged_label (8865413079414246081) -->
+    <skip />
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"بلوتوث"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"روشنایی"</string>
+    <!-- no translation found for quick_settings_ime_label (7073463064369468429) -->
+    <skip />
+    <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="4393429107095001520">"Wifi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"شبکه‌ای موجود نیست"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"صفحه نمایش Wifi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"اتصال صفحه نمایش 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="wifi_display_scan" msgid="8453135922233546097">"اسکن"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"قطع اتصال"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"صفحه نمایش Wifi"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"در دسترس"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"در حال اتصال"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"متصل"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index a4229b4..09a6eaf 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -58,6 +58,12 @@
     <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>
+    <!-- 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 />
     <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>
@@ -138,11 +144,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="870400522982252717">"Aloita unelmointi"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Lentokonetila"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Kirkkaus"</string>
+    <!-- no translation found for quick_settings_ime_label (7073463064369468429) -->
+    <skip />
+    <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="4393429107095001520">"Wifi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ei verkkoa"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Wifi-näyttö"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Ei yhteyttä wifi-näyttöön"</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="wifi_display_scan" msgid="8453135922233546097">"Etsi"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Katkaise yhteys"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Wifi-näyttö"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Käytettävissä"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Yhdistetään"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Yhdistetty"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 30b3539..e699c640 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Afficher"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Utiliser par défaut pour ce périphérique USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Utiliser par défaut pour cet accessoire USB"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoomer pour remplir l\'écran"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Étirer pour remplir l\'écran"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilité"</string>
@@ -135,16 +141,46 @@
     <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="870400522982252717">"Lancer Rêves"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mode avion"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Luminosité"</string>
+    <!-- no translation found for quick_settings_ime_label (7073463064369468429) -->
+    <skip />
+    <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="4393429107095001520">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Aucun réseau"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Écran Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Aucune connexion à un écran Wi-Fi"</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="wifi_display_scan" msgid="8453135922233546097">"Rechercher"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Déconnecter"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Écran Wi-Fi"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Disponible"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Connexion en cours…"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Connecté"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index aae070a..f49eaf1 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"देखें"</string>
     <string name="always_use_device" msgid="1450287437017315906">"इस USB उपकरण के लिए डिफ़ॉल्‍ट रूप से उपयोग करें"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"इस USB एसेसरी के लिए डिफ़ॉल्‍ट रूप से उपयोग करें"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"स्‍क्रीन भरने हेतु ज़ूम करें"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"स्‍क्रीन को भरने के लिए खींचें"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"संगतता ज़ूम"</string>
@@ -138,11 +144,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="870400522982252717">"dreams प्रारंभ करें"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"हवाई जहाज़ मोड"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"चमक"</string>
+    <!-- no translation found for quick_settings_ime_label (7073463064369468429) -->
+    <skip />
+    <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="4393429107095001520">"Wifi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"कोई नेटवर्क नहीं"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Wifi डिस्प्ले"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"कोई 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="wifi_display_scan" msgid="8453135922233546097">"स्कैन करें"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"डिस्कनेक्ट करें"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Wifi डिस्प्ले"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"उपलब्ध"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"कनेक्ट हो रहा है"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"कनेक्ट किया गया"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 4a1f35a..405fe2c 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Prikaži"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Koristi se prema zadanim postavkama za ovaj USB uređaj"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Koristi se prema zadanim postavkama za ovaj USB pribor"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Zumiraj i ispuni zaslon"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Rastegni i ispuni zaslon"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Kompatibilno zumiranje"</string>
@@ -138,11 +144,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="870400522982252717">"Počni sanjati"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Način rada u zrakoplovu"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Svjetlina"</string>
+    <!-- no translation found for quick_settings_ime_label (7073463064369468429) -->
+    <skip />
+    <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="4393429107095001520">"Wifi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nema mreže"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"WiFi zaslon"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Nema veze s Wifi zaslonom"</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="wifi_display_scan" msgid="8453135922233546097">"Skeniraj"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Isključi"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"WiFi zaslon"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Dostupan"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Povezivanje"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Povezan"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 2ea0f76..c77a0d8 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Megtekintés"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Alapértelmezett használat ehhez az USB-eszközhöz"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Alapértelmezett használat ehhez az USB-kiegészítőhöz"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Nagyítás a kitöltéshez"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Nyújtás kitöltéshez"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Kompatibilitás -- nagyítás/kicsinyítés"</string>
@@ -138,11 +144,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="870400522982252717">"Álmok indítása"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Repülőgép üzemmód"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Fényerő"</string>
+    <!-- no translation found for quick_settings_ime_label (7073463064369468429) -->
+    <skip />
+    <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="4393429107095001520">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nincs hálózat"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Wi-Fi kijelző"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Nincs kapcsolat Wi-Fi kijelzővel"</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="wifi_display_scan" msgid="8453135922233546097">"Keresés"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Szétkapcsol"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Wi-Fi kijelző"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Rendelkezésre álló"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Kapcsolódás"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Kapcsolatban"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index a69fc23..f425b88 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -58,6 +58,12 @@
     <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>
+    <!-- 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 />
     <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>
@@ -138,11 +144,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="870400522982252717">"Mulai mimpi"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mode pesawat"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Kecerahan"</string>
+    <!-- no translation found for quick_settings_ime_label (7073463064369468429) -->
+    <skip />
+    <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="4393429107095001520">"Wifi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Tidak Ada Jaringan"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Tampilan Wifi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Tidak Ada Koneksi Tampilan Wifi"</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="wifi_display_scan" msgid="8453135922233546097">"Pindai"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Putuskan"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Tampilan Wifi"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Tersedia"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Menghubungkan"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Terhubung"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 432d984..3a421a8 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>
@@ -140,11 +143,40 @@
     <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="870400522982252717">"Avvia Dreams"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modalità aereo"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Luminosità"</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="4393429107095001520">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nessuna rete"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Schermo Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Nessun collegamento a schermi Wi-Fi"</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="wifi_display_scan" msgid="8453135922233546097">"Scansione"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Disconnetti"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Schermo Wi-Fi"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Disponibile"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Collegamento"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Collegato"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index bdc84b6..7c90447 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>
@@ -138,11 +141,40 @@
     <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="870400522982252717">"הפעל את Dreams"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"מצב טיסה"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"בהירות"</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="4393429107095001520">"Wifi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"אין רשת"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"תצוגת Wifi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"אין חיבור תצוגת 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="wifi_display_scan" msgid="8453135922233546097">"סרוק"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"נתק"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"תצוגת Wifi"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"זמין"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"מתחבר"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"מחובר"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 70ba034..3226f94 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"表示"</string>
     <string name="always_use_device" msgid="1450287437017315906">"このUSBデバイスにデフォルトで使用する"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"このUSBアクセサリにデフォルトで使用する"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"画面サイズに合わせて拡大"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"画面サイズに合わせて拡大"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"互換ズーム"</string>
@@ -65,7 +71,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>
@@ -140,11 +146,65 @@
     <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>
+    <!-- no translation found for jelly_bean_dream_name (5992026543636816792) -->
+    <skip />
+    <!-- no translation found for start_dreams (870400522982252717) -->
+    <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_brightness_label (6968372297018755815) -->
+    <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 (4393429107095001520) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_no_network (2221993077220856376) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_label (6653501376641018614) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_no_connection_label (6255615315258869136) -->
+    <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 wifi_display_scan (8453135922233546097) -->
+    <skip />
+    <!-- no translation found for wifi_display_disconnect (5450214362789378584) -->
+    <skip />
+    <!-- no translation found for wifi_display_dialog_title (2817993038700218900) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_available (980373281442607096) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connecting (1677010908036241940) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connected (9154375061719151149) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index e54b06c..35adf62 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"보기"</string>
     <string name="always_use_device" msgid="1450287437017315906">"이 USB 기기에 기본값으로 사용"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"이 USB 액세서리에 기본값으로 사용"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"전체화면 모드로 확대"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"전체화면 모드로 확대"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"호환성 확대/축소"</string>
@@ -138,11 +144,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="870400522982252717">"화면보호기 시작"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"비행기 모드"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- no translation found for quick_settings_battery_charged_label (8865413079414246081) -->
+    <skip />
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"블루투스"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"밝기"</string>
+    <!-- no translation found for quick_settings_ime_label (7073463064369468429) -->
+    <skip />
+    <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="4393429107095001520">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"네트워크가 연결되지 않음"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Wi-Fi 디스플레이"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Wi-Fi 디스플레이가 연결되지 않음"</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="wifi_display_scan" msgid="8453135922233546097">"검색"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"연결 해제"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Wi-Fi 디스플레이"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"사용 가능"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"연결 중"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"연결됨"</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-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 018b5e5..b0a0008 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Žiūrėti"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Šiam USB įreng. naudoti pagal numat. nustatymus"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Šiam USB priedui naudoti pagal numat. nustatymus"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Keisti mast., kad atit. ekr."</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Ištempti, kad atit. ekr."</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Suderinamumo mastelio keitimas"</string>
@@ -138,11 +144,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="870400522982252717">"Paleisti vizijas"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Lėktuvo režimas"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Skaistis"</string>
+    <!-- no translation found for quick_settings_ime_label (7073463064369468429) -->
+    <skip />
+    <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="4393429107095001520">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Tinklo nėra"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"„Wi-Fi“ pateiktis"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Nėra „Wi-Fi“ pateikties ryšio"</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="wifi_display_scan" msgid="8453135922233546097">"Nuskaityti"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Atjungti"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"„Wi-Fi“ pateiktis"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Pasiekiama"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Jungiama"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Prijungta"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index e708804..7578385 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Skatīt"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Pēc noklusējuma izmantot šai USB ierīcei"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Pēc noklusējuma izmantot šim USB piederumam"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Tālumm., lai aizp. ekr."</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Stiepiet, lai aizp. ekr."</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Saderības tālummaiņa"</string>
@@ -138,11 +144,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="870400522982252717">"Palaist Dreams"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Lidojuma režīms"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Spilgtums"</string>
+    <!-- no translation found for quick_settings_ime_label (7073463064369468429) -->
+    <skip />
+    <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="4393429107095001520">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nav tīkla"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Wi-Fi displejs"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Nav Wi-Fi displeja savienojuma"</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="wifi_display_scan" msgid="8453135922233546097">"Meklēt"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Atvienot"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Wi-Fi displejs"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Pieejams"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Notiek savienojuma izveide"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Savienots"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 3265cd5..2a6d4ed 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Lihat"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Gunakan secara lalai untuk peranti USB ini"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Gunakan secara lalai untuk aksesori USB ini"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Zum untuk memenuhi skrin"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Regang utk memenuhi skrin"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zum keserasian"</string>
@@ -138,11 +144,65 @@
     <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>
+    <!-- no translation found for jelly_bean_dream_name (5992026543636816792) -->
+    <skip />
+    <!-- no translation found for start_dreams (870400522982252717) -->
+    <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_brightness_label (6968372297018755815) -->
+    <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 (4393429107095001520) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_no_network (2221993077220856376) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_label (6653501376641018614) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_no_connection_label (6255615315258869136) -->
+    <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 wifi_display_scan (8453135922233546097) -->
+    <skip />
+    <!-- no translation found for wifi_display_disconnect (5450214362789378584) -->
+    <skip />
+    <!-- no translation found for wifi_display_dialog_title (2817993038700218900) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_available (980373281442607096) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connecting (1677010908036241940) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connected (9154375061719151149) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index a1ee469..be6daa0 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>
@@ -138,11 +141,40 @@
     <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="870400522982252717">"Start drømmemodus"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Flymodus"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Lysstyrke"</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="4393429107095001520">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ingen nettverk"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Wi-Fi-skjermer"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Ingen tilkobling for Wi-Fi-skjermer"</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="wifi_display_scan" msgid="8453135922233546097">"Skann"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Koble fra"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Wi-Fi-skjerm"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Tilgjengelig"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Kobler til"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Tilkoblet"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 936e0958..d605c4c 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>
@@ -138,11 +141,40 @@
     <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="870400522982252717">"Dromen starten"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Vliegmodus"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Helderheid"</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="4393429107095001520">"Wifi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Geen netwerk"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Wifi-display"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Geen wifi-displayverbinding"</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="wifi_display_scan" msgid="8453135922233546097">"Scannen"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Verbinding verbreken"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Wifi-display"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Beschikbaar"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Verbinding maken"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Verbonden"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index b4a77a2..d3a5fec 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Wyświetl"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Używaj domyślnie dla tego urządzenia USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Używaj domyślnie dla tego akcesorium USB"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Powiększ, aby wypełnić ekran"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Rozciągnij, aby wypełnić ekran"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Powiększenie w trybie zgodności"</string>
@@ -138,11 +144,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="870400522982252717">"Zacznij śnić"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Tryb samolotowy"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Jasność"</string>
+    <!-- no translation found for quick_settings_ime_label (7073463064369468429) -->
+    <skip />
+    <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="4393429107095001520">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Brak sieci"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Wyświetlacz Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Brak połączenia z wyświetlaczem Wi-Fi"</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="wifi_display_scan" msgid="8453135922233546097">"Skanuj"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Rozłącz"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Wyświetlacz Wi-Fi"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Dostępny"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Łączenie"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Połączony"</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..ebd673d 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>
@@ -138,11 +141,64 @@
     <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>
+    <!-- no translation found for jelly_bean_dream_name (5992026543636816792) -->
+    <skip />
+    <!-- no translation found for start_dreams (870400522982252717) -->
+    <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_brightness_label (6968372297018755815) -->
+    <skip />
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Método de Introdução"</string>
+    <!-- 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 (4393429107095001520) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_no_network (2221993077220856376) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_label (6653501376641018614) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_no_connection_label (6255615315258869136) -->
+    <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 wifi_display_scan (8453135922233546097) -->
+    <skip />
+    <!-- no translation found for wifi_display_disconnect (5450214362789378584) -->
+    <skip />
+    <!-- no translation found for wifi_display_dialog_title (2817993038700218900) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_available (980373281442607096) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connecting (1677010908036241940) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connected (9154375061719151149) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 596ceec..889c96c 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Visualizar"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Usar por padrão para este dispositivo USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Usar por padrão para este acessório USB"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom p/ preencher a tela"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Ampliar p/ preencher tela"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom em modo de compatibilidade"</string>
@@ -140,11 +146,65 @@
     <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>
+    <!-- no translation found for jelly_bean_dream_name (5992026543636816792) -->
+    <skip />
+    <!-- no translation found for start_dreams (870400522982252717) -->
+    <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_brightness_label (6968372297018755815) -->
+    <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 (4393429107095001520) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_no_network (2221993077220856376) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_label (6653501376641018614) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_no_connection_label (6255615315258869136) -->
+    <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 wifi_display_scan (8453135922233546097) -->
+    <skip />
+    <!-- no translation found for wifi_display_disconnect (5450214362789378584) -->
+    <skip />
+    <!-- no translation found for wifi_display_dialog_title (2817993038700218900) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_available (980373281442607096) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connecting (1677010908036241940) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connected (9154375061719151149) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 16e5719..2e3570f 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) -->
@@ -246,10 +252,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 +266,58 @@
     <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 (870400522982252717) -->
+    <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_brightness_label (6968372297018755815) -->
+    <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 (4393429107095001520) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_no_network (2221993077220856376) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_label (6653501376641018614) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_no_connection_label (6255615315258869136) -->
+    <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 wifi_display_scan (8453135922233546097) -->
+    <skip />
+    <!-- no translation found for wifi_display_disconnect (5450214362789378584) -->
+    <skip />
+    <!-- no translation found for wifi_display_dialog_title (2817993038700218900) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_available (980373281442607096) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connecting (1677010908036241940) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connected (9154375061719151149) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 87eec9f..73e41d2 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Afişaţi"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Utilizaţi în mod prestabilit pt. acest dispoz. USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Utiliz. în mod prestabilit pt. acest accesoriu USB"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom pt. a umple ecranul"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Înt. pt. a umple ecranul"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilitate"</string>
@@ -138,11 +144,65 @@
     <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>
+    <!-- no translation found for jelly_bean_dream_name (5992026543636816792) -->
+    <skip />
+    <!-- no translation found for start_dreams (870400522982252717) -->
+    <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_brightness_label (6968372297018755815) -->
+    <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 (4393429107095001520) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_no_network (2221993077220856376) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_label (6653501376641018614) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_no_connection_label (6255615315258869136) -->
+    <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 wifi_display_scan (8453135922233546097) -->
+    <skip />
+    <!-- no translation found for wifi_display_disconnect (5450214362789378584) -->
+    <skip />
+    <!-- no translation found for wifi_display_dialog_title (2817993038700218900) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_available (980373281442607096) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connecting (1677010908036241940) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connected (9154375061719151149) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 7a7d08f..4841a31 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -25,7 +25,7 @@
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Показать уведомления"</string>
     <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Удаление из списка"</string>
     <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"О приложении"</string>
-    <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"Нет данных"</string>
+    <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"В последнее время вы не запускали приложения."</string>
     <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Закрыть недавние приложения"</string>
   <plurals name="status_bar_accessibility_recent_apps">
     <item quantity="one" msgid="5854176083865845541">"Недавних приложений: 1"</item>
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Просмотр"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Использовать по умолчанию для этого USB-устройства"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Использовать по умолчанию для этого USB-аксессуара"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Подогнать по размерам экрана"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Растянуть на весь экран"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Масштаб и совместимость"</string>
@@ -135,16 +141,46 @@
     <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="870400522982252717">"Включить заставку"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Режим полета"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Яркость"</string>
+    <!-- no translation found for quick_settings_ime_label (7073463064369468429) -->
+    <skip />
+    <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="4393429107095001520">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Нет сети"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Экраны, подключенные через Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Экран не подключен"</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="wifi_display_scan" msgid="8453135922233546097">"Искать"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Отключить"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Подключенный экран"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Доступен"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Подключение…"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Подключен"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 8e64487..4d8a527 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Zobraziť"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Pre toto zariadenie USB použiť ako predvolené"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Pre toto periférne zar. USB použiť ako predvolené"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Priblížiť na celú obrazovku"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Na celú obrazovku"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Úprava veľkosti z dôvodu kompatibility"</string>
@@ -140,11 +146,65 @@
     <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>
+    <!-- no translation found for jelly_bean_dream_name (5992026543636816792) -->
+    <skip />
+    <!-- no translation found for start_dreams (870400522982252717) -->
+    <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_brightness_label (6968372297018755815) -->
+    <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 (4393429107095001520) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_no_network (2221993077220856376) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_label (6653501376641018614) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_no_connection_label (6255615315258869136) -->
+    <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 wifi_display_scan (8453135922233546097) -->
+    <skip />
+    <!-- no translation found for wifi_display_disconnect (5450214362789378584) -->
+    <skip />
+    <!-- no translation found for wifi_display_dialog_title (2817993038700218900) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_available (980373281442607096) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connecting (1677010908036241940) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connected (9154375061719151149) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 1fa3b21..b0e4ae4 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -58,6 +58,12 @@
     <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>
+    <!-- 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 />
     <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>
@@ -138,11 +144,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="870400522982252717">"Začni sanje"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Način za letalo"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Svetlost"</string>
+    <!-- no translation found for quick_settings_ime_label (7073463064369468429) -->
+    <skip />
+    <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="4393429107095001520">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ni omrežja"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Zaslon Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Ni povezav z zaslonom Wi-Fi"</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="wifi_display_scan" msgid="8453135922233546097">"Išči"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Prek. povezavo"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Zaslon Wi-Fi"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Na voljo"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Vzpostavljanje povezave"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Povezava vzpostavljena"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index fd41e02..9eb07ed 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Прикажи"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Користи подразумевано за овај USB уређај"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Користи подразумевано за овај USB додатак"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Зумирај на целом екрану"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Развуци на цео екран"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Компатибилно зумирање"</string>
@@ -138,11 +144,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="870400522982252717">"Покрени Dreams"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Режим рада у авиону"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Осветљеност"</string>
+    <!-- no translation found for quick_settings_ime_label (7073463064369468429) -->
+    <skip />
+    <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="4393429107095001520">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Нема мреже"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Wi-Fi екран"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Нема везе са Wi-Fi екраном"</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="wifi_display_scan" msgid="8453135922233546097">"Скенирај"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Прекини везу"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Wi-Fi екран"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Доступан"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Повезивање"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Повезан"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index afbe0fb..67d3744 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>
@@ -138,11 +141,40 @@
     <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="870400522982252717">"Starta drömmar"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Flygplansläge"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Ljusstyrka"</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="4393429107095001520">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Inget nätverk"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Wi-Fi-skärm"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Ingen anslutning till Wi-Fi-skärm"</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="wifi_display_scan" msgid="8453135922233546097">"Skanna"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Koppla från"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Wi-Fi-skärm"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Tillgänglig"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Ansluter"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Ansluten"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 8f22b81c..b666b12 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,11 +51,14 @@
     <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">"Kila wakati ruhusu kutoka kwenye kompyuta hii"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Kuza ili kujaza skrini"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Tanua ili kujaza skrini"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Kukuza kwa Utangamanifu"</string>
@@ -136,11 +139,40 @@
     <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="870400522982252717">"Anza ndoto"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modi ya ndege"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Ung\'avu"</string>
+    <string name="quick_settings_ime_label" msgid="7073463064369468429">"Mbinu Ingizo"</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="4393429107095001520">"Wifi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Hakuna Mtandao"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Onyesho la Wifi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Hakuna Muunganisho wa Onyesho la Wifi"</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="wifi_display_scan" msgid="8453135922233546097">"Changanua"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Kata muunganisho"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Onyesho la Wifi"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Inapatikana"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Inaunganisha"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Umeunganishwa"</string>
 </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..209ad11
--- /dev/null
+++ b/packages/SystemUI/res/values-sw600dp/config.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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources>
+    <!-- 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>
+</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 2b5248f..b6faff3 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>
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..a61fd68 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
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..37be5c9 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"ดู"</string>
     <string name="always_use_device" msgid="1450287437017315906">"ใช้ค่าเริ่มต้นสำหรับอุปกรณ์ USB นี้"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"ใช้ค่าเริ่มต้นสำหรับอุปกรณ์เสริม USB นี้"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"ขยายจนเต็มหน้าจอ"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"ยืดจนเต็มหน้าจอ"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"ความเข้ากันได้ของการย่อ/ขยาย"</string>
@@ -138,11 +144,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="870400522982252717">"เริ่ม Dreams"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"โหมดใช้งานบนเครื่องบิน"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- no translation found for quick_settings_battery_charged_label (8865413079414246081) -->
+    <skip />
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"บลูทูธ"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"ความสว่าง"</string>
+    <!-- no translation found for quick_settings_ime_label (7073463064369468429) -->
+    <skip />
+    <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="4393429107095001520">"WiFi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ไม่มีเครือข่าย"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"การแสดงผลด้วย WiFi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"ไม่มีการเชื่อมต่อการแสดงผลด้วย 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="wifi_display_scan" msgid="8453135922233546097">"สแกน"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"เลิกต่อ"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"การแสดงผลด้วย WiFi"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"มีอยู่"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"กำลังเชื่อมต่อ"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"เชื่อมต่อแล้ว"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index e1c4185..30b214a 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Tingnan"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Gamitin bilang default para sa USB device"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Gamitin bilang default sa USB accessory na ito"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"I-zoom upang punan screen"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"I-stretch upang mapuno screen"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom sa pagiging Tugma"</string>
@@ -138,11 +144,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="870400522982252717">"Simulan panaginip"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Airplane mode"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Brightness"</string>
+    <!-- no translation found for quick_settings_ime_label (7073463064369468429) -->
+    <skip />
+    <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="4393429107095001520">"Wifi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Walang Network"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Wifi Display"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Walang Koneksyon sa Wifi 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="wifi_display_scan" msgid="8453135922233546097">"I-scan"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Idiskonekta"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Wifi Display"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Available"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Kumukonekta"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Nakakonekta"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 9bf8f76..cd390d3 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Görüntüle"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Bu USB cihazı için varsayılan olarak kullan"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Bu USB aksesuar için varsayılan olarak kullan"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Yakınlaştır (ekranı kaplasın)"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Genişlet (ekran kapansın)"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Uyumluluk yakınlaştırması"</string>
@@ -138,11 +144,65 @@
     <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>
+    <!-- no translation found for jelly_bean_dream_name (5992026543636816792) -->
+    <skip />
+    <!-- no translation found for start_dreams (870400522982252717) -->
+    <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_brightness_label (6968372297018755815) -->
+    <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 (4393429107095001520) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_no_network (2221993077220856376) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_label (6653501376641018614) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_no_connection_label (6255615315258869136) -->
+    <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 wifi_display_scan (8453135922233546097) -->
+    <skip />
+    <!-- no translation found for wifi_display_disconnect (5450214362789378584) -->
+    <skip />
+    <!-- no translation found for wifi_display_dialog_title (2817993038700218900) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_available (980373281442607096) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connecting (1677010908036241940) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connected (9154375061719151149) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 165baae..0e708c8 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>
@@ -138,11 +141,40 @@
     <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="870400522982252717">"Увімкнути Dreams"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Режим польоту"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- 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_brightness_label" msgid="6968372297018755815">"Яскравість"</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="4393429107095001520">"Wi-Fi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Немає мережі"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Екран Wi-Fi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Немає з’єднання з екраном Wi-Fi"</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="wifi_display_scan" msgid="8453135922233546097">"Сканувати"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Від’єднати"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Екран Wi-Fi"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Доступний"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Під’єднання"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Під’єднаний"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index eef2c83..267dcb6 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Xem"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Sử dụng theo mặc định cho thiết bị USB này"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Sử dụng theo mặc định cho phụ kiện USB này"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"T.phóng để lấp đầy m.hình"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Giãn ra để lấp đầy m.hình"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Thu phóng tương thích"</string>
@@ -138,11 +144,65 @@
     <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>
+    <!-- no translation found for jelly_bean_dream_name (5992026543636816792) -->
+    <skip />
+    <!-- no translation found for start_dreams (870400522982252717) -->
+    <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_brightness_label (6968372297018755815) -->
+    <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 (4393429107095001520) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_no_network (2221993077220856376) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_label (6653501376641018614) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_no_connection_label (6255615315258869136) -->
+    <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 wifi_display_scan (8453135922233546097) -->
+    <skip />
+    <!-- no translation found for wifi_display_disconnect (5450214362789378584) -->
+    <skip />
+    <!-- no translation found for wifi_display_dialog_title (2817993038700218900) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_available (980373281442607096) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connecting (1677010908036241940) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connected (9154375061719151149) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index ca29738..c8e860a 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"查看"</string>
     <string name="always_use_device" msgid="1450287437017315906">"默认情况下用于该 USB 设备"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"默认情况下用于该 USB 配件"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"缩放以填满屏幕"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"拉伸以填满屏幕"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"兼容性缩放"</string>
@@ -140,11 +146,65 @@
     <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>
+    <!-- no translation found for jelly_bean_dream_name (5992026543636816792) -->
+    <skip />
+    <!-- no translation found for start_dreams (870400522982252717) -->
+    <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_brightness_label (6968372297018755815) -->
+    <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 (4393429107095001520) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_no_network (2221993077220856376) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_label (6653501376641018614) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_display_no_connection_label (6255615315258869136) -->
+    <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 wifi_display_scan (8453135922233546097) -->
+    <skip />
+    <!-- no translation found for wifi_display_disconnect (5450214362789378584) -->
+    <skip />
+    <!-- no translation found for wifi_display_dialog_title (2817993038700218900) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_available (980373281442607096) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connecting (1677010908036241940) -->
+    <skip />
+    <!-- no translation found for wifi_display_state_connected (9154375061719151149) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 8fa4af9..5f9877e 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -58,12 +58,18 @@
     <string name="label_view" msgid="6304565553218192990">"查看"</string>
     <string name="always_use_device" msgid="1450287437017315906">"預設用於這個 USB 裝置"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"預設用於這個 USB 配件"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"放大為全螢幕"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"放大為全螢幕"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"相容性縮放"</string>
     <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>
@@ -140,11 +146,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="870400522982252717">"啟動 Dream"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"飛航模式"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- no translation found for quick_settings_battery_charged_label (8865413079414246081) -->
+    <skip />
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"藍牙"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"亮度"</string>
+    <!-- no translation found for quick_settings_ime_label (7073463064369468429) -->
+    <skip />
+    <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="4393429107095001520">"WiFi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"沒有網路"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"WiFi Display"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"未連接 WiFi Display"</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="wifi_display_scan" msgid="8453135922233546097">"掃描"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"中斷連線"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"WiFi Display"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"可以使用"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"連線中"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"已連線"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 4f3e787..f1c5770 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Buka"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Sebenzisa ngokuzenzakalelayo yale divayisi ye-USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Sebenzisa ngokuzenzakalelayo kule-accessory ye-USB"</string>
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Sondeza ukugcwalisa isikrini"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Nweba ukugcwalisa isikrini"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Ukuhambelana Kokusondeza"</string>
@@ -138,11 +144,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="870400522982252717">"Qala amaphupho"</string>
+    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Isimo sendiza"</string>
+    <!-- no translation found for quick_settings_battery_charging_label (490074774465309209) -->
+    <skip />
+    <!-- no translation found for quick_settings_battery_charged_label (8865413079414246081) -->
+    <skip />
+    <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"I-Bluetooth"</string>
+    <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Ukugqama"</string>
+    <!-- no translation found for quick_settings_ime_label (7073463064369468429) -->
+    <skip />
+    <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="4393429107095001520">"I-WiFi"</string>
+    <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ayikho inethiwekhi"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6653501376641018614">"Ukubuka kwe-Wifi"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="6255615315258869136">"Alukho uxhumo lokubonisa le-Wifi"</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="wifi_display_scan" msgid="8453135922233546097">"Skena"</string>
+    <string name="wifi_display_disconnect" msgid="5450214362789378584">"Nqamula"</string>
+    <string name="wifi_display_dialog_title" msgid="2817993038700218900">"Ukubuka kwe-Wifi"</string>
+    <string name="wifi_display_state_available" msgid="980373281442607096">"Kuyatholakala"</string>
+    <string name="wifi_display_state_connecting" msgid="1677010908036241940">"Iyaxhuma"</string>
+    <string name="wifi_display_state_connected" msgid="9154375061719151149">"Ixhunyiwe"</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..19b64ba 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -33,4 +33,5 @@
     <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..1edc3fc 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -67,6 +67,28 @@
     <integer translatable="false" name="config_search_panel_view_vibration_duration">20</integer>
 
     <!-- The length of the vibration when the notificaiotn pops open. -->
-    <integer name="blinds_pop_duration_ms">10</integer>
+    <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>
 </resources>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index c6fd66a..63ce2a9 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,20 @@
     <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>
+    <!-- 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 +63,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>
@@ -144,16 +161,27 @@
     <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>
+
+    <!-- Quick settings panels minimum fling open target width. -->
+    <dimen name="settings_panel_fling_gutter">90dp</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 -->
-    <dimen name="blinds_pop_threshold">32dp</dimen>
+    <dimen name="one_finger_pop_limit">32dp</dimen>
 
-    <!-- The size of the gesture span needed to activate the "pull" notification expansion -->
-    <dimen name="pull_span_min">25dp</dimen>
+    <!-- The amount of padding around the QuickSettings tiles -->
+    <dimen name="quick_settings_container_padding">12dp</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">5dp</dimen>
+
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index f18e33e..cbd9957 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>
@@ -363,13 +372,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 +394,73 @@
 
     <!-- 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">Start dreams</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: 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">Wifi</string>
+    <!-- QuickSettings: Wifi (No network) [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_wifi_no_network">No Network</string>
+    <!-- QuickSettings: Wifi display [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_wifi_display_label">Wifi Display</string>
+    <!-- QuickSettings: Wifi display [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_wifi_display_no_connection_label">No Wifi Display Connection</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>
+
+    <!-- Wifi display: Scan button text [CHAR LIMIT=15] -->
+    <string name="wifi_display_scan">Scan</string>
+
+    <!-- Wifi display: Disconnect button text [CHAR LIMIT=15] -->
+    <string name="wifi_display_disconnect">Disconnect</string>
+
+    <!-- Wifi display: Quick setting dialog title [CHAR LIMIT=30] -->
+    <string name="wifi_display_dialog_title">Wifi Display</string>
+
+    <!-- Wifi display: Subtitle text shown to indicate that a display is available [CHAR LIMIT=30] -->
+    <string name="wifi_display_state_available">Available</string>
+
+    <!-- Wifi display: Subtitle text shown to indicate that a display is connecting [CHAR LIMIT=30] -->
+    <string name="wifi_display_state_connecting">Connecting</string>
+
+    <!-- Wifi display: Subtitle text shown to indicate that a display is connected [CHAR LIMIT=30] -->
+    <string name="wifi_display_state_connected">Connected</string>
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 2564003..738b41f 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -70,6 +70,36 @@
     <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">#ff8d908c</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="Animation" />
 
     <style name="Animation.ShirtPocketPanel">
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..12e45c7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/BeanBagDream.java
@@ -0,0 +1,31 @@
+package com.android.systemui;
+
+import android.service.dreams.Dream;
+
+import com.android.systemui.BeanBag.Board;
+
+public class BeanBagDream extends Dream {
+
+    private Board mBoard;
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        setInteractive(true);
+        mBoard = new Board(this, null);
+    }
+
+    @Override
+    public void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        setContentView(mBoard);
+        lightsOut();
+        mBoard.startAnimation();
+    }
+
+    @Override
+    public void finish() {
+        mBoard.stopAnimation();
+        super.finish();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index dcfd0b3..674d9a3 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -50,7 +50,7 @@
     private static final long EXPAND_DURATION = 250;
     private static final long GLOW_DURATION = 150;
 
-    // Set to false to disable focus-based gestures (spread-finger vertical pull).
+    // Set to false to disable focus-based gestures (two-finger pull).
     private static final boolean USE_DRAG = true;
     // Set to false to disable scale-based gestures (both horizontal and vertical).
     private static final boolean USE_SPAN = true;
@@ -69,12 +69,8 @@
     @SuppressWarnings("unused")
     private Context mContext;
 
-    private boolean mExpanding;
-    private static final int NONE    = 0;
-    private static final int BLINDS  = 1<<0;
-    private static final int PULL    = 1<<1;
-    private static final int STRETCH = 1<<2;
-    private int mExpansionStyle = NONE;
+    private boolean mStretching;
+    private boolean mPullingWithOneFinger;
     private boolean mWatchingForPull;
     private boolean mHasPopped;
     private View mEventSource;
@@ -90,9 +86,8 @@
     private int mLastMotionY;
     private float mPopLimit;
     private int mPopDuration;
-    private float mPullGestureMinXSpan;
     private Callback mCallback;
-    private ScaleGestureDetector mSGD;
+    private ScaleGestureDetector mDetector;
     private ViewScaler mScaler;
     private ObjectAnimator mScaleAnimation;
     private AnimatorSet mGlowAnimationSet;
@@ -127,7 +122,7 @@
             if (height < 0) {
                 height = mView.getMeasuredHeight();
             }
-            return height;
+            return (float) height;
         }
         public int getNaturalHeight(int maximum) {
             ViewGroup.LayoutParams lp = mView.getLayoutParams();
@@ -166,9 +161,8 @@
         mGravity = Gravity.TOP;
         mScaleAnimation = ObjectAnimator.ofFloat(mScaler, "height", 0f);
         mScaleAnimation.setDuration(EXPAND_DURATION);
-        mPopLimit = mContext.getResources().getDimension(R.dimen.blinds_pop_threshold);
-        mPopDuration = mContext.getResources().getInteger(R.integer.blinds_pop_duration_ms);
-        mPullGestureMinXSpan = mContext.getResources().getDimension(R.dimen.pull_span_min);
+        mPopLimit = mContext.getResources().getDimension(R.dimen.one_finger_pop_limit);
+        mPopDuration = mContext.getResources().getInteger(R.integer.one_finger_pop_duration_ms);
 
         AnimatorListenerAdapter glowVisibilityController = new AnimatorListenerAdapter() {
             @Override
@@ -199,30 +193,41 @@
         final ViewConfiguration configuration = ViewConfiguration.get(mContext);
         mTouchSlop = configuration.getScaledTouchSlop();
 
-        mSGD = new ScaleGestureDetector(context,
+        mDetector =
+                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();
+                float x = detector.getFocusX();
+                float y = detector.getFocusY();
 
                 // your fingers have to be somewhat close to the bounds of the view in question
-                mInitialTouchFocusY = focusY;
+                mInitialTouchFocusY = detector.getFocusY();
                 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;
+                mStretching = initScale(findView(x, y));
+                return mStretching;
             }
 
             @Override
             public boolean onScale(ScaleGestureDetector detector) {
                 if (DEBUG_SCALE) Slog.v(TAG, "onscale() on " + mCurrView);
-                updateExpansion();
+
+                // are we scaling or dragging?
+                float span = Math.abs(detector.getCurrentSpan()) - mInitialTouchSpan;
+                span *= USE_SPAN ? 1f : 0f;
+                float drag = detector.getFocusY() - mInitialTouchFocusY;
+                drag *= USE_DRAG ? 1f : 0f;
+                drag *= mGravity == Gravity.BOTTOM ? -1f : 1f;
+                float pull = Math.abs(drag) + Math.abs(span) + 1f;
+                float hand = drag * Math.abs(drag) / pull + span * Math.abs(span) / pull;
+                float target = hand + mOldHeight;
+                float newHeight = clamp(target);
+                mScaler.setHeight(newHeight);
+
+                setGlow(calculateGlow(target, newHeight));
                 return true;
             }
 
@@ -231,28 +236,13 @@
                 if (DEBUG_SCALE) Slog.v(TAG, "onscaleend()");
                 // I guess we're alone now
                 if (DEBUG_SCALE) Slog.d(TAG, "scale end");
-                finishExpanding(false);
+                finishScale(false);
                 clearView();
+                mStretching = false;
             }
         });
     }
 
-    private void updateExpansion() {
-        // are we scaling or dragging?
-        float span = Math.abs(mSGD.getCurrentSpan()) - mInitialTouchSpan;
-        span *= USE_SPAN ? 1f : 0f;
-        float drag = mSGD.getFocusY() - mInitialTouchFocusY;
-        drag *= USE_DRAG ? 1f : 0f;
-        drag *= mGravity == Gravity.BOTTOM ? -1f : 1f;
-        float pull = Math.abs(drag) + Math.abs(span) + 1f;
-        float hand = drag * Math.abs(drag) / pull + span * Math.abs(span) / pull;
-        float target = hand + mOldHeight;
-        float newHeight = clamp(target);
-        mScaler.setHeight(newHeight);
-
-        setGlow(calculateGlow(target, newHeight));
-    }
-
     private float clamp(float target) {
         float out = target;
         out = out < mSmallSize ? mSmallSize : (out > mLargeSize ? mLargeSize : out);
@@ -265,8 +255,8 @@
         if (mEventSource != null) {
             int[] location = new int[2];
             mEventSource.getLocationOnScreen(location);
-            x += location[0];
-            y += location[1];
+            x += (float) location[0];
+            y += (float) location[1];
             v = mCallback.getChildAtRawPosition(x, y);
         } else {
             v = mCallback.getChildAtPosition(x, y);
@@ -284,14 +274,14 @@
         if (mEventSource != null) {
             int[] location = new int[2];
             mEventSource.getLocationOnScreen(location);
-            x += location[0];
-            y += location[1];
+            x += (float) location[0];
+            y += (float) location[1];
             if (DEBUG) Slog.d(TAG, "  to global (" + x + ", " + y + ")");
         }
         int[] location = new int[2];
         v.getLocationOnScreen(location);
-        x -= location[0];
-        y -= location[1];
+        x -= (float) location[0];
+        y -= (float) location[1];
         if (DEBUG) Slog.d(TAG, "  to local (" + x + ", " + y + ")");
         if (DEBUG) Slog.d(TAG, "  inside (" + v.getWidth() + ", " + v.getHeight() + ")");
         boolean inside = (x > 0f && y > 0f && x < v.getWidth() & y < v.getHeight());
@@ -313,7 +303,7 @@
     private float calculateGlow(float target, float actual) {
         // glow if overscale
         if (DEBUG_GLOW) Slog.d(TAG, "target: " + target + " actual: " + actual);
-        float stretch = Math.abs((target - actual) / mMaximumStretch);
+        float stretch = (float) Math.abs((target - actual) / mMaximumStretch);
         float strength = 1f / (1f + (float) Math.pow(Math.E, -1 * ((8f * stretch) - 5f)));
         if (DEBUG_GLOW) Slog.d(TAG, "stretch: " + stretch + " strength: " + strength);
         return (GLOW_BASE + strength * (1f - GLOW_BASE));
@@ -350,54 +340,32 @@
                 View.INVISIBLE : View.VISIBLE);
     }
 
-    @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
-        final int action = ev.getAction();
-        if (DEBUG_SCALE) Slog.d(TAG, "intercept: act=" + MotionEvent.actionToString(action) +
-                         " expanding=" + mExpanding +
-                         (0 != (mExpansionStyle & BLINDS) ? " (blinds)" : "") +
-                         (0 != (mExpansionStyle & PULL) ? " (pull)" : "") +
-                         (0 != (mExpansionStyle & STRETCH) ? " (stretch)" : ""));
-        // check for a spread-finger vertical pull gesture
-        mSGD.onTouchEvent(ev);
-        final int x = (int) mSGD.getFocusX();
-        final int y = (int) mSGD.getFocusY();
-        if (mExpanding) {
+        if (DEBUG) Slog.d(TAG, "interceptTouch: act=" + (ev.getAction()) +
+                         " stretching=" + mStretching +
+                         " onefinger=" + mPullingWithOneFinger);
+        // check for a two-finger gesture
+        mDetector.onTouchEvent(ev);
+        if (mStretching) {
             return true;
         } else {
-            if ((action == MotionEvent.ACTION_MOVE) && 0 != (mExpansionStyle & BLINDS)) {
-                // we've begun Venetian blinds style expansion
-                return true;
-            }
-            final float xspan = mSGD.getCurrentSpanX();
-            if ((action == MotionEvent.ACTION_MOVE &&
-                    xspan > mPullGestureMinXSpan &&
-                    xspan > mSGD.getCurrentSpanY())) {
-                // 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);
-                }
+            final int action = ev.getAction();
+            if ((action == MotionEvent.ACTION_MOVE) && mPullingWithOneFinger) {
                 return true;
             }
             if (mScrollView != null && mScrollView.getScrollY() > 0) {
                 return false;
             }
-            // Now look for other gestures
             switch (action & MotionEvent.ACTION_MASK) {
             case MotionEvent.ACTION_MOVE: {
                 if (mWatchingForPull) {
+                    final int x = (int) ev.getX();
+                    final int y = (int) ev.getY();
                     final int yDiff = y - mLastMotionY;
                     if (yDiff > mTouchSlop) {
-                        if (DEBUG) Slog.v(TAG, "got venetian gesture (dy=" + yDiff + "px)");
                         mLastMotionY = y;
-                        final View underFocus = findView(x, y);
-                        if (underFocus != null) {
-                            startExpanding(underFocus, BLINDS);
+                        mPullingWithOneFinger = initScale(findView(x, y));
+                        if (mPullingWithOneFinger) {
                             mInitialTouchY = mLastMotionY;
                             mHasPopped = false;
                         }
@@ -407,35 +375,35 @@
             }
 
             case MotionEvent.ACTION_DOWN:
-                mWatchingForPull = isInside(mScrollView, x, y);
-                mLastMotionY = y;
+                mWatchingForPull = isInside(mScrollView, ev.getX(), ev.getY());
+                mLastMotionY = (int) ev.getY();
                 break;
 
             case MotionEvent.ACTION_CANCEL:
             case MotionEvent.ACTION_UP:
-                if (DEBUG) Slog.d(TAG, "up/cancel");
-                finishExpanding(false);
-                clearView();
+                if (mPullingWithOneFinger) {
+                    finishScale(false);
+                    clearView();
+                }
+                mPullingWithOneFinger = false;
+                mWatchingForPull = false;
                 break;
             }
-            return mExpanding;
+            return mPullingWithOneFinger;
         }
     }
 
-    @Override
     public boolean onTouchEvent(MotionEvent ev) {
         final int action = ev.getAction();
-        if (DEBUG_SCALE) Slog.d(TAG, "touch: act=" + MotionEvent.actionToString(action) +
-                " expanding=" + mExpanding +
-                (0 != (mExpansionStyle & BLINDS) ? " (blinds)" : "") +
-                (0 != (mExpansionStyle & PULL) ? " (pull)" : "") +
-                (0 != (mExpansionStyle & STRETCH) ? " (stretch)" : ""));
-
-        mSGD.onTouchEvent(ev);
-
+        if (DEBUG_SCALE) Slog.d(TAG, "touch: act=" + (action) +
+                         " stretching=" + mStretching +
+                         " onefinger=" + mPullingWithOneFinger);
+        if (mStretching) {
+            mDetector.onTouchEvent(ev);
+        }
         switch (action) {
             case MotionEvent.ACTION_MOVE: {
-                if (0 != (mExpansionStyle & BLINDS)) {
+                if (mPullingWithOneFinger) {
                     final float rawHeight = ev.getY() - mInitialTouchY + mOldHeight;
                     final float newHeight = clamp(rawHeight);
                     final boolean wasClosed = (mOldHeight == mSmallSize);
@@ -462,59 +430,57 @@
                         setGlow(calculateGlow(4f * pull, 0f));
                     }
 
-                    final int x = (int) mSGD.getFocusX();
-                    final int y = (int) mSGD.getFocusY();
-                    View underFocus = findView(x, y);
-                    if (isFinished && underFocus != null && underFocus != mCurrView) {
-                        finishExpanding(false); // @@@ needed?
-                        startExpanding(underFocus, BLINDS);
-                        mInitialTouchY = y;
+                    final int x = (int) ev.getX();
+                    final int y = (int) ev.getY();
+                    View underPointer = findView(x, y);
+                    if (isFinished && underPointer != null && underPointer != mCurrView) {
+                        finishScale(false);
+                        initScale(underPointer);
+                        mInitialTouchY = ev.getY();
                         mHasPopped = false;
                     }
                     return true;
                 }
-
-                if (mExpanding) {
-                    updateExpansion();
-                    return true;
-                }
-
                 break;
             }
             case MotionEvent.ACTION_UP:
             case MotionEvent.ACTION_CANCEL:
-                if (DEBUG) Slog.d(TAG, "up/cancel");
-                finishExpanding(false);
+                if (DEBUG) Slog.d(TAG, "cancel");
+                mStretching = false;
+                if (mPullingWithOneFinger) {
+                    finishScale(false);
+                    mPullingWithOneFinger = false;
+                }
                 clearView();
                 break;
         }
         return true;
     }
-
-    private void startExpanding(View v, int expandType) {
-        mExpanding = true;
-        mExpansionStyle = expandType; 
-        if (DEBUG) Slog.d(TAG, "scale type " + expandType + " beginning on view: " + v);
-        mCallback.setUserLockedChild(v, true);
-        setView(v);
-        setGlow(GLOW_BASE);
-        mScaler.setView(v);
-        mOldHeight = mScaler.getHeight();
-        if (mCallback.canChildBeExpanded(v)) {
-            if (DEBUG) Slog.d(TAG, "working on an expandable child");
-            mNaturalHeight = mScaler.getNaturalHeight(mLargeSize);
+    private boolean initScale(View v) {
+        if (v != null) {
+            if (DEBUG) Slog.d(TAG, "scale begins on view: " + v);
+            mCallback.setUserLockedChild(v, true);
+            setView(v);
+            setGlow(GLOW_BASE);
+            mScaler.setView(v);
+            mOldHeight = mScaler.getHeight();
+            if (mCallback.canChildBeExpanded(v)) {
+                if (DEBUG) Slog.d(TAG, "working on an expandable child");
+                mNaturalHeight = mScaler.getNaturalHeight(mLargeSize);
+            } else {
+                if (DEBUG) Slog.d(TAG, "working on a non-expandable child");
+                mNaturalHeight = mOldHeight;
+            }
+            if (DEBUG) Slog.d(TAG, "got mOldHeight: " + mOldHeight +
+                        " mNaturalHeight: " + mNaturalHeight);
+            v.getParent().requestDisallowInterceptTouchEvent(true);
+            return true;
         } else {
-            if (DEBUG) Slog.d(TAG, "working on a non-expandable child");
-            mNaturalHeight = mOldHeight;
+            return false;
         }
-        if (DEBUG) Slog.d(TAG, "got mOldHeight: " + mOldHeight +
-                    " mNaturalHeight: " + mNaturalHeight);
-        v.getParent().requestDisallowInterceptTouchEvent(true);
     }
 
-    private void finishExpanding(boolean force) {
-        if (!mExpanding) return;
-
+    private void finishScale(boolean force) {
         float currentHeight = mScaler.getHeight();
         float targetHeight = mSmallSize;
         float h = mScaler.getHeight();
@@ -535,10 +501,6 @@
             mScaleAnimation.start();
         }
         mCallback.setUserLockedChild(mCurrView, false);
-
-        mExpanding = false;
-        mExpansionStyle = NONE;
-
         if (DEBUG) Slog.d(TAG, "scale was finished on view: " + mCurrView);
     }
 
@@ -565,8 +527,8 @@
 
     @Override
     public void onClick(View v) {
-        startExpanding(v, STRETCH);
-        finishExpanding(true);
+        initScale(v);
+        finishScale(true);
         clearView();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index b0a7c4b..0671e44 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -30,10 +30,8 @@
 import android.renderscript.Matrix4f;
 import android.service.wallpaper.WallpaperService;
 import android.util.Log;
-import android.view.Display;
 import android.view.MotionEvent;
 import android.view.SurfaceHolder;
-import android.view.WindowManager;
 
 import javax.microedition.khronos.egl.EGL10;
 import javax.microedition.khronos.egl.EGLConfig;
@@ -74,10 +72,7 @@
         //noinspection PointlessBooleanExpression,ConstantConditions
         if (FIXED_SIZED_SURFACE && USE_OPENGL) {
             if (!isEmulator()) {
-                WindowManager windowManager =
-                        (WindowManager) getSystemService(Context.WINDOW_SERVICE);
-                Display display = windowManager.getDefaultDisplay();
-                mIsHwAccelerated = ActivityManager.isHighEndGfx(display);
+                mIsHwAccelerated = ActivityManager.isHighEndGfx();
             }
         }
     }
@@ -294,13 +289,6 @@
                 updateWallpaperLocked();
             }
 
-            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();
diff --git a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
index 475fb6d..281f25f 100644
--- a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
@@ -24,6 +24,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
+import android.os.UserHandle;
 import android.os.Vibrator;
 import android.provider.Settings;
 import android.util.AttributeSet;
@@ -73,14 +74,16 @@
         // Close Recent Apps if needed
         mBar.animateCollapse(CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL);
         // Launch Assist
-        Intent intent = SearchManager.getAssistIntent(mContext);
+        Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+                .getAssistIntent(mContext, UserHandle.USER_CURRENT);
         if (intent == null) return;
         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());
+            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 +143,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,
@@ -277,6 +281,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..89d4ef7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/Somnambulator.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.systemui;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.service.dreams.IDreamManager;
+import android.util.Slog;
+
+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_dreams));
+            resultIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
+            resultIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, getString(R.string.start_dreams));
+            setResult(RESULT_OK, resultIntent);
+        } else {
+            IDreamManager somnambulist = IDreamManager.Stub.asInterface(
+                    ServiceManager.checkService("dreams"));
+            if (somnambulist != null) {
+                try {
+                    Slog.v("Somnambulator", "Dreaming by user request.");
+                    somnambulist.dream();
+                } catch (RemoteException e) {
+                    // fine, stay asleep then
+                }
+            }
+        }
+        finish();
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
new file mode 100644
index 0000000..f97d4ff
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.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;
+
+import android.app.Application;
+
+import com.android.systemui.recent.RecentTasksLoader;
+
+public class SystemUIApplication extends Application {
+    private RecentTasksLoader mRecentTasksLoader;
+
+    public RecentTasksLoader getRecentTasksLoader() {
+        if (mRecentTasksLoader == null) {
+            mRecentTasksLoader = new RecentTasksLoader(this);
+        }
+        return mRecentTasksLoader;
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index 0a57499..1bde949 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -31,6 +31,7 @@
 import android.os.ServiceManager;
 import android.util.Slog;
 import android.view.IWindowManager;
+import android.view.WindowManagerGlobal;
 
 public class SystemUIService extends Service {
     static final String TAG = "SystemUIService";
@@ -67,8 +68,7 @@
     @Override
     public void onCreate() {
         // Pick status bar or system bar.
-        IWindowManager wm = IWindowManager.Stub.asInterface(
-                ServiceManager.getService(Context.WINDOW_SERVICE));
+        IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
         try {
             SERVICES[0] = wm.hasSystemNavBar()
                     ? R.string.config_systemBarComponent
diff --git a/packages/SystemUI/src/com/android/systemui/UniverseBackground.java b/packages/SystemUI/src/com/android/systemui/UniverseBackground.java
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/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..6d84350 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
@@ -31,6 +31,8 @@
 import android.os.Handler;
 import android.os.Process;
 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 +43,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;
 
@@ -50,18 +52,43 @@
 
     private Context mContext;
     private RecentsPanelView mRecentsPanel;
+    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;
+
+    private boolean mFirstScreenful;
+    private ArrayList<TaskDescription> mLoadedTasks;
+
+    private enum State { LOADING, LOADED, CANCELLED };
+    private State mState = State.CANCELLED;
+
+    public TaskDescription getFirstTask() {
+        while (!mFirstTaskLoaded) {
+            if (mState == State.CANCELLED) {
+                loadTasksInBackground();
+            }
+            try {
+                if (mState == State.LOADED) {
+                    break;
+                }
+                Thread.sleep(5);
+            } catch (InterruptedException e) {
+            }
+        }
+        return mFirstTask;
+    }
 
     public RecentTasksLoader(Context context) {
         mContext = context;
+        mHandler = new Handler();
 
         final Resources res = context.getResources();
 
@@ -91,18 +118,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 +138,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);
@@ -209,7 +241,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 +294,28 @@
             mThumbnailLoader.cancel(false);
             mThumbnailLoader = null;
         }
+        mLoadedTasks = null;
+        mFirstTask = null;
+        mFirstTaskLoaded = false;
+        if (mRecentsPanel != null) {
+            mRecentsPanel.onTaskLoadingCancelled();
+        }
+        mFirstScreenful = false;
+        mState = State.CANCELLED;
     }
 
     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 +323,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 +353,34 @@
                 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)) {
+                        if (index == 0) {
+                            mFirstTaskLoaded = true;
+                        }
+                        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 +435,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,19 +460,25 @@
                         } catch (InterruptedException e) {
                         }
                     }
-                    if (td.isNull()) {
+                    if (td.isNull()) { // end sentinel
+                        publishProgress(td);
                         break;
                     }
                     loadThumbnailAndIcon(td);
-                    synchronized(td) {
-                        publishProgress(td);
+
+                    if (!mFirstTaskLoaded) {
+                        mFirstTask = td;
+                        mFirstTaskLoaded = true;
                     }
+                    publishProgress(td);
                 }
 
                 Process.setThreadPriority(origPri);
                 return null;
             }
         };
+        mFirstTask = null;
+        mFirstTaskLoaded = false;
         mThumbnailLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
     }
 }
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..9c3756c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.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 com.android.systemui.R;
+import com.android.systemui.SystemUIApplication;
+import com.android.systemui.statusbar.tablet.StatusBarPanel;
+
+public class RecentsActivity extends Activity {
+    public static final String TOGGLE_RECENTS_INTENT = "com.android.systemui.TOGGLE_RECENTS";
+    public static final String CLOSE_RECENTS_INTENT = "com.android.systemui.CLOSE_RECENTS";
+    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 (mRecentsPanel != null && mRecentsPanel.isShowing()) {
+                if (mShowing && !mForeground) {
+                    // Captures the case right before we transition to another activity
+                    mRecentsPanel.show(false);
+                }
+            }
+        }
+    };
+
+    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() {
+        mForeground = false;
+        super.onPause();
+    }
+
+    @Override
+    public void onStop() {
+        mShowing = false;
+        if (mRecentsPanel != null) {
+            mRecentsPanel.onUiHidden();
+        }
+        super.onStop();
+    }
+
+    @Override
+    public void onStart() {
+        mShowing = true;
+        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 SystemUIApplication app = (SystemUIApplication) getApplication();
+            final RecentTasksLoader recentTasksLoader = app.getRecentTasksLoader();
+            TaskDescription firstTask = recentTasksLoader.getFirstTask();
+            if (firstTask != null && mRecentsPanel.simulateClick(firstTask)) {
+                // recents panel will take care of calling show(false);
+                return;
+            }
+            mRecentsPanel.show(false);
+        }
+        finish();
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        final SystemUIApplication app = (SystemUIApplication) getApplication();
+        final RecentTasksLoader recentTasksLoader = app.getRecentTasksLoader();
+
+        setContentView(R.layout.status_bar_recent_panel);
+        mRecentsPanel = (RecentsPanelView) findViewById(R.id.recents_root);
+        mRecentsPanel.setOnTouchListener(new TouchOutsideListener(mRecentsPanel));
+        mRecentsPanel.setRecentTasksLoader(recentTasksLoader);
+        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());
+        }
+        mIntentFilter = new IntentFilter();
+        mIntentFilter.addAction(CLOSE_RECENTS_INTENT);
+        registerReceiver(mIntentReceiver, mIntentFilter);
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        outState.putBoolean(WAS_SHOWING, mRecentsPanel.isShowing());
+    }
+
+    @Override
+    protected void onDestroy() {
+        final SystemUIApplication app = (SystemUIApplication) getApplication();
+        final RecentTasksLoader recentTasksLoader = app.getRecentTasksLoader();
+        recentTasksLoader.setRecentsPanel(null, mRecentsPanel);
+        unregisterReceiver(mIntentReceiver);
+        super.onDestroy();
+    }
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        handleIntent(intent);
+    }
+
+    private void handleIntent(Intent intent) {
+        super.onNewIntent(intent);
+
+        if (TOGGLE_RECENTS_INTENT.equals(intent.getAction())) {
+            if (mRecentsPanel != null) {
+                if (mRecentsPanel.isShowing()) {
+                    dismissAndGoBack();
+                } else {
+                    final SystemUIApplication app = (SystemUIApplication) getApplication();
+                    final RecentTasksLoader recentTasksLoader = app.getRecentTasksLoader();
+                    mRecentsPanel.show(true, recentTasksLoader.getLoadedTasks(),
+                            recentTasksLoader.isFirstScreenful());
+                }
+            }
+        }
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
index f85007e..4aa2095 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(TaskDescription task) {
+        for (int i = 0; i < mLinearLayout.getChildCount(); i++) {
+            View v = mLinearLayout.getChildAt(i);
+            RecentsPanelView.ViewHolder holder = (RecentsPanelView.ViewHolder) v.getTag();
+            if (holder.taskDescription == task) {
+                return v;
+            }
+        }
+        return null;
+    }
+
     private void update() {
         for (int i = 0; i < mLinearLayout.getChildCount(); i++) {
             View v = mLinearLayout.getChildAt(i);
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index 0bdf84a..04e38a4 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -21,6 +21,7 @@
 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,25 +29,21 @@
 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.widget.AdapterView;
@@ -60,7 +57,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 +64,10 @@
 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 +76,22 @@
 
     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 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(TaskDescription task);
     }
 
     private final class OnLongClickDelegate implements View.OnLongClickListener {
@@ -178,13 +159,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();
 
@@ -249,15 +223,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 +242,26 @@
         }
     }
 
-    public void show(boolean show, boolean animate) {
+    public void show(boolean show) {
+        show(show, null, false);
+    }
+
+    public void show(boolean show, ArrayList<TaskDescription> recentTaskDescriptions,
+            boolean firstScreenful) {
         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 +274,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 +324,6 @@
             createCustomAnimations(transitioner);
         } else {
             ((ViewGroup)mRecentsContainer).setLayoutTransition(null);
-            clearRecentTasksList();
         }
     }
 
@@ -400,16 +333,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 +354,6 @@
         return mShowing;
     }
 
-    public void setBar(BaseStatusBar bar) {
-        mBar = bar;
-
-    }
-
     public void setStatusBarView(View statusBarView) {
         if (mStatusBarTouchProxy != null) {
             mStatusBarTouchProxy.setStatusBar(statusBarView);
@@ -446,18 +364,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));
@@ -483,12 +389,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 +399,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) {
@@ -601,44 +492,19 @@
         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();
-                }
-            }
-        }
-        return false;
-    }
-
-    public void preloadRecentTasksList() {
-        if (!mShowing) {
-            mPreloadTasksRunnable.run();
-        }
-    }
-
     public void clearRecentTasksList() {
         // Clear memory used by screenshots
-        if (!mShowing && mRecentTaskDescriptions != null) {
-            mRecentTasksLoader.cancelLoadingThumbnailsAndIcons();
-            mRecentTaskDescriptions.clear();
+        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();
-            mRecentTasksDirty = true;
         }
     }
 
@@ -648,23 +514,15 @@
 
     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 
+    public void onTasksLoaded(ArrayList<TaskDescription> tasks, boolean firstScreenful) {
+        mNumItemsWaitingForThumbnailsAndIcons = firstScreenful
                 ? tasks.size() : mRecentTaskDescriptions == null 
                         ? 0 : mRecentTaskDescriptions.size();
         if (mRecentTaskDescriptions == null) {
@@ -674,19 +532,9 @@
         }
         mListAdapter.notifyDataSetInvalidated();
         updateUiElements(getResources().getConfiguration());
-        mReadyToShow = true;
-        mFirstScreenful = false;
         showIfReady();
     }
 
-    public ArrayList<TaskDescription> getRecentTasksList() {
-        return mRecentTaskDescriptions;
-    }
-
-    public boolean getFirstScreenful() {
-        return mFirstScreenful;
-    }
-
     private void updateUiElements(Configuration config) {
         final int items = mRecentTaskDescriptions.size();
 
@@ -705,8 +553,19 @@
         setContentDescription(recentAppsAccessibilityDescription);
     }
 
+    public boolean simulateClick(TaskDescription task) {
+        if (mRecentsContainer instanceof RecentsScrollView){
+            RecentsScrollView scrollView
+                = (RecentsScrollView) mRecentsContainer;
+            View v = scrollView.findViewForTask(task);
+            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 +582,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 +624,7 @@
         // mListAdapter.notifyDataSetChanged();
 
         if (mRecentTaskDescriptions.size() == 0) {
-            hide(false);
+            dismissAndGoBack();
         }
 
         // Currently, either direction means the same thing, so ignore direction and remove
@@ -845,8 +645,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 +674,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/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..a0f197dd 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(TaskDescription task) {
+        for (int i = 0; i < mLinearLayout.getChildCount(); i++) {
+            View v = mLinearLayout.getChildAt(i);
+            RecentsPanelView.ViewHolder holder = (RecentsPanelView.ViewHolder) v.getTag();
+            if (holder.taskDescription == task) {
+                return v;
+            }
+        }
+        return null;
+    }
+
     private void update() {
         for (int i = 0; i < mLinearLayout.getChildCount(); i++) {
             View v = mLinearLayout.getChildAt(i);
@@ -150,7 +157,9 @@
             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);
         }
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 8d7734e..923cd93 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,39 @@
 
 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.SystemUIApplication;
+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.ActivityManagerNative;
+import android.app.ActivityOptions;
 import android.app.KeyguardManager;
-import android.app.Notification;
 import android.app.PendingIntent;
+import android.app.Service;
+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 +58,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;
@@ -46,37 +71,24 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.WindowManagerGlobal;
 import android.view.ViewGroup.LayoutParams;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
-import android.widget.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 {
+        CommandQueue.Callbacks {
     static final String TAG = "StatusBar";
     private 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 +121,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,18 +133,12 @@
      */
     protected abstract void createAndAddWindows();
 
+    protected WindowManager mWindowManager;
+    protected IWindowManager mWindowManagerService;
     protected Display mDisplay;
-    private IWindowManager mWindowManager;
+
     private boolean mDeviceProvisioned = false;
 
-    public IWindowManager getWindowManager() {
-        return mWindowManager;
-    }
-
-    public Display getDisplay() {
-        return mDisplay;
-    }
-
     public IStatusBarService getStatusBarService() {
         return mBarService;
     }
@@ -185,17 +189,15 @@
     };
 
     public void start() {
-        mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
-                .getDefaultDisplay();
+        mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
+        mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
+        mDisplay = mWindowManager.getDefaultDisplay();
 
         mProvisioningObserver.onChange(false); // set up
         mContext.getContentResolver().registerContentObserver(
                 Settings.Secure.getUriFor(Settings.Secure.DEVICE_PROVISIONED), true,
                 mProvisioningObserver);
 
-        mWindowManager = IWindowManager.Stub.asInterface(
-                ServiceManager.getService(Context.WINDOW_SERVICE));
-
         mBarService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
 
@@ -255,6 +257,40 @@
                    switches[3]
                    ));
         }
+
+        // XXX: this is currently broken and will always return 0, but should start working at some point
+        try {
+            mCurrentUserId = ActivityManagerNative.getDefault().getCurrentUser().id;
+        } catch (RemoteException e) {
+            Log.v(TAG, "Couldn't get current user ID; guessing it's 0", e);
+        }
+
+        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 thisUserId == notificationUserId;
     }
 
     protected View updateNotificationVetoButton(View row, StatusBarNotification n) {
@@ -301,8 +337,8 @@
     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();
     }
 
     protected View.OnLongClickListener getNotificationLongClicker() {
@@ -347,8 +383,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,49 +416,15 @@
         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 RecentTasksLoader getRecentTasksLoader() {
+        final SystemUIApplication app = (SystemUIApplication) ((Service) mContext).getApplication();
+        return app.getRecentTasksLoader();
     }
 
     protected void updateSearchPanel() {
@@ -431,7 +432,7 @@
         boolean visible = false;
         if (mSearchPanelView != null) {
             visible = mSearchPanelView.isShowing();
-            WindowManagerImpl.getDefault().removeView(mSearchPanelView);
+            mWindowManager.removeView(mSearchPanelView);
         }
 
         // Provide SearchPanel with a temporary parent to allow layout params to work.
@@ -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,140 @@
         }
     }
 
+    protected abstract View getStatusBarView();
+
+    protected void toggleRecentsActivity() {
+        try {
+            final RecentTasksLoader recentTasksLoader = getRecentTasksLoader();
+            TaskDescription firstTask = recentTasksLoader.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) {
+                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(labelTextSize);
+                    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,
+                        null);
+                mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
+                        UserHandle.USER_CURRENT));
+            }
+            return;
+        } catch (ActivityNotFoundException e) {
+            Log.e(TAG, "Failed to launch RecentAppsIntent", e);
+        }
+    }
+
     protected class H extends Handler {
         public void handleMessage(Message m) {
             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 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();
+                  getRecentTasksLoader().preloadRecentTasksList();
                   break;
              case MSG_CANCEL_PRELOAD_RECENT_APPS:
                   if (DEBUG) Slog.d(TAG, "cancel preloading recents");
-                  mRecentsPanel.clearRecentTasksList();
+                  getRecentTasksLoader().cancelPreloadingRecentTasksList();
                   break;
              case MSG_OPEN_SEARCH_PANEL:
                  if (DEBUG) Slog.d(TAG, "opening search panel");
@@ -529,8 +642,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 +686,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 +717,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;
@@ -923,8 +1041,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/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/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 00d6d6f..dcc2e57 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,11 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
 import android.app.StatusBarManager;
 import android.content.Context;
 import android.content.res.Resources;
+import android.graphics.Point;
 import android.graphics.Rect;
-import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.os.Message;
@@ -33,31 +32,25 @@
 import android.view.animation.AccelerateInterpolator;
 import android.view.Display;
 import android.view.MotionEvent;
-import android.view.VelocityTracker;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.Surface;
-import android.view.Window;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.lang.StringBuilder;
 
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.R;
 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;
 
     final static boolean ANIMATE_HIDE_TRANSITION = false; // turned off because it introduces unsightly delay when videos goes to full screen
@@ -77,6 +70,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 +109,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
@@ -243,7 +241,8 @@
             } else {
                 return;
             }
-            WindowManagerImpl.getDefault().updateViewLayout(this, lp);
+            WindowManager wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
+            wm.updateViewLayout(this, lp);
         }
     }
 
@@ -340,15 +339,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 +428,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..9c978d5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.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.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 com.android.systemui.R;
+
+public class NotificationPanelView extends PanelView {
+
+    Drawable mHandleBar;
+    float mHandleBarHeight;
+
+    public NotificationPanelView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        Resources resources = context.getResources();
+        mHandleBar = resources.getDrawable(R.drawable.status_bar_close);
+        mHandleBarHeight = resources.getDimension(R.dimen.close_handle_height);
+    }
+
+    @Override
+    public void fling(float vel, boolean always) {
+        ((PhoneStatusBarView) mBar).mBar.getGestureRecorder().tag(
+            "fling " + ((vel > 0) ? "open" : "closed"),
+            "notifications,v=" + vel);
+        super.fling(vel, always);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        if (changed) {
+            mHandleBar.setBounds(0, 0, getWidth(), (int) mHandleBarHeight);
+        }
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        super.draw(canvas);
+        canvas.translate(0, getHeight() - mHandleBarHeight);
+        mHandleBar.draw(canvas);
+        canvas.translate(0, -getHeight() + mHandleBarHeight);
+    }
+}
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..bffb903
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -0,0 +1,158 @@
+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.widget.FrameLayout;
+
+public class PanelBar extends FrameLayout {
+    public static final boolean DEBUG = false;
+    public static final String TAG = PanelView.class.getSimpleName();
+    public static final void LOG(String fmt, Object... args) {
+        if (!DEBUG) return;
+        Slog.v(TAG, String.format(fmt, args));
+    }
+
+    private PanelHolder mPanelHolder;
+    private ArrayList<PanelView> mPanels = new ArrayList<PanelView>();
+    protected PanelView mTouchingPanel;
+    private static final int STATE_CLOSED = 0;
+    private static final int STATE_TRANSITIONING = 1;
+    private static final int STATE_OPEN = 2;
+    private int mState = STATE_CLOSED;
+    private boolean mTracking;
+
+    private void go(int state) {
+        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 PanelView v = (PanelView) ph.getChildAt(i);
+            if (v != null) {
+                addPanel(v);
+            }
+        }
+    }
+
+    public float getBarHeight() {
+        return getMeasuredHeight();
+    }
+
+    public PanelView selectPanelForTouchX(float x) {
+        final int N = mPanels.size();
+        return mPanels.get((int)(N * x / 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) {
+            mTouchingPanel = selectPanelForTouchX(event.getX());
+            mPanelHolder.setSelectedPanel(mTouchingPanel);
+            LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %s", mState, mTouchingPanel.getName());
+            if (mState == STATE_CLOSED || mState == STATE_OPEN) {
+                go(STATE_TRANSITIONING);
+                onPanelPeeked();
+            }
+        }
+        final boolean result = mTouchingPanel.getHandle().dispatchTouchEvent(event);
+        return result;
+    }
+
+    public void panelExpansionChanged(PanelView panel, float frac) {
+        boolean fullyClosed = true;
+        PanelView fullyOpenedPanel = null;
+        LOG("panelExpansionChanged: start state=%d panel=%s", mState, panel.getName());
+        for (PanelView pv : mPanels) {
+            // adjust any other panels that may be partially visible
+            if (pv.getExpandedHeight() > 0f) {
+                fullyClosed = false;
+                final float thisFrac = pv.getExpandedFraction();
+                LOG("panelExpansionChanged:  -> %s: f=%.1f", pv.getName(), thisFrac);
+                if (panel == pv) {
+                    if (thisFrac == 1f) fullyOpenedPanel = panel;
+                } else {
+                    pv.setExpandedFraction(1f-frac);
+                }
+            }
+        }
+        if (fullyOpenedPanel != null && !mTracking) {
+            go(STATE_OPEN);
+            onPanelFullyOpened(fullyOpenedPanel);
+        } else if (fullyClosed && !mTracking) {
+            go(STATE_CLOSED);
+            onAllPanelsCollapsed();
+        }
+
+        LOG("panelExpansionChanged: end state=%d [%s%s ]", mState,
+                (fullyOpenedPanel!=null)?" fullyOpened":"", fullyClosed?" fullyClosed":"");
+    }
+
+    public void collapseAllPanels(boolean animate) {
+        for (PanelView pv : mPanels) {
+            if (animate && pv == mTouchingPanel) {
+                mTouchingPanel.collapse();
+            } else {
+                pv.setExpandedFraction(0); // just in case
+            }
+        }
+    }
+
+    public void onPanelPeeked() {
+        LOG("onPanelPeeked");
+    }
+
+    public void onAllPanelsCollapsed() {
+        LOG("onAllPanelsCollapsed");
+    }
+
+    public void onPanelFullyOpened(PanelView openPanel) {
+        LOG("onPanelFullyOpened");
+    }
+
+    public void onTrackingStarted(PanelView panel) {
+        mTracking = true;
+        if (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..abd82bd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelHolder.java
@@ -0,0 +1,65 @@
+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;
+    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:
+                mBar.collapseAllPanels(true);
+                break;
+        }
+        return false;
+    }
+
+    public void setBar(PanelBar panelBar) {
+        mBar = panelBar;
+    }
+}
\ No newline at end of file
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..1c244d4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -0,0 +1,392 @@
+package com.android.systemui.statusbar.phone;
+
+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;
+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 PanelView extends FrameLayout {
+    public static final boolean DEBUG = false;
+    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 static final boolean STRETCH_PAST_CONTENTS = 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 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 mTouchOffset;
+    private float mExpandedFraction = 0;
+    private float mExpandedHeight = 0;
+    private boolean mClosing;
+    private boolean mRubberbanding;
+    private boolean mTracking;
+
+    private TimeAnimator mTimeAnimator;
+    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() { public void run() {
+        if (mTimeAnimator.isStarted()) {
+            mTimeAnimator.end();
+            mRubberbanding = false;
+        }
+    }};
+
+    private float mVel, mAccel;
+    private int mFullHeight = 0;
+    private String mViewName;
+
+    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);
+
+            mTimeAnimator.start();
+            
+            mRubberbanding = STRETCH_PAST_CONTENTS && mExpandedHeight > getFullHeight();
+            mClosing = (mExpandedHeight > 0 && mVel < 0) || mRubberbanding;
+        } else if (dtms > 0) {
+            final float dt = dtms * 0.001f;                  // ms -> s
+            LOG("tick: v=%.2fpx/s dt=%.4fs", mVel, dt);
+            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;
+            }
+
+            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);
+
+        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);
+    }
+
+    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);
+    }
+
+    // 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();
+        loadDimens();
+
+        mHandleView = findViewById(R.id.handle);
+        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();
+                    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;
+                            mVelocityTracker = VelocityTracker.obtain();
+                            trackMovement(event);
+                            mBar.onTrackingStarted(PanelView.this);
+                            mTouchOffset = (rawY - mAbsPos[1]) - PanelView.this.getExpandedHeight();
+                            break;
+
+                        case MotionEvent.ACTION_MOVE:
+                            PanelView.this.setExpandedHeightInternal(rawY - mAbsPos[1] - mTouchOffset);
+
+                            mBar.panelExpansionChanged(PanelView.this, mExpandedFraction);
+
+                            trackMovement(event);
+                            break;
+
+                        case MotionEvent.ACTION_UP:
+                        case MotionEvent.ACTION_CANCEL:
+                            mTracking = false;
+                            mBar.onTrackingStopped(PanelView.this);
+                            trackMovement(event);
+                            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;
+                            }
+
+                            LOG("gesture: vraw=(%f,%f) vnorm=(%f,%f) vlinear=%f",
+                                    mVelocityTracker.getXVelocity(),
+                                    mVelocityTracker.getYVelocity(),
+                                    xVel, yVel,
+                                    vel);
+
+                            fling(vel, true);
+
+                            mVelocityTracker.recycle();
+                            mVelocityTracker = null;
+
+                            break;
+                    }
+                    return true;
+                }});
+        }
+    }
+
+    public void fling(float vel, boolean always) {
+        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) {
+        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);
+
+        LOG("onMeasure(%d, %d) -> (%d, %d)",
+                widthMeasureSpec, heightMeasureSpec, getMeasuredWidth(), getMeasuredHeight());
+        mFullHeight = getMeasuredHeight();
+        // if one of our children is getting smaller, we should track that
+        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) {
+        post(mStopAnimator);
+        setExpandedHeightInternal(height);
+    }
+
+    @Override
+    protected void onLayout (boolean changed, int left, int top, int right, int bottom) {
+        LOG("onLayout: changed=%s, bottom=%d eh=%d fh=%d", changed?"T":"f", bottom, (int)mExpandedHeight, (int)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
+        }
+
+        LOG("setExpansion: height=%.1f fh=%.1f tracking=%s rubber=%s", h, fh, mTracking?"T":"f", mRubberbanding?"T":"f");
+
+        if (h < 0) h = 0;
+        if (!(STRETCH_PAST_CONTENTS && (mTracking || mRubberbanding)) && h > fh) h = fh;
+        mExpandedHeight = h;
+
+        requestLayout();
+//        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
+//        lp.height = (int) mExpandedHeight;
+//        setLayoutParams(lp);
+
+        mExpandedFraction = Math.min(1f, h / fh);
+    }
+
+    private float getFullHeight() {
+        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 void setBar(PanelBar panelBar) {
+        mBar = panelBar;
+    }
+
+    public void setImeWindowStatus(boolean visible) {
+        // To be implemented by classes extending PanelView
+    }
+
+    public void setup(NetworkController network, BluetoothController bt, BatteryController batt,
+            LocationController location) {
+        // To be implemented by classes extending PanelView
+    }
+
+    public void collapse() {
+        // TODO: abort animation or ongoing touch
+        if (!isFullyCollapsed()) {
+            fling(-mSelfCollapseVelocityPx, /*always=*/ true);
+        }
+    }
+
+    public void expand() {
+        if (!isFullyExpanded()) {
+            fling (mSelfExpandVelocityPx, /*always=*/ true);
+        }
+    }
+}
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..ca1f82a 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.LayoutTransition;
 import android.animation.ObjectAnimator;
 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,7 +30,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
@@ -47,22 +44,21 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.provider.Settings;
+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.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
@@ -72,24 +68,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 java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -107,9 +105,6 @@
     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;
     // 1020-1030 reserved for BaseStatusBar
@@ -140,6 +135,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;
@@ -149,7 +145,7 @@
     int mIconHPadding = -1;
     Display mDisplay;
 
-    IWindowManager mWindowManager;
+    IDreamManager mDreamManager;
 
     StatusBarWindowView mStatusBarWindow;
     PhoneStatusBarView mStatusBarView;
@@ -164,14 +160,19 @@
     LinearLayout mStatusIcons;
 
     // expanded notifications
-    View mNotificationPanel; // the sliding/resizing panel within the notification window
+    PanelView mNotificationPanel; // the sliding/resizing panel within the notification window
     ScrollView mScrollView;
     View mExpandedContents;
-    int mNotificationPanelMarginBottomPx, mNotificationPanelMarginLeftPx;
     final Rect mNotificationPanelBackgroundPadding = new Rect();
     int mNotificationPanelGravity;
+    int mNotificationPanelMarginBottomPx, mNotificationPanelMarginPx;
     int mNotificationPanelMinHeight;
     boolean mNotificationPanelIsFullScreenWidth;
+    TextView mNotificationPanelDebugText;
+
+    // settings
+    PanelView mSettingsPanel;
+    int mSettingsPanelGravity;
 
     // top bar
     View mClearButton;
@@ -183,14 +184,12 @@
     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 +214,6 @@
     boolean mTracking;
     VelocityTracker mVelocityTracker;
 
-    Choreographer mChoreographer;
     boolean mAnimating;
     boolean mClosing; // only valid when mAnimating; indicates the initial acceleration
     float mAnimY;
@@ -240,6 +238,9 @@
 
     DisplayMetrics mDisplayMetrics = new DisplayMetrics();
 
+    // XXX: gesture research
+    private GestureRecorder mGestureRec = new GestureRecorder("/sdcard/statusbar_gestures.dat");
+
     private int mNavigationIconHints = 0;
     private final Animator.AnimatorListener mMakeIconsInvisible = new AnimatorListenerAdapter() {
         @Override
@@ -252,66 +253,13 @@
         }
     };
 
-    private final Runnable mStartRevealAnimation = new Runnable() {
-        @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;
-            }
-            return super.dispatchKeyEvent(event);
-        }
-    }
-
     @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("dreams"));
 
         super.start(); // calls createAndAddWindows()
 
@@ -346,7 +294,7 @@
             @Override
             public boolean onTouch(View v, MotionEvent event) {
                 if (event.getAction() == MotionEvent.ACTION_DOWN) {
-                    if (mExpanded && !mAnimating) {
+                    if (mExpandedVisible && !mAnimating) {
                         animateCollapse();
                     }
                 }
@@ -354,21 +302,19 @@
             }});
 
         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 = (PanelView) mStatusBarWindow.findViewById(R.id.notification_panel);
         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)) {
+        if (!ActivityManager.isHighEndGfx()) {
             mStatusBarWindow.setBackground(null);
             mNotificationPanel.setBackground(new FastColorDrawable(context.getResources().getColor(
                     R.color.notification_panel_solid_background)));
@@ -378,15 +324,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 =
@@ -430,10 +376,6 @@
         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,9 +386,11 @@
         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);
 
@@ -461,8 +405,10 @@
                 }});
         }
 
-        if (SHOW_CARRIER_LABEL) {
-            mCarrierLabel = (TextView)mStatusBarWindow.findViewById(R.id.carrier_label);
+        mCarrierLabel = (TextView)mStatusBarWindow.findViewById(R.id.carrier_label);
+        mShowCarrierInPanel = (mCarrierLabel != null);
+        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,26 +428,40 @@
             });
         }
 
+        // Quick Settings (WIP)
+        mSettingsPanel = (PanelView) mStatusBarWindow.findViewById(R.id.settings_panel);
+        mSettingsPanel.setBar(mStatusBarView);
+        mSettingsPanel.setup(mNetworkController, mBluetoothController, mBatteryController,
+                mLocationController);
+
+        if (!ActivityManager.isHighEndGfx()) {
+            mSettingsPanel.setBackground(new FastColorDrawable(context.getResources().getColor(
+                    R.color.notification_panel_solid_background)));
+        }
+
 //        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);
 
         return mStatusBarView;
     }
 
     @Override
+    protected View getStatusBarView() {
+        return mStatusBarView;
+    }
+
+    @Override
     protected WindowManager.LayoutParams getRecentsLayoutParams(LayoutParams layoutParams) {
         boolean opaque = false;
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
@@ -512,7 +472,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 +497,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 +509,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();
@@ -573,7 +522,7 @@
         WindowManager.LayoutParams lp =
             (android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams();
         lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
-        WindowManagerImpl.getDefault().updateViewLayout(mNavigationBarView, lp);
+        mWindowManager.updateViewLayout(mNavigationBarView, lp);
     }
 
     @Override
@@ -582,7 +531,7 @@
         WindowManager.LayoutParams lp =
             (android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams();
         lp.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
-        WindowManagerImpl.getDefault().updateViewLayout(mNavigationBarView, lp);
+        mWindowManager.updateViewLayout(mNavigationBarView, lp);
     }
 
     protected int getStatusBarGravity() {
@@ -598,10 +547,6 @@
         return mNaturalBarHeight;
     }
 
-    private int getCloseViewHeight() {
-        return mCloseViewHeight;
-    }
-
     private View.OnClickListener mRecentsClickListener = new View.OnClickListener() {
         public void onClick(View v) {
             toggleRecentApps();
@@ -612,6 +557,7 @@
     private Runnable mShowSearchPanel = new Runnable() {
         public void run() {
             showSearchPanel();
+            awakenDreams();
         }
     };
 
@@ -628,17 +574,28 @@
             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(getRecentTasksLoader());
         mNavigationBarView.getHomeButton().setOnTouchListener(mHomeSearchActionListener);
         updateSearchPanel();
     }
@@ -650,8 +607,7 @@
 
         prepareNavigationBarView();
 
-        WindowManagerImpl.getDefault().addView(
-                mNavigationBarView, getNavigationBarLayoutParams());
+        mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams());
     }
 
     private void repositionNavigationBar() {
@@ -659,8 +615,7 @@
 
         prepareNavigationBarView();
 
-        WindowManagerImpl.getDefault().updateViewLayout(
-                mNavigationBarView, getNavigationBarLayoutParams());
+        mWindowManager.updateViewLayout(mNavigationBarView, getNavigationBarLayoutParams());
     }
 
     private WindowManager.LayoutParams getNavigationBarLayoutParams() {
@@ -671,10 +626,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 +640,6 @@
     }
 
     private void addIntruderView() {
-        final int height = getStatusBarHeight();
-
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.WRAP_CONTENT,
@@ -703,7 +657,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) {
@@ -778,6 +732,10 @@
          */
 
         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");
             try {
@@ -821,12 +779,6 @@
         setAreThereNotifications();
     }
 
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        updateRecentsPanel();
-        updateShowSearchHoldoff();
-    }
-
     private void updateShowSearchHoldoff() {
         mShowSearchHoldoff = mContext.getResources().getInteger(
             R.integer.config_show_search_delay);
@@ -843,9 +795,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>();
@@ -870,12 +822,6 @@
         mSettingsButton.setEnabled(isDeviceProvisioned());
     }
 
-    private void reloadAllNotificationIcons() {
-        if (mNotificationIcons == null) return;
-        mNotificationIcons.removeAllViews();
-        updateNotificationIcons();
-    }
-
     @Override
     protected void updateNotificationIcons() {
         if (mNotificationIcons == null) return;
@@ -897,10 +843,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 +870,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 +881,7 @@
         final boolean emergencyCallsShownElsewhere = mEmergencyCallLabel != null;
         final boolean makeVisible =
             !(emergencyCallsShownElsewhere && mNetworkController.isEmergencyOnly())
-            && mPile.getHeight() < (mScrollView.getHeight() - mCarrierLabelHeight);
+            && mPile.getHeight() < (mNotificationPanel.getHeight() - mCarrierLabelHeight - mNotificationHeaderHeight);
         
         if (force || mCarrierLabelVisible != makeVisible) {
             mCarrierLabelVisible = makeVisible;
@@ -1166,20 +1112,6 @@
         }
     }
 
-    final Runnable mAnimationCallback = new Runnable() {
-        @Override
-        public void run() {
-            doAnimation(mChoreographer.getFrameTimeNanos());
-        }
-    };
-
-    final Runnable mRevealAnimationCallback = new Runnable() {
-        @Override
-        public void run() {
-            doRevealAnimation(mChoreographer.getFrameTimeNanos());
-        }
-    };
-
     View.OnFocusChangeListener mFocusChangeListener = new View.OnFocusChangeListener() {
         public void onFocusChange(View v, boolean hasFocus) {
             // Because 'v' is a ViewGroup, all its children will be (un)selected
@@ -1188,7 +1120,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 +1141,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 animateCollapse() {
         animateCollapse(CommandQueue.FLAG_EXCLUDE_NONE);
     }
 
     public void animateCollapse(int flags) {
-        animateCollapse(flags, 1.0f);
-    }
-
-    public void animateCollapse(int flags, float velocityMultiplier) {
         if (SPEW) {
-            Slog.d(TAG, "animateCollapse(): mExpanded=" + mExpanded
+            Slog.d(TAG, "animateCollapse(): "
                     + " mExpandedVisible=" + mExpandedVisible
-                    + " mExpanded=" + mExpanded
                     + " mAnimating=" + mAnimating
                     + " mAnimatingReveal=" + mAnimatingReveal
                     + " mAnimY=" + mAnimY
@@ -1264,41 +1177,23 @@
             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);
+        mStatusBarView.collapseAllPanels(true);
     }
 
-    void performExpand() {
-        if (SPEW) Slog.d(TAG, "performExpand: mExpanded=" + mExpanded);
+    @Override
+    public void animateExpand() {
+        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 (false) postStartTracing();
     }
 
-    void performCollapse() {
-        if (SPEW) Slog.d(TAG, "performCollapse: mExpanded=" + mExpanded
+    void makeExpandedInvisible() {
+        if (SPEW) Slog.d(TAG, "makeExpandedInvisible: mExpandedVisible=" + mExpandedVisible
                 + " mExpandedVisible=" + mExpandedVisible);
 
         if (!mExpandedVisible) {
@@ -1306,7 +1201,7 @@
         }
 
         // Ensure the panel is fully collapsed (just in case; bug 6765842)
-        updateExpandedViewPos(0);
+        mStatusBarView.collapseAllPanels(/*animate=*/ false);
 
         mExpandedVisible = false;
         mPile.setLayoutTransitionsEnabled(false);
@@ -1319,18 +1214,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 +1229,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,128 +1276,6 @@
         }
     }
 
-    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 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);
-            }
-        }
-    }
-
-    void prepareTracking(int y, boolean opening) {
-        if (CHATTY) {
-            Slog.d(TAG, "panel: beginning to track the user's touch, y=" + y + " opening=" + opening);
-        }
-
-        mCloseView.setPressed(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);
-            }
-            updateExpandedViewPos(y + mViewDelta);
-        }
-    }
-
-    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) {
         if (SPEW) {
             Slog.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled="
@@ -1583,105 +1289,13 @@
             }
         }
 
-        if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
-            return false;
-        }
+        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);
-            }
-
-        }
         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
@@ -1777,7 +1391,7 @@
 
     private void notifyUiVisibilityChanged() {
         try {
-            mWindowManager.statusBarVisibilityChanged(mSystemUiVisibility);
+            mWindowManagerService.statusBarVisibilityChanged(mSystemUiVisibility);
         } catch (RemoteException ex) {
         }
     }
@@ -1802,68 +1416,11 @@
         mCommandQueue.setNavigationIconHints(
                 altBack ? (mNavigationIconHints | StatusBarManager.NAVIGATION_HINT_BACK_ALT)
                         : (mNavigationIconHints & ~StatusBarManager.NAVIGATION_HINT_BACK_ALT));
+        mSettingsPanel.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 +1430,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
@@ -1943,8 +1503,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 +1519,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 +1567,9 @@
             }
         }
 
+        pw.print("  status bar gestures: ");
+        mGestureRec.dump(fd, pw, args);
+
         mNetworkController.dump(fd, pw, args);
     }
 
@@ -2040,7 +1601,7 @@
         lp.packageName = mContext.getPackageName();
 
         makeStatusBarView();
-        WindowManagerImpl.getDefault().addView(mStatusBarWindow, lp);
+        mWindowManager.addView(mStatusBarWindow, lp);
     }
 
     void setNotificationIconVisibility(boolean visible, int anim) {
@@ -2066,88 +1627,26 @@
     }
 
     @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();
-
-        // 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;
-
+    public void updateExpandedViewPos(int thingy) {
+        // TODO
+        if (DEBUG) Slog.v(TAG, "updateExpandedViewPos");
         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);
+        lp = (FrameLayout.LayoutParams) mSettingsPanel.getLayoutParams();
+        lp.gravity = mSettingsPanelGravity;
+        lp.rightMargin = mNotificationPanelMarginPx;
+        mSettingsPanel.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);
-        }
-        
         updateCarrierLabelVisibility(false);
     }
 
+    // called by makeStatusbar and also by PhoneStatusBarView
     void updateDisplaySize() {
         mDisplay.getMetrics(mDisplayMetrics);
+        mGestureRec.tag("display", 
+                String.format("%dx%d", mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels));
     }
 
     void performDisableActions(int net) {
@@ -2185,9 +1684,6 @@
     }
 
     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
@@ -2224,6 +1720,9 @@
                         mPostCollapseCleanup = new Runnable() {
                             @Override
                             public void run() {
+                                if (DEBUG) {
+                                    Slog.v(TAG, "running post-collapse cleanup");
+                                }
                                 try {
                                     mPile.setViewRemoval(true);
                                     mBarService.onClearAllNotifications();
@@ -2271,14 +1770,16 @@
                 ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
             } catch (RemoteException e) {
             }
-            v.getContext().startActivity(new Intent(Settings.ACTION_SETTINGS)
-                    .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+            v.getContext().startActivityAsUser(new Intent(Settings.ACTION_SETTINGS)
+                    .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
+                    new UserHandle(UserHandle.USER_CURRENT));
             animateCollapse();
         }
     };
 
     private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         public void onReceive(Context context, Intent intent) {
+            Slog.v(TAG, "onReceive: " + intent);
             String action = intent.getAction();
             if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
                 int flags = CommandQueue.FLAG_EXCLUDE_NONE;
@@ -2292,16 +1793,31 @@
             }
             else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
                 // no waiting!
-                performCollapse();
+                makeExpandedInvisible();
             }
             else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
+                if (DEBUG) {
+                    Slog.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration());
+                }
                 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();
             }
         }
     };
 
+    @Override
+    public void userSwitched(int newUserId) {
+        if (MULTIUSER_DEBUG) mNotificationPanelDebugText.setText("USER " + newUserId);
+        animateCollapse();
+        updateNotificationIcons();
+    }
+    
     private void setIntruderAlertVisibility(boolean vis) {
         if (!ENABLE_INTRUDERS) return;
         if (DEBUG) {
@@ -2337,6 +1853,10 @@
         if (mClearButton instanceof TextView) {
             ((TextView)mClearButton).setText(context.getText(R.string.status_bar_clear_all_button));
         }
+
+        // Update the QuickSettings container
+        ((SettingsPanelView) mSettingsPanel).updateResources();
+
         loadDimens();
     }
 
@@ -2377,11 +1897,15 @@
 
         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;
+        }
+        mSettingsPanelGravity = res.getInteger(R.integer.settings_panel_layout_gravity);
+        if (mSettingsPanelGravity <= 0) {
+            mSettingsPanelGravity = Gravity.RIGHT | Gravity.TOP;
         }
         getNinePatchPadding(res.getDrawable(R.drawable.notification_panel_bg), mNotificationPanelBackgroundPadding);
         final int notificationPanelDecorationHeight =
@@ -2394,6 +1918,7 @@
             + res.getDimensionPixelSize(R.dimen.close_handle_underlap);
 
         mCarrierLabelHeight = res.getDimensionPixelSize(R.dimen.carrier_label_height);
+        mNotificationHeaderHeight = res.getDimensionPixelSize(R.dimen.notification_panel_header_height);
 
         if (false) Slog.v(TAG, "updateResources");
     }
@@ -2444,7 +1969,7 @@
 
     @Override
     protected boolean shouldDisableNavbarGestures() {
-        return mExpanded || (mDisabled & StatusBarManager.DISABLE_HOME) != 0;
+        return mExpandedVisible || (mDisabled & StatusBarManager.DISABLE_HOME) != 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..8fe525c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -16,12 +16,17 @@
 
 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.content.res.Resources;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Rect;
 import android.os.SystemClock;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
@@ -34,133 +39,50 @@
 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";
-
-    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;
-
-    Rect mButtonBounds = new Rect();
-    boolean mCapturingEvents = true;
+    PhoneStatusBar mBar;
+    int mScrimColor;
+    float mMinFlingGutter;
+    float mNotificationWidth;
+    boolean mFullWidthNotifications;
+    PanelView mFadingPanel = null;
+    PanelView mNotificationPanel, mSettingsPanel;
 
     public PhoneStatusBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
 
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mNotificationIcons = (ViewGroup)findViewById(R.id.notificationIcons);
-        mStatusIcons = (ViewGroup)findViewById(R.id.statusIcons);
+    public void setBar(PhoneStatusBar bar) {
+        mBar = bar;
     }
 
     @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() {
+        Resources res = getContext().getResources();
+        mScrimColor = res.getColor(R.color.notification_panel_scrim_color);
+        mMinFlingGutter = res.getDimension(R.dimen.settings_panel_fling_gutter);
+        mFullWidthNotifications = false;
+        try {
+            mNotificationWidth = res.getDimension(R.dimen.notification_panel_width);
+        } catch (Resources.NotFoundException ex) {
+            mFullWidthNotifications = true;
         }
     }
 
-    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;
+        }
     }
 
     @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 +99,70 @@
         }
         return false;
     }
+
+    @Override
+    public PanelView selectPanelForTouchX(float x) {
+        // 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 = (float) getMeasuredWidth();
+        final float gutter = w - mNotificationWidth;
+        final boolean useGutter = !mFullWidthNotifications && gutter > mMinFlingGutter;
+        final float threshold = 1.0f - (gutter / w);
+        final float f = x / w;
+        if ((useGutter && f > threshold && mSettingsPanel.getExpandedFraction() != 1.0f) ||
+            mNotificationPanel.getExpandedFraction() == 1.0f) {
+            return mSettingsPanel;
+        }
+        return mNotificationPanel;
+    }
+
+    @Override
+    public void onPanelPeeked() {
+        super.onPanelPeeked();
+        mBar.makeExpandedVisible(true);
+        if (mFadingPanel == null) {
+            mFadingPanel = mTouchingPanel;
+        }
+    }
+
+    @Override
+    public void onAllPanelsCollapsed() {
+        super.onAllPanelsCollapsed();
+        mBar.makeExpandedInvisible();
+        mFadingPanel = null;
+    }
+
+    @Override
+    public void onPanelFullyOpened(PanelView openPanel) {
+        mFadingPanel = openPanel;
+    }
+
+    @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 pv, float frac) {
+        super.panelExpansionChanged(pv, frac);
+
+        if (mFadingPanel == pv 
+                && mScrimColor != 0 && ActivityManager.isHighEndGfx()) {
+            // woo, special effects
+            final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2.2f))));
+            // attenuate background color alpha by k
+            final int color = (int) ((float)(mScrimColor >>> 24) * k) << 24 | (mScrimColor & 0xFFFFFF);
+            mBar.mStatusBarWindow.setBackgroundColor(color);
+        }
+
+        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..9fb6d7c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -0,0 +1,709 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.Dialog;
+import android.app.PendingIntent;
+import android.bluetooth.BluetoothDevice;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.CursorLoader;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.Loader;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.graphics.drawable.LevelListDrawable;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.WifiDisplay;
+import android.hardware.display.WifiDisplayStatus;
+import android.net.Uri;
+import android.os.Debug;
+import android.provider.ContactsContract;
+import android.provider.Settings;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.android.internal.view.RotationPolicy;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.QuickSettingsModel.BrightnessState;
+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.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 java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Set;
+
+
+/**
+ *
+ */
+class QuickSettings {
+
+    private Context mContext;
+    private PanelBar mBar;
+    private QuickSettingsModel mModel;
+    private QuickSettingsContainerView mContainerView;
+
+    private DisplayManager mDisplayManager;
+    private WifiDisplayStatus mWifiDisplayStatus;
+    private WifiDisplayListAdapter mWifiDisplayListAdapter;
+    
+    private BrightnessController mBrightnessController;
+    private BluetoothController mBluetoothController;
+    private Dialog mBrightnessDialog;
+
+    private CursorLoader mUserInfoLoader;
+
+    private LevelListDrawable mBatteryLevels;
+    private LevelListDrawable mChargingBatteryLevels;
+
+    // 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();
+        mWifiDisplayListAdapter = new WifiDisplayListAdapter(context);
+
+        Resources r = mContext.getResources();
+        mBatteryLevels = (LevelListDrawable) r.getDrawable(R.drawable.qs_sys_battery);
+        mChargingBatteryLevels =
+                (LevelListDrawable) r.getDrawable(R.drawable.qs_sys_battery_charging);
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED);
+        mContext.registerReceiver(mReceiver, filter);
+    }
+
+    void setBar(PanelBar bar) {
+        mBar = bar;
+    }
+
+    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);
+    }
+
+    private void queryForUserInformation() {
+        Uri userContactUri = Uri.withAppendedPath(
+            ContactsContract.Profile.CONTENT_URI,
+            ContactsContract.Contacts.Data.CONTENT_DIRECTORY);
+
+        String[] selectArgs = {
+            ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
+            ContactsContract.CommonDataKinds.Photo.PHOTO
+        };
+        String where = String.format("(%s = ? OR %s = ?) AND %s IS NULL",
+            ContactsContract.Contacts.Data.MIMETYPE,
+            ContactsContract.Contacts.Data.MIMETYPE,
+            ContactsContract.RawContacts.ACCOUNT_TYPE);
+        String[] whereArgs = {
+            ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE,
+            ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE
+        };
+
+        mUserInfoLoader = new CursorLoader(mContext, userContactUri, selectArgs, where, whereArgs,
+                null);
+        mUserInfoLoader.registerListener(0,
+                new Loader.OnLoadCompleteListener<Cursor>() {
+                    @Override
+                    public void onLoadComplete(Loader<Cursor> loader,
+                            Cursor cursor) {
+                        if (cursor != null && cursor.moveToFirst()) {
+                            String name = cursor.getString(0); // DISPLAY_NAME
+                            mModel.setUserTileInfo(name, null);
+                            /*
+                            byte[] photoData = cursor.getBlob(0);
+                            Bitmap b =
+                                BitmapFactory.decodeByteArray(photoData, 0, photoData.length);
+                             */
+                        }
+                        mUserInfoLoader.stopLoading();
+                    }
+                });
+        mUserInfoLoader.startLoading();
+    }
+
+    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();
+    }
+
+    private void startSettingsActivity(String action) {
+        Intent intent = new Intent(action);
+        startSettingsActivity(intent);
+    }
+    private void startSettingsActivity(Intent intent) {
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        mBar.collapseAllPanels(true);
+        mContext.startActivity(intent);
+    }
+
+    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);
+        mModel.addUserTile(userTile, new QuickSettingsModel.RefreshCallback() {
+            @Override
+            public void refreshView(QuickSettingsTileView view, State state) {
+                UserState us = (UserState) state;
+                TextView tv = (TextView) view.findViewById(R.id.user_textview);
+                tv.setText(state.label);
+                if (us.avatar != null) {
+                    tv.setCompoundDrawables(null, us.avatar, null, null);
+                }
+            }
+        });
+        parent.addView(userTile);
+        mDynamicSpannedTiles.add(userTile);
+
+        // 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) {
+                // 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.addTimeTile(timeTile, new QuickSettingsModel.RefreshCallback() {
+            @Override
+            public void refreshView(QuickSettingsTileView view, State alarmState) {
+                TextView tv = (TextView) view.findViewById(R.id.alarm_textview);
+                tv.setText(alarmState.label);
+                tv.setVisibility(alarmState.enabled ? View.VISIBLE : View.GONE);
+            }
+        });
+        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);
+            }
+        });
+        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) {
+                TextView tv = (TextView) view.findViewById(R.id.wifi_textview);
+                tv.setCompoundDrawablesWithIntrinsicBounds(0, state.iconId, 0, 0);
+                tv.setText(state.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);
+                }
+            });
+            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);
+            }
+        });
+        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);
+            }
+        });
+        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) {
+                    TextView tv = (TextView) view.findViewById(R.id.bluetooth_textview);
+                    tv.setCompoundDrawablesWithIntrinsicBounds(0, state.iconId, 0, 0);
+
+                    Resources r = mContext.getResources();
+                    String label = null;
+                    /*
+                    //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());
+                    }
+                    */
+                    if (label == null) {
+                        label = r.getString(R.string.quick_settings_bluetooth_label);
+                    }
+                    tv.setText(label);
+                }
+            });
+            parent.addView(bluetoothTile);
+        }
+
+        // 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);
+            }
+        });
+        parent.addView(brightnessTile);
+    }
+
+    private void addTemporaryTiles(final ViewGroup parent, final LayoutInflater inflater) {
+        // 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) {
+                mBar.collapseAllPanels(true);
+                showWifiDisplayDialog();
+            }
+        });
+        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);
+                view.setVisibility(state.enabled ? View.VISIBLE : View.GONE);
+            }
+        });
+        parent.addView(wifiDisplayTile);
+
+        // 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);
+
+        /*
+        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 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);
+        }
+        mContainerView.requestLayout();
+    }
+    
+    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,
+                    (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().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
+        }
+        if (!mBrightnessDialog.isShowing()) {
+            mBrightnessDialog.show();
+        }
+    }
+
+    // Wifi Display
+    private void showWifiDisplayDialog() {
+        mDisplayManager.scanWifiDisplays();
+        updateWifiDisplayStatus();
+
+        Dialog dialog = new Dialog(mContext);
+        dialog.setContentView(R.layout.wifi_display_dialog);
+        dialog.setCanceledOnTouchOutside(true);
+        dialog.setTitle(R.string.wifi_display_dialog_title);
+
+        Button scanButton = (Button)dialog.findViewById(R.id.scan);
+        scanButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                mDisplayManager.scanWifiDisplays();
+            }
+        });
+
+        Button disconnectButton = (Button)dialog.findViewById(R.id.disconnect);
+        disconnectButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                mDisplayManager.disconnectWifiDisplay();
+            }
+        });
+
+        ListView list = (ListView)dialog.findViewById(R.id.list);
+        list.setAdapter(mWifiDisplayListAdapter);
+        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            @Override
+            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+                WifiDisplay display = mWifiDisplayListAdapter.getItem(position);
+                mDisplayManager.connectWifiDisplay(display.getDeviceAddress());
+            }
+        });
+
+        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+        dialog.show();
+    }
+
+    private void updateWifiDisplayStatus() {
+        applyWifiDisplayStatus(mDisplayManager.getWifiDisplayStatus());
+    }
+
+    private void applyWifiDisplayStatus(WifiDisplayStatus status) {
+        mWifiDisplayStatus = status;
+
+        mWifiDisplayListAdapter.clear();
+        mWifiDisplayListAdapter.addAll(status.getKnownDisplays());
+        if (status.getActiveDisplay() != null
+                && !contains(status.getKnownDisplays(), status.getActiveDisplay())) {
+            mWifiDisplayListAdapter.add(status.getActiveDisplay());
+        }
+        mWifiDisplayListAdapter.sort(mWifiDisplayComparator);
+
+        mModel.onWifiDisplayStateChanged(status);
+    }
+
+    private static boolean contains(WifiDisplay[] displays, WifiDisplay display) {
+        for (WifiDisplay d : displays) {
+            if (d.equals(display)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent.getAction().equals(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED)) {
+                WifiDisplayStatus status = (WifiDisplayStatus)intent.getParcelableExtra(
+                        DisplayManager.EXTRA_WIFI_DISPLAY_STATUS);
+                applyWifiDisplayStatus(status);
+            }
+        }
+    };
+
+    private final class WifiDisplayListAdapter extends ArrayAdapter<WifiDisplay> {
+        private final LayoutInflater mInflater;
+
+        public WifiDisplayListAdapter(Context context) {
+            super(context, android.R.layout.simple_list_item_2);
+            mInflater = LayoutInflater.from(context);
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            WifiDisplay item = getItem(position);
+            View view = convertView;
+            if (view == null) {
+                view = mInflater.inflate(android.R.layout.simple_list_item_2,
+                        parent, false);
+            }
+            TextView headline = (TextView) view.findViewById(android.R.id.text1);
+            TextView subText = (TextView) view.findViewById(android.R.id.text2);
+            headline.setText(item.getDeviceName());
+
+            int state = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED;
+            if (item.equals(mWifiDisplayStatus.getActiveDisplay())) {
+                state = mWifiDisplayStatus.getActiveDisplayState();
+            }
+            switch (state) {
+                case WifiDisplayStatus.DISPLAY_STATE_CONNECTING:
+                    subText.setText(R.string.wifi_display_state_connecting);
+                    break;
+                case WifiDisplayStatus.DISPLAY_STATE_CONNECTED:
+                    subText.setText(R.string.wifi_display_state_connected);
+                    break;
+                case WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED:
+                default:
+                    subText.setText(R.string.wifi_display_state_available);
+                    break;
+            }
+            return view;
+        }
+    }
+
+    private final Comparator<WifiDisplay> mWifiDisplayComparator = new Comparator<WifiDisplay>() {
+        @Override
+        public int compare(WifiDisplay lhs, WifiDisplay rhs) {
+            int c = lhs.getDeviceName().compareToIgnoreCase(rhs.getDeviceName());
+            if (c == 0) {
+                c = lhs.getDeviceAddress().compareToIgnoreCase(rhs.getDeviceAddress());
+            }
+            return c;
+        }
+    };
+}
\ No newline at end of file
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..27cfab1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsContainerView.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.systemui.statusbar.phone;
+
+import android.animation.LayoutTransition;
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.AttributeSet;
+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 = 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);
+            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..485b3e5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.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.provider.Settings;
+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.LocationController.LocationGpsStateChangeCallback;
+import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
+
+import java.util.List;
+
+
+class QuickSettingsModel implements BluetoothStateChangeCallback,
+        NetworkSignalChangedCallback,
+        BatteryStateChangeCallback,
+        LocationGpsStateChangeCallback,
+        BrightnessStateChangeCallback {
+
+    /** 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;
+        int dataTypeIconId;
+    }
+    static class UserState extends State {
+        Drawable avatar;
+    }
+    static class BrightnessState extends State {
+        boolean autoBrightness;
+    }
+
+    /** 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);
+        }
+    }
+
+    private Context mContext;
+    private Handler mHandler;
+    private NextAlarmObserver mNextAlarmObserver;
+
+    private QuickSettingsTileView mUserTile;
+    private RefreshCallback mUserCallback;
+    private UserState mUserState = new UserState();
+
+    private QuickSettingsTileView mTimeTile;
+    private RefreshCallback mTimeAlarmCallback;
+    private State mTimeAlarmState = new State();
+
+    private QuickSettingsTileView mAirplaneModeTile;
+    private RefreshCallback mAirplaneModeCallback;
+    private State mAirplaneModeState = new State();
+
+    private QuickSettingsTileView mWifiTile;
+    private RefreshCallback mWifiCallback;
+    private State mWifiState = new State();
+
+    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 State mBluetoothState = new State();
+
+    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;
+    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();
+
+    public QuickSettingsModel(Context context) {
+        mContext = context;
+        mHandler = new Handler();
+        mNextAlarmObserver = new NextAlarmObserver(mHandler);
+        mNextAlarmObserver.startObserving();
+
+        IntentFilter alarmIntentFilter = new IntentFilter();
+        alarmIntentFilter.addAction(Intent.ACTION_ALARM_CHANGED);
+        context.registerReceiver(mAlarmIntentReceiver, alarmIntentFilter);
+    }
+
+    // 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;
+        mTimeAlarmCallback = cb;
+        mTimeAlarmCallback.refreshView(view, mTimeAlarmState);
+    }
+    void onAlarmChanged(Intent intent) {
+        mTimeAlarmState.enabled = intent.getBooleanExtra("alarmSet", false);
+        mTimeAlarmCallback.refreshView(mTimeTile, mTimeAlarmState);
+    }
+    void onNextAlarmChanged() {
+        mTimeAlarmState.label = Settings.System.getString(mContext.getContentResolver(),
+                Settings.System.NEXT_ALARM_FORMATTED);
+        mTimeAlarmCallback.refreshView(mTimeTile, mTimeAlarmState);
+    }
+
+    // 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;
+        mAirplaneModeCallback.refreshView(mAirplaneModeTile, mAirplaneModeState);
+    }
+    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);
+        mAirplaneModeCallback.refreshView(mAirplaneModeTile, mAirplaneModeState);
+    }
+
+    // Wifi
+    void addWifiTile(QuickSettingsTileView view, RefreshCallback cb) {
+        mWifiTile = view;
+        mWifiCallback = cb;
+        mWifiCallback.refreshView(mWifiTile, mWifiState);
+    }
+    // NetworkSignalChanged callback
+    @Override
+    public void onWifiSignalChanged(boolean enabled, int wifiSignalIconId, String enabledDesc) {
+        // TODO: If view is in awaiting state, disable
+        Resources r = mContext.getResources();
+        mWifiState.iconId = enabled && (wifiSignalIconId > 0)
+                ? wifiSignalIconId
+                : R.drawable.ic_qs_wifi_no_network;
+        mWifiState.label = enabled
+                ? enabledDesc
+                : r.getString(R.string.quick_settings_wifi_no_network);
+        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,
+            int dataTypeIconId, 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.dataTypeIconId = enabled && (dataTypeIconId > 0)
+                    ? dataTypeIconId
+                    : 0;
+            mRSSIState.label = enabled
+                    ? 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();
+        onBluetoothStateChange(adapter.isEnabled());
+    }
+    boolean deviceSupportsBluetooth() {
+        return (BluetoothAdapter.getDefaultAdapter() != null);
+    }
+    // BluetoothController callback
+    @Override
+    public void onBluetoothStateChange(boolean on) {
+        // TODO: If view is in awaiting state, disable
+        Resources r = mContext.getResources();
+        mBluetoothState.enabled = on;
+        if (on) {
+            mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_on;
+        } else {
+            mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_off;
+        }
+        mBluetoothCallback.refreshView(mBluetoothTile, mBluetoothState);
+    }
+
+    // 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);
+    }
+
+    // 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);
+    }
+
+    // Wifi Display
+    void addWifiDisplayTile(QuickSettingsTileView view, RefreshCallback cb) {
+        mWifiDisplayTile = view;
+        mWifiDisplayCallback = cb;
+    }
+    public void onWifiDisplayStateChanged(WifiDisplayStatus status) {
+        mWifiDisplayState.enabled = status.isEnabled();
+        if (status.getActiveDisplay() != null) {
+            mWifiDisplayState.label = status.getActiveDisplay().getDeviceName();
+        } else {
+            mWifiDisplayState.label = mContext.getString(
+                    R.string.quick_settings_wifi_display_no_connection_label);
+        }
+        mWifiDisplayCallback.refreshView(mWifiDisplayTile, mWifiDisplayState);
+
+    }
+
+    // IME
+    void addImeTile(QuickSettingsTileView view, RefreshCallback cb) {
+        mImeTile = view;
+        mImeCallback = cb;
+        mImeCallback.refreshView(mImeTile, mImeState);
+    }
+    void onImeWindowStatusChanged(boolean visible) {
+        InputMethodManager imm =
+                (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
+        List<InputMethodInfo> imis = imm.getInputMethodList();
+
+        mImeState.enabled = visible;
+        mImeState.label = getCurrentInputMethodName(mContext, mContext.getContentResolver(),
+                imm, imis, mContext.getPackageManager());
+        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);
+        }
+    }
+
+    // Brightness
+    void addBrightnessTile(QuickSettingsTileView view, RefreshCallback cb) {
+        mBrightnessTile = view;
+        mBrightnessCallback = cb;
+        onBrightnessLevelChanged();
+    }
+    @Override
+    public void onBrightnessLevelChanged() {
+        int mode = Settings.System.getInt(mContext.getContentResolver(),
+                Settings.System.SCREEN_BRIGHTNESS_MODE,
+                Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
+        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;
+        mBrightnessCallback.refreshView(mBrightnessTile, mBrightnessState);
+    }
+
+}
\ No newline at end of file
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..4a7a424
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.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.systemui.statusbar.phone;
+
+import android.animation.LayoutTransition;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+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.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;
+
+    public SettingsPanelView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        mQSContainer = (QuickSettingsContainerView) findViewById(R.id.quick_settings_container);
+        mQS = new QuickSettings(getContext(), mQSContainer);
+    }
+
+    @Override
+    public void setBar(PanelBar panelBar) {
+        super.setBar(panelBar);
+
+        if (mQS != null) {
+            mQS.setBar(panelBar);
+        }
+    }
+
+    @Override
+    public void setImeWindowStatus(boolean visible) {
+        if (mQS != null) {
+            mQS.setImeWindowStatus(visible);
+        }
+    }
+
+    @Override
+    public void setup(NetworkController networkController, BluetoothController bluetoothController,
+            BatteryController batteryController, LocationController locationController) {
+        super.setup(networkController, bluetoothController, batteryController, 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) {
+        ((PhoneStatusBarView) mBar).mBar.getGestureRecorder().tag(
+            "fling " + ((vel > 0) ? "open" : "closed"),
+            "settings,v=" + vel);
+        super.fling(vel, always);
+    }
+}
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..e0b7fe6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -21,6 +21,7 @@
 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;
@@ -36,6 +37,7 @@
 
     private ExpandHelper mExpandHelper;
     private NotificationRowLayout latestItems;
+    private NotificationPanelView mNotificationPanel;
 
     PhoneStatusBar mService;
 
@@ -49,6 +51,7 @@
         super.onAttachedToWindow();
         latestItems = (NotificationRowLayout) findViewById(R.id.latestItems);
         ScrollView scroller = (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);
@@ -71,21 +74,31 @@
 
     @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()) {
+            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;
     }
 }
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/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..0567371 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,25 @@
             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() {
+        Set<BluetoothDevice> devices = BluetoothAdapter.getDefaultAdapter().getBondedDevices();
+        if (devices != null) {
+            mBondedDevices.clear();
+            for (BluetoothDevice device : devices) {
+                if (device.getBondState() != BluetoothDevice.BOND_NONE) {
+                    mBondedDevices.add(device);
+                }
+            }
+        } else {
+            mBondedDevices.clear();
+        }
     }
 
     public void handleAdapterStateChange(int adapterState) {
@@ -98,5 +134,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..bb59420 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;
@@ -28,20 +29,35 @@
 import android.view.IWindowManager;
 import android.widget.CompoundButton;
 
+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 ArrayList<BrightnessStateChangeCallback> mChangeCallbacks =
+            new ArrayList<BrightnessStateChangeCallback>();
+
+    public interface BrightnessStateChangeCallback {
+        public void onBrightnessLevelChanged();
+    }
+
     public BrightnessController(Context context, ToggleSlider control) {
         mContext = context;
         mControl = control;
 
+        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+        mMinimumBacklight = pm.getMinimumScreenBrightnessSetting();
+        mMaximumBacklight = pm.getMaximumScreenBrightnessSetting();
+
         boolean automaticAvailable = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_automatic_brightness_available);
         mPower = IPowerManager.Stub.asInterface(ServiceManager.getService("power"));
@@ -65,20 +81,24 @@
             value = Settings.System.getInt(mContext.getContentResolver(), 
                     Settings.System.SCREEN_BRIGHTNESS);
         } catch (SettingNotFoundException ex) {
-            value = MAXIMUM_BACKLIGHT;
+            value = mMaximumBacklight;
         }
 
-        control.setMax(MAXIMUM_BACKLIGHT - MINIMUM_BACKLIGHT);
-        control.setValue(value - MINIMUM_BACKLIGHT);
+        control.setMax(mMaximumBacklight - mMinimumBacklight);
+        control.setValue(value - mMinimumBacklight);
 
         control.setOnChangedListener(this);
     }
 
+    public void addStateChangedCallback(BrightnessStateChangeCallback cb) {
+        mChangeCallbacks.add(cb);
+    }
+
     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);
         if (!automatic) {
-            final int val = value + MINIMUM_BACKLIGHT;
+            final int val = value + mMinimumBacklight;
             setBrightness(val);
             if (!tracking) {
                 AsyncTask.execute(new Runnable() {
@@ -89,6 +109,10 @@
                     });
             }
         }
+
+        for (BrightnessStateChangeCallback cb : mChangeCallbacks) {
+            cb.onBrightnessLevelChanged();
+        }
     }
 
     private void setMode(int mode) {
@@ -98,7 +122,7 @@
     
     private void setBrightness(int brightness) {
         try {
-            mPower.setBacklightBrightness(brightness);
+            mPower.setTemporaryScreenBrightnessSettingOverride(brightness);
         } catch (RemoteException ex) {
         }        
     }
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/DateView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
index c19550b..640dcca 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,7 +86,7 @@
         return 0;
     }
 
-    private final void updateClock() {
+    protected void updateClock() {
         final Context context = getContext();
         Date now = new Date();
         CharSequence dow = DateFormat.format("EEEE", now);
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..f864d04 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();
@@ -84,14 +97,18 @@
         }
         
         try {
+            // XXX WHAT TO DO ABOUT MULTI-USER?
             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 +125,20 @@
                         null, 
                         GPS_NOTIFICATION_ID, 
                         n,
-                        idOut);
+                        idOut,
+                        UserHandle.USER_CURRENT);
+
+                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_CURRENT);
+
+                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..ee82777 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,13 @@
         void setIsAirplaneMode(boolean is, int airplaneIcon);
     }
 
+    public interface NetworkSignalChangedCallback {
+        void onWifiSignalChanged(boolean enabled, int wifiSignalIconId, String description);
+        void onMobileDataSignalChanged(boolean enabled, int mobileSignalIconId, int dataTypeIconId,
+                String description);
+        void onAirplaneModeChanged(boolean enabled);
+    }
+
     /**
      * Construct this controller object and register for updates.
      */
@@ -299,6 +307,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 +342,29 @@
         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, wifiDesc);
+
+        if (isEmergencyOnly()) {
+            cb.onMobileDataSignalChanged(false, mQSPhoneSignalIconId, mQSDataTypeIconId, null);
+        } else {
+            if (mIsWimaxEnabled && mWimaxConnected) {
+                // Wimax is special
+                cb.onMobileDataSignalChanged(true, mQSPhoneSignalIconId, mQSDataTypeIconId,
+                        mNetworkName);
+            } else {
+                // Normal mobile data
+                cb.onMobileDataSignalChanged(mHasMobileDataFeature, mQSPhoneSignalIconId,
+                        mQSDataTypeIconId, mNetworkName);
+            }
+        }
+        cb.onAirplaneModeChanged(mAirplaneMode);
+    }
+
     public void setStackedMode(boolean stacked) {
         mDataAndWifiStacked = true;
     }
@@ -475,19 +511,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 +556,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 +570,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 +579,7 @@
                     if (!mShowAtLeastThreeGees) {
                         mDataIconList = TelephonyIcons.DATA_G[mInetCondition];
                         mDataTypeIconId = 0;
+                        mQSDataTypeIconId = 0;
                         mContentDescriptionDataType = mContext.getString(
                                 R.string.accessibility_data_connection_gprs);
                         break;
@@ -548,6 +590,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 +600,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 +611,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 +627,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 +638,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 +651,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 +666,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 +683,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 +864,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,6 +998,7 @@
 
         if (!mHasMobileDataFeature) {
             mDataSignalIconId = mPhoneSignalIconId = 0;
+            mQSPhoneSignalIconId = 0;
             mobileLabel = "";
         } else {
             // We want to show the carrier name if in service and either:
@@ -1051,7 +1109,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 +1139,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 +1168,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 +1189,9 @@
             for (SignalCluster cluster : mSignalClusters) {
                 refreshSignalCluster(cluster);
             }
+            for (NetworkSignalChangedCallback cb : mSignalsChangedCallbacks) {
+                notifySignalsChangedCallbacks(cb);
+            }
         }
 
         if (mLastAirplaneMode != mAirplaneMode) {
@@ -1320,6 +1388,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 +1404,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 +1422,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/QuickSettingsDateView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/QuickSettingsDateView.java
new file mode 100644
index 0000000..c52f94b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/QuickSettingsDateView.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.systemui.statusbar.policy;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.text.format.DateFormat;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewParent;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+
+import java.util.Date;
+
+public final class QuickSettingsDateView extends DateView {
+
+    public QuickSettingsDateView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    protected void updateClock() {
+        final Context context = getContext();
+        Date now = new Date();
+        CharSequence dow = DateFormat.format("MMM d, yyyy", now);
+        setText(dow);
+    }
+}
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/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/SettingsView.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
index 537ff66..c45ac3f 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;
@@ -117,8 +118,9 @@
     // Settings
     // ----------------------------
     private void onClickSettings() {
-        getContext().startActivity(new Intent(Settings.ACTION_SETTINGS)
-                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+        getContext().startActivityAsUser(new Intent(Settings.ACTION_SETTINGS)
+                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
+                new UserHandle(UserHandle.USER_CURRENT));
         getStatusBarManager().collapse();
     }
 }
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..7153ec7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -53,11 +53,9 @@
 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;
 
@@ -70,9 +68,9 @@
 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 +84,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 +122,6 @@
     int mMenuNavIconWidth = -1;
     private int mMaxNotificationIcons = 5;
 
-    IWindowManager mWindowManager;
-
     TabletStatusBarView mStatusBarView;
     View mNotificationArea;
     View mNotificationTrigger;
@@ -232,10 +227,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 +237,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 +302,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 +330,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 +353,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(getRecentTasksLoader());
 
         mPile = (NotificationRowLayout)mNotificationPanel.findViewById(R.id.content);
         mPile.removeAllViews();
@@ -384,7 +372,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 +387,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 +439,7 @@
         }
     }
 
+    @Override
     public View getStatusBarView() {
         return mStatusBarView;
     }
@@ -460,9 +447,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 +458,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 +479,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 +636,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 +651,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 +664,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 +673,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 +695,7 @@
         }
         if (lp.height != height) {
             lp.height = height;
-            final WindowManager wm = WindowManagerImpl.getDefault();
-            wm.updateViewLayout(mStatusBarView, lp);
+            mWindowManager.updateViewLayout(mStatusBarView, lp);
         }
     }
 
@@ -1073,7 +1050,7 @@
 
     private void notifyUiVisibilityChanged() {
         try {
-            mWindowManager.statusBarVisibilityChanged(mSystemUiVisibility);
+            mWindowManagerService.statusBarVisibilityChanged(mSystemUiVisibility);
         } catch (RemoteException ex) {
         }
     }
@@ -1165,12 +1142,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 +1173,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 +1223,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 +1260,7 @@
                 mNotificationArea.postDelayed(mHiliteOnR, 100);
             } else {
                 mNotificationArea.removeCallbacks(mHiliteOnR);
-                mNotificationArea.setBackgroundDrawable(null);
+                mNotificationArea.setBackground(null);
             }
         }
 
@@ -1368,106 +1334,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();
@@ -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() {
@@ -1636,14 +1502,6 @@
                         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);
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
index d4ebe6d..932b035 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
@@ -35,7 +35,6 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.FrameLayout;
@@ -62,7 +61,8 @@
 
     private static final int ADVANCE_DELAY = 5000; // 5 seconds
 
-    private Context mContext;
+    private final Context mContext;
+    private final WindowManager mWindowManager;
 
     private ViewGroup mWindow;
     private IBinder mCurrentKey;
@@ -83,6 +83,7 @@
     public TabletTicker(TabletStatusBar bar) {
         mBar = bar;
         mContext = bar.getContext();
+        mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
         final Resources res = mContext.getResources();
         mLargeIconHeight = res.getDimensionPixelSize(
                 android.R.dimen.notification_large_icon_height);
@@ -178,7 +179,7 @@
             if (mCurrentView != null) {
                 if (mWindow == null) {
                     mWindow = makeWindow();
-                    WindowManagerImpl.getDefault().addView(mWindow, mWindow.getLayoutParams());
+                    mWindowManager.addView(mWindow, mWindow.getLayoutParams());
                 }
 
                 mWindow.addView(mCurrentView);
@@ -242,7 +243,7 @@
     public void endTransition(LayoutTransition transition, ViewGroup container,
             View view, int transitionType) {
         if (mWindowShouldClose) {
-            WindowManagerImpl.getDefault().removeView(mWindow);
+            mWindowManager.removeView(mWindow);
             mWindow = null;
             mWindowShouldClose = false;
             mBar.doneTicking();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
new file mode 100644
index 0000000..6022fd2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.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 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 {
+    View mView;
+
+    @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 animateExpand() {
+    }
+
+    @Override
+    public void animateCollapse(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;
+    }
+
+    protected View makeStatusBarView() {
+        synchronized (this) {
+            if (mView == null) {
+                mView = new View(mContext);
+            }
+        }
+        return mView;
+    }
+
+    public View getStatusBarView() {
+        return null;
+    }
+
+    protected int getStatusBarGravity() {
+        return 0;
+    }
+
+    public int getStatusBarHeight() {
+        return 0;
+    }
+
+    public void animateCollapse() {
+    }
+
+}
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/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 9999adb1..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/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..d8e361f 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -29,6 +29,7 @@
 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.Handler;
@@ -37,6 +38,8 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.os.Vibrator;
 import android.provider.Settings;
 import android.telephony.PhoneStateListener;
@@ -48,10 +51,12 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
 import android.view.WindowManagerPolicy.WindowManagerFuncs;
 import android.widget.AdapterView;
 import android.widget.BaseAdapter;
 import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
 import android.widget.TextView;
 
 import java.util.ArrayList;
@@ -87,8 +92,6 @@
     private boolean mHasTelephony;
     private boolean mHasVibrator;
 
-    private IWindowManager mIWindowManager;
-
     /**
      * @param context everything needs a context :(
      */
@@ -112,7 +115,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();
@@ -207,11 +210,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 +230,57 @@
         // 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(0, 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() {
+                                                SystemProperties.set("ctl.start", "bugreport");
+                                            }
+                                        }, 500);
+                                    }
+                                });
+                        AlertDialog dialog = builder.create();
+                        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_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();
+        List<UserInfo> users = ((UserManager) mContext.getSystemService(Context.USER_SERVICE))
+                .getUsers();
         if (users.size() > 1) {
             UserInfo currentUser;
             try {
@@ -243,14 +291,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);
                         }
@@ -439,6 +488,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 +496,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 +531,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 +848,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 +860,16 @@
      * 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);
-        }
-        return mIWindowManager;
-    }
 }
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..e761847 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -613,8 +613,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);
 
@@ -2841,6 +2840,8 @@
             mDecor = generateDecor();
             mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
             mDecor.setIsRootNamespace(true);
+            mDecor.setLayoutDirection(
+                    getContext().getResources().getConfiguration().getLayoutDirection());
         }
         if (mContentParent == null) {
             mContentParent = generateLayout(mDecor);
@@ -2850,6 +2851,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..6c62680 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -40,12 +40,11 @@
 import android.graphics.Rect;
 import android.media.AudioManager;
 import android.media.IAudioService;
-import android.os.BatteryManager;
 import android.os.Bundle;
+import android.os.FactoryTest;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.IRemoteCallback;
-import android.os.LocalPowerManager;
 import android.os.Looper;
 import android.os.Message;
 import android.os.Messenger;
@@ -55,21 +54,24 @@
 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;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.SparseIntArray;
 import android.view.Display;
 import android.view.Gravity;
 import android.view.HapticFeedbackConstants;
@@ -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;
@@ -106,11 +109,13 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
 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_SEARCH_BAR;
@@ -125,13 +130,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;
@@ -168,12 +173,10 @@
     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
@@ -182,6 +185,7 @@
     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 UNIVERSE_BACKGROUND_LAYER = 1;
     static final int WALLPAPER_LAYER = 2;
     static final int APPLICATION_LAYER = 2;
     static final int PHONE_LAYER = 3;
@@ -217,14 +221,18 @@
     static final int NAVIGATION_BAR_PANEL_LAYER = 20;
     // system-level error dialogs
     static final int SYSTEM_ERROR_LAYER = 21;
+    // used to highlight the magnified portion of a display
+    static final int MAGNIFICATION_OVERLAY_LAYER = 22;
+    // used to simulate secondary display devices
+    static final int DISPLAY_OVERLAY_LAYER = 23;
     // 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;
+    static final int DRAG_LAYER = 24;
+    static final int SECURE_SYSTEM_OVERLAY_LAYER = 25;
+    static final int BOOT_PROGRESS_LAYER = 26;
     // the (mouse) pointer layer
-    static final int POINTER_LAYER = 25;
-    static final int HIDDEN_NAV_CONSUMER_LAYER = 26;
+    static final int POINTER_LAYER = 27;
+    static final int HIDDEN_NAV_CONSUMER_LAYER = 28;
 
     static final int APPLICATION_MEDIA_SUBLAYER = -2;
     static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
@@ -277,7 +285,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
@@ -338,8 +346,6 @@
     boolean mSystemReady;
     boolean mSystemBooted;
     boolean mHdmiPlugged;
-    int mExternalDisplayWidth;
-    int mExternalDisplayHeight;
     int mUiMode;
     int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
     int mLidOpenRotation;
@@ -361,6 +367,7 @@
     boolean mScreenOnEarly = false;
     boolean mScreenOnFully = false;
     boolean mOrientationSensorEnabled = false;
+    int mLastSensorRotation = -1;
     int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
     boolean mHasSoftInput = false;
     
@@ -472,13 +479,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;
 
@@ -570,12 +570,6 @@
                     Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
             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
             updateSettings();
         }
 
@@ -731,8 +725,12 @@
         public void run() {
             // The context isn't read
             if (mLongPressOnPowerBehavior < 0) {
-                mLongPressOnPowerBehavior = mContext.getResources().getInteger(
-                        com.android.internal.R.integer.config_longPressOnPowerBehavior);
+                if (FactoryTest.isLongPressOnPowerOffEnabled()) {
+                    mLongPressOnPowerBehavior = LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
+                } else {
+                    mLongPressOnPowerBehavior = mContext.getResources().getInteger(
+                            com.android.internal.R.integer.config_longPressOnPowerBehavior);
+                }
             }
             switch (mLongPressOnPowerBehavior) {
             case LONG_PRESS_POWER_NOTHING:
@@ -744,10 +742,12 @@
                 showGlobalActionsDialog();
                 break;
             case LONG_PRESS_POWER_SHUT_OFF:
+            case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
                 mPowerKeyHandled = true;
                 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
                 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
-                mWindowManagerFuncs.shutdown();
+                mWindowManagerFuncs.shutdown(
+                        mLongPressOnPowerBehavior == LONG_PRESS_POWER_SHUT_OFF);
                 break;
             }
         }
@@ -861,16 +861,14 @@
 
     /** {@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);
@@ -896,8 +894,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,14 +928,6 @@
                     Intent.EXTRA_DOCK_STATE_UNDOCKED);
         }
 
-        // watch the plug to know whether to trigger the screen saver
-        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));
-        }
-
         mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
         mLongPressVibePattern = getLongIntArray(mContext.getResources(),
                 com.android.internal.R.array.config_longPressVibePattern);
@@ -964,7 +954,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 +986,6 @@
             }
         }
 
-        mExternalDisplayWidth = mDisplay.getRawExternalWidth();
-        mExternalDisplayHeight = mDisplay.getRawExternalHeight();
-
         mStatusBarHeight = mContext.getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.status_bar_height);
 
@@ -1021,22 +1008,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 +1038,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
@@ -1131,26 +1109,6 @@
                 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);
@@ -1229,7 +1187,7 @@
         
         if (type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
                 || type > WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) {
-            return WindowManagerImpl.ADD_OKAY;
+            return WindowManagerGlobal.ADD_OKAY;
         }
         String permission = null;
         switch (type) {
@@ -1256,10 +1214,10 @@
         if (permission != null) {
             if (mContext.checkCallingOrSelfPermission(permission)
                     != PackageManager.PERMISSION_GRANTED) {
-                return WindowManagerImpl.ADD_PERMISSION_DENIED;
+                return WindowManagerGlobal.ADD_PERMISSION_DENIED;
             }
         }
-        return WindowManagerImpl.ADD_OKAY;
+        return WindowManagerGlobal.ADD_OKAY;
     }
     
     public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
@@ -1374,6 +1332,12 @@
             return HIDDEN_NAV_CONSUMER_LAYER;
         case TYPE_DREAM:
             return SCREENSAVER_LAYER;
+        case TYPE_UNIVERSE_BACKGROUND:
+            return UNIVERSE_BACKGROUND_LAYER;
+        case TYPE_DISPLAY_OVERLAY:
+            return DISPLAY_OVERLAY_LAYER;
+        case TYPE_MAGNIFICATION_OVERLAY:
+            return MAGNIFICATION_OVERLAY_LAYER;
         }
         Log.e(TAG, "Unknown window type: " + type);
         return APPLICATION_LAYER;
@@ -1400,6 +1364,10 @@
         return STATUS_BAR_LAYER;
     }
 
+    public int getAboveUniverseLayer() {
+        return SYSTEM_ERROR_LAYER;
+    }
+
     public boolean hasSystemNavBar() {
         return mHasSystemNavBar;
     }
@@ -1453,7 +1421,8 @@
     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;
+                && attrs.type != WindowManager.LayoutParams.TYPE_WALLPAPER
+                && attrs.type != WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND;
     }
 
     /** {@inheritDoc} */
@@ -1549,7 +1518,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 +1557,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 +1568,7 @@
                         "PhoneWindowManager");
                 if (mStatusBar != null) {
                     if (mStatusBar.isAlive()) {
-                        return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
+                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
                     }
                 }
                 mStatusBar = win;
@@ -1609,7 +1579,7 @@
                         "PhoneWindowManager");
                 if (mNavigationBar != null) {
                     if (mNavigationBar.isAlive()) {
-                        return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
+                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
                     }
                 }
                 mNavigationBar = win;
@@ -1632,12 +1602,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} */
@@ -1767,15 +1737,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,7 +1824,8 @@
             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) {
@@ -2114,7 +2087,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 +2095,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 +2243,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 +2284,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 +2313,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 +2527,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 +2552,25 @@
         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) {
+        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, sim, 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;
@@ -2657,6 +2637,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 +2649,7 @@
                         cf.right = mContentRight;
                         cf.bottom = mContentBottom;
                     }
+
                     applyStableConstraints(sysUiFl, fl, cf);
                     if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
                         vf.left = mCurLeft;
@@ -2720,7 +2702,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 +2733,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 +2792,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,9 +2804,9 @@
                 + 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()) {
@@ -2853,7 +2838,7 @@
     }
 
     /** {@inheritDoc} */
-    public void beginAnimationLw(int displayWidth, int displayHeight) {
+    public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
         mTopFullscreenOpaqueWindowState = null;
         mForceStatusBar = false;
         
@@ -2863,7 +2848,7 @@
     }
 
     /** {@inheritDoc} */
-    public void animatingWindowLw(WindowState win,
+    public void applyPostLayoutPolicyLw(WindowState win,
                                 WindowManager.LayoutParams attrs) {
         if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
                 + win.isVisibleOrBehindKeyguardLw());
@@ -2872,8 +2857,8 @@
             if ((attrs.flags & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
                 mForceStatusBar = true;
             }
-            if (attrs.type >= FIRST_APPLICATION_WINDOW
-                    && attrs.type <= LAST_APPLICATION_WINDOW
+            if (((attrs.type >= FIRST_APPLICATION_WINDOW && attrs.type <= LAST_APPLICATION_WINDOW)
+                        || attrs.type == TYPE_DREAM)
                     && attrs.x == 0 && attrs.y == 0
                     && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
                     && attrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
@@ -2895,7 +2880,7 @@
     }
 
     /** {@inheritDoc} */
-    public int finishAnimationLw() {
+    public int finishPostLayoutPolicyLw() {
         int changes = 0;
         boolean topIsFullscreen = false;
 
@@ -2950,10 +2935,11 @@
 
         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 (localLOGV) Log.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard="
+                    + mHideLockScreen);
             if (mDismissKeyguard && !mKeyguardMediator.isSecure()) {
                 if (mKeyguard.hideLw(true)) {
                     changes |= FINISH_LAYOUT_REDO_LAYOUT
@@ -3034,27 +3020,21 @@
                 mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(
                         KeyEvent.KEYCODE_POWER, mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED);
             } 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 +3172,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 +3183,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 +3203,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 +3221,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
@@ -3261,7 +3244,7 @@
                             mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED);
                 } else {
                     // Otherwise, wake the device ourselves.
-                    result |= ACTION_POKE_USER_ACTIVITY;
+                    result |= ACTION_WAKE_UP;
                 }
             }
         }
@@ -3366,7 +3349,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 +3391,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;
                 }
@@ -3493,7 +3476,7 @@
                 mKeyguardMediator.onWakeMotionWhenKeyguardShowingTq();
             } else {
                 // Otherwise, wake the device ourselves.
-                result |= ACTION_POKE_USER_ACTIVITY;
+                result |= ACTION_WAKE_UP;
             }
         }
         return result;
@@ -3573,15 +3556,6 @@
         }
     };
 
-    BroadcastReceiver mPowerReceiver = new BroadcastReceiver() {
-        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);
-            }
-        }
-    };
-
     /** {@inheritDoc} */
     public void screenTurnedOff(int why) {
         EventLog.writeEvent(70000, 0);
@@ -3744,7 +3718,16 @@
         synchronized (mLock) {
             int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
             if (sensorRotation < 0) {
-                sensorRotation = lastRotation;
+                // Sensor is disabled, device probably just turned off.
+                if (mLastSensorRotation >= 0) {
+                    sensorRotation = mLastSensorRotation;
+                } else {
+                    // Sensor has never been enabled. Last resort is to use lastRotation.
+                    sensorRotation = lastRotation;
+                }
+            } else {
+                // Valid sensor data, save it away.
+                mLastSensorRotation = sensorRotation;
             }
 
             final int preferredRotation;
@@ -4046,60 +4029,6 @@
         }
     }
 
-    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;
-    }
-
-    @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() {
         public void run() {
             synchronized (this) {
@@ -4143,8 +4072,6 @@
     }
 
     private void applyLidSwitchState() {
-        mPowerManager.setKeyboardVisibility(isBuiltInKeyboardVisible());
-
         if (mLidState == LID_CLOSED && mLidControlsSleep) {
             mPowerManager.goToSleep(SystemClock.uptimeMillis());
         }
@@ -4225,7 +4152,7 @@
             } catch (ActivityNotFoundException e) {
             }
         }
-        mContext.startActivity(mHomeIntent);
+        mContext.startActivityAsUser(mHomeIntent, UserHandle.CURRENT);
     }
     
     /**
@@ -4254,22 +4181,22 @@
                     Intent dock = createHomeDockIntent();
                     if (dock != null) {
                         int result = ActivityManagerNative.getDefault()
-                                .startActivity(null, dock,
+                                .startActivityAsUser(null, dock,
                                         dock.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;
                         }
                     }
                 }
                 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;
                 }
@@ -4326,24 +4253,13 @@
     }
     
     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;
-        }
     }
 
     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;
+                mPowerManager.userActivity(curTime, false);
             }
         }
     }
@@ -4400,6 +4316,18 @@
         mLastInputMethodTargetWindow = target;
     }
 
+    public boolean canMagnifyWindow(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;
+    }
+
     public void dump(String prefix, PrintWriter pw, String[] args) {
         pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
                 pw.print(" mSystemReady="); pw.print(mSystemReady);
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..39afaa2
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/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;
+
+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/FaceUnlock.java b/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java
new file mode 100644
index 0000000..a4159d0
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java
@@ -0,0 +1,521 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.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_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;
+
+    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;
+    }
+
+    /**
+     * 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 (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 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 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.
+     */
+    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()");
+        // Not required
+    }
+
+    /**
+     * Hide face unlock and show backup
+     */
+    void handleHideFaceUnlockView() {
+        if (DEBUG) Log.d(TAG, "handleHideFaceUnlockView()");
+        mKeyguardScreenCallback.showBackupSecurity();
+    }
+
+    /**
+     * 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.  Shows the
+     * Face Unlock view to keep the backup lock covered while the device unlocks.
+     */
+    void handleUnlock() {
+        if (DEBUG) Log.d(TAG, "handleUnlock()");
+        removeDisplayMessages();
+        stop();
+        mKeyguardScreenCallback.reportSuccessfulUnlockAttempt();
+        mKeyguardScreenCallback.dismiss(true);
+    }
+
+    /**
+     * Stops the Face Unlock service and exposes the backup lock.
+     */
+    void handleCancel() {
+        if (DEBUG) Log.d(TAG, "handleCancel()");
+        mKeyguardScreenCallback.dismiss(false);
+        stop();
+        mKeyguardScreenCallback.userActivity(BACKUP_LOCK_TIMEOUT);
+    }
+
+    /**
+     * Increments the number of failed Face Unlock attempts.
+     */
+    void handleReportFailedAttempt() {
+        if (DEBUG) Log.d(TAG, "handleReportFailedAttempt()");
+        mKeyguardScreenCallback.reportFailedUnlockAttempt();
+    }
+
+    /**
+     * 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()");
+        // No longer required because face unlock doesn't cover backup unlock.
+    }
+
+    /**
+     * Pokes the wakelock to keep the screen alive and active for a specific amount of time.
+     */
+    void handlePokeWakelock(int millis) {
+        mKeyguardScreenCallback.userActivity(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().
+         */
+        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 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.
+         **/
+        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/KeyguardAccountView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java
new file mode 100644
index 0000000..1e73c5b
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.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 KeyguardNavigationManager mNavigationManager;
+
+    /**
+     * 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();
+        mNavigationManager = new KeyguardNavigationManager(this);
+
+        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);
+        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();
+        mNavigationManager.setMessage(mLockPatternUtils.isPermanentlyLocked() ?
+                R.string.kg_login_too_many_attempts : R.string.kg_login_instructions);
+    }
+
+    /** {@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.startActivity(intent);
+                    mCallback.reportSuccessfulUnlockAttempt();
+
+                    // dismiss keyguard
+                    mCallback.dismiss(true);
+                } else {
+                    mNavigationManager.setMessage(R.string.kg_login_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.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).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.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).confirmCredentials(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 */);
+    }
+
+    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() {
+        reset();
+    }
+
+}
+
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..7dffca8
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.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 com.android.internal.policy.impl.keyguard;
+
+import android.content.Context;
+import android.telephony.TelephonyManager;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import com.android.internal.R;
+import com.android.internal.policy.impl.keyguard.BiometricSensorUnlock;
+import com.android.internal.policy.impl.keyguard.FaceUnlock;
+import com.android.internal.widget.LockPatternUtils;
+
+public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecurityView {
+
+    private static final String TAG = "KeyguardFaceUnlockView";
+    private KeyguardSecurityCallback mKeyguardSecurityCallback;
+    private LockPatternUtils mLockPatternUtils;
+    private BiometricSensorUnlock mBiometricUnlock;
+    private KeyguardNavigationManager mNavigationManager;
+    private View mFaceUnlockAreaView;
+
+    public KeyguardFaceUnlockView(Context context) {
+        this(context, null);
+    }
+
+    public KeyguardFaceUnlockView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mNavigationManager = new KeyguardNavigationManager(this);
+
+        initializeBiometricUnlockView();
+    }
+
+    @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 onPause() {
+        if (mBiometricUnlock != null) {
+            mBiometricUnlock.hide();
+            mBiometricUnlock.stop();
+        }
+        KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateCallback);
+    }
+
+    @Override
+    public void onResume() {
+        maybeStartBiometricUnlock();
+        mBiometricUnlock.show(0);
+        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() {
+        mFaceUnlockAreaView = findViewById(R.id.face_unlock_area_view);
+        if (mFaceUnlockAreaView != null) {
+            mBiometricUnlock = new FaceUnlock(mContext);
+        } 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 including
+     * the mSuppressBiometricUnlock flag.  If it should not be started, it hides the biometric
+     * unlock area.
+     */
+    private void maybeStartBiometricUnlock() {
+        if (mBiometricUnlock != null) {
+            KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
+            final boolean backupIsTimedOut = (
+                    monitor.getFailedUnlockAttempts() >=
+                    LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT);
+            if (monitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE
+                    && !monitor.getMaxBiometricUnlockAttemptsReached()
+                    && !backupIsTimedOut) {
+                mBiometricUnlock.start();
+            } else {
+                mBiometricUnlock.hide();
+            }
+        }
+    }
+
+    KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
+        // We need to stop the biometric unlock when a phone call comes in
+        @Override
+        public void onPhoneStateChanged(int phoneState) {
+            if (phoneState == TelephonyManager.CALL_STATE_RINGING) {
+                mBiometricUnlock.stop();
+                mBiometricUnlock.hide();
+            }
+        }
+
+        @Override
+        public void onUserSwitched(int userId) {
+            if (mBiometricUnlock != null) {
+                mBiometricUnlock.stop();
+            }
+            mLockPatternUtils.setCurrentUser(userId);
+        }
+    };
+
+}
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..47ec243
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
@@ -0,0 +1,759 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.admin.DevicePolicyManager;
+import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetHostView;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
+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.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 android.widget.ViewFlipper;
+
+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 = "KeyguardViewHost";
+
+    // Use this to debug all of keyguard
+    public static boolean DEBUG;
+
+    // also referenced in SecuritySettings.java
+    static final int APPWIDGET_HOST_ID = 0x4B455947;
+    private static final String KEYGUARD_WIDGET_PREFS = "keyguard_widget_prefs";
+
+    private AppWidgetHost mAppWidgetHost;
+    private KeyguardWidgetPager mAppWidgetContainer;
+    private ViewFlipper mSecurityViewContainer;
+    private boolean mEnableMenuKey;
+    private boolean mIsVerifyUnlockOnly;
+    private boolean mEnableFallback; // TODO: This should get the value from KeyguardPatternView
+    private SecurityMode mCurrentSecuritySelection = SecurityMode.None;
+
+    protected Runnable mLaunchRunnable;
+
+    protected int mFailedAttempts;
+    private LockPatternUtils mLockPatternUtils;
+
+    private KeyguardSecurityModel mSecurityModel;
+
+    private Rect mTempRect = new Rect();
+    private KeyguardTransportControlView mTransportControl;
+
+    /*package*/ interface TransportCallback {
+        void hide();
+        void show();
+    }
+
+    /*package*/ interface UserSwitcherCallback {
+        void hideSecurityView(int duration);
+        void showSecurityView();
+    }
+
+    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());
+        mSecurityModel = new KeyguardSecurityModel(context);
+
+        // The following enables the MENU key to work for testing automation
+        mEnableMenuKey = shouldEnableMenuKey();
+        setFocusable(true);
+        setFocusableInTouchMode(true);
+    }
+
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent ev) {
+        boolean result = super.dispatchTouchEvent(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);
+        mViewMediatorCallback.keyguardDoneDrawing();
+    }
+
+    private int getWidgetPosition(int id) {
+        final int children = mAppWidgetContainer.getChildCount();
+        for (int i = 0; i < children; i++) {
+            if (mAppWidgetContainer.getChildAt(i).getId() == id) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        mAppWidgetContainer = (KeyguardWidgetPager) findViewById(R.id.app_widget_container);
+        mAppWidgetContainer.setVisibility(VISIBLE);
+        mSecurityViewContainer = (ViewFlipper) findViewById(R.id.view_flipper);
+
+        // 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.
+        mTransportControl =
+                (KeyguardTransportControlView) findViewById(R.id.keyguard_transport_control);
+        if (mTransportControl != null) {
+            mTransportControl.setKeyguardCallback(new TransportCallback() {
+                boolean mSticky = false;
+                @Override
+                public void hide() {
+                    int page = getWidgetPosition(R.id.keyguard_transport_control);
+                    if (page != -1 && !mSticky) {
+                        if (page == mAppWidgetContainer.getCurrentPage()) {
+                            // Switch back to clock view if music was showing.
+                            mAppWidgetContainer
+                                .setCurrentPage(getWidgetPosition(R.id.keyguard_status_view));
+                        }
+                        mAppWidgetContainer.removeView(mTransportControl);
+                        // XXX keep view attached to hierarchy so we still get show/hide events
+                        // from AudioManager
+                        KeyguardHostView.this.addView(mTransportControl);
+                        mTransportControl.setVisibility(View.GONE);
+                    }
+                }
+
+                @Override
+                public void show() {
+                    if (getWidgetPosition(R.id.keyguard_transport_control) == -1) {
+                        KeyguardHostView.this.removeView(mTransportControl);
+                        mAppWidgetContainer.addView(mTransportControl,
+                                getWidgetPosition(R.id.keyguard_status_view) + 1);
+                        mTransportControl.setVisibility(View.VISIBLE);
+                        // Once shown, leave it showing
+                        mSticky = true;
+                    }
+                }
+            });
+        }
+        updateSecurityViews();
+    }
+
+    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);
+        } 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();
+        maybePopulateWidgets();
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        mAppWidgetHost.stopListening();
+    }
+
+    private AppWidgetHost getAppWidgetHost() {
+        return mAppWidgetHost;
+    }
+
+    void addWidget(AppWidgetHostView view) {
+        mAppWidgetContainer.addWidget(view);
+    }
+
+    private KeyguardSecurityCallback mCallback = new KeyguardSecurityCallback() {
+
+        public void userActivity(long timeout) {
+            mViewMediatorCallback.pokeWakelock(timeout);
+        }
+
+        public void dismiss(boolean authenticated) {
+            showNextSecurityScreenOrFinish(authenticated);
+        }
+
+        public boolean isVerifyUnlockOnly() {
+            return mIsVerifyUnlockOnly;
+        }
+
+        public void reportSuccessfulUnlockAttempt() {
+            KeyguardUpdateMonitor.getInstance(mContext).clearFailedUnlockAttempts();
+        }
+
+        public void reportFailedUnlockAttempt() {
+            // TODO: handle biometric attempt differently.
+            KeyguardHostView.this.reportFailedUnlockAttempt();
+        }
+
+        public int getFailedAttempts() {
+            return KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts();
+        }
+
+        @Override
+        public void showBackupSecurity() {
+            KeyguardHostView.this.showBackupSecurity();
+        }
+
+        @Override
+        public void setOnDismissRunnable(Runnable runnable) {
+            KeyguardHostView.this.setOnDismissRunnable(runnable);
+        }
+
+    };
+
+    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();
+    }
+
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        if (event.getAction() == KeyEvent.ACTION_UP
+                && event.getKeyCode() == KeyEvent.KEYCODE_BACK
+                && mCurrentSecuritySelection != SecurityMode.None) {
+            mCallback.dismiss(false);
+            return true;
+        }
+        return super.dispatchKeyEvent(event);
+    }
+
+    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 Password: {
+                    final boolean isPin = mLockPatternUtils.getKeyguardStoredPasswordQuality() ==
+                        DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
+                    messageId = isPin ? R.string.kg_too_many_failed_pin_attempts_dialog_message
+                            : 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);
+
+        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 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 showBackupSecurity() {
+        SecurityMode currentMode = mSecurityModel.getAlternateFor(mSecurityModel.getSecurityMode());
+        showSecurityScreen(mSecurityModel.getBackupFor(currentMode));
+    }
+
+    private void showNextSecurityScreenOrFinish(boolean 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 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:
+                    showSecurityScreen(SecurityMode.None);
+                    break;
+            }
+        } else {
+            // Not authenticated but we were asked to dismiss so go back to selector screen.
+            showSecurityScreen(SecurityMode.None);
+        }
+        if (finish) {
+            // If there's a pending runnable because the user interacted with a widget
+            // and we're leaving keyguard, then run it.
+            if (mLaunchRunnable != null) {
+                mLaunchRunnable.run();
+                mLaunchRunnable = null;
+            }
+            mViewMediatorCallback.keyguardDone(true);
+        }
+    }
+
+    private OnClickHandler mOnClickHandler = new OnClickHandler() {
+        @Override
+        public boolean onClickHandler(final View view,
+                final android.app.PendingIntent pendingIntent,
+                final Intent fillInIntent) {
+            if (pendingIntent.isActivity()) {
+                setOnDismissRunnable(new Runnable() {
+                    public void run() {
+                        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);
+                          }
+                    }
+                });
+
+                mCallback.dismiss(false);
+                return true;
+            } else {
+                return super.onClickHandler(view, pendingIntent, fillInIntent);
+            }
+        };
+    };
+
+    @Override
+    public void reset() {
+        mIsVerifyUnlockOnly = false;
+        mAppWidgetContainer.setCurrentPage(getWidgetPosition(R.id.keyguard_status_view));
+        requestFocus();
+    }
+
+    /**
+     *  Sets a runnable to run when keyguard is dismissed
+     * @param runnable
+     */
+    protected void setOnDismissRunnable(Runnable runnable) {
+        mLaunchRunnable = runnable;
+    }
+
+    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;
+            }
+        }
+        if (view == null) {
+            final LayoutInflater inflater = LayoutInflater.from(mContext);
+            View v = inflater.inflate(getLayoutIdFor(securityMode), this, false);
+            mSecurityViewContainer.addView(v);
+            updateSecurityView(v);
+            view = (KeyguardSecurityView) v;
+        }
+        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 (securityMode == mCurrentSecuritySelection) return;
+
+        KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);
+        KeyguardSecurityView newView = getSecurityView(securityMode);
+
+        // Emulate Activity life cycle
+        oldView.onPause();
+        newView.onResume();
+
+        mViewMediatorCallback.setNeedsInput(newView.needsInput());
+
+        // Find and show this child.
+        final int childCount = mSecurityViewContainer.getChildCount();
+
+        // If we're go to/from the selector view, do flip animation, otherwise use fade animation.
+        final boolean doFlip = mCurrentSecuritySelection == SecurityMode.None
+                || securityMode == SecurityMode.None;
+        final int inAnimation = doFlip ? R.anim.keyguard_security_animate_in
+                : R.anim.keyguard_security_fade_in;
+        final int outAnimation = doFlip ? R.anim.keyguard_security_animate_out
+                : R.anim.keyguard_security_fade_out;
+
+        mSecurityViewContainer.setInAnimation(AnimationUtils.loadAnimation(mContext, inAnimation));
+        mSecurityViewContainer.setOutAnimation(AnimationUtils.loadAnimation(mContext, outAnimation));
+        final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
+        for (int i = 0; i < childCount; i++) {
+            if (mSecurityViewContainer.getChildAt(i).getId() == securityViewIdForMode) {
+                mSecurityViewContainer.setDisplayedChild(i);
+                break;
+            }
+        }
+
+        // Discard current runnable if we're switching back to the selector view
+        if (securityMode == SecurityMode.None) {
+            setOnDismissRunnable(null);
+        }
+
+        mCurrentSecuritySelection = securityMode;
+    }
+
+    @Override
+    public void onScreenTurnedOn() {
+        if (DEBUG) Log.d(TAG, "screen on");
+        showSecurityScreen(mCurrentSecuritySelection);
+        getSecurityView(mCurrentSecuritySelection).onResume();
+
+        // 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();
+    }
+
+    @Override
+    public void onScreenTurnedOff() {
+        if (DEBUG) Log.d(TAG, "screen off");
+        showSecurityScreen(SecurityMode.None);
+        getSecurityView(mCurrentSecuritySelection).onPause();
+    }
+
+    @Override
+    public void show() {
+        onScreenTurnedOn();
+    }
+
+    private boolean isSecure() {
+        SecurityMode mode = mSecurityModel.getSecurityMode();
+        switch (mode) {
+            case Pattern:
+                return mLockPatternUtils.isLockPatternEnabled();
+            case Password:
+                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);
+            mViewMediatorCallback.pokeWakelock();
+        } else {
+            if (DEBUG) Log.d(TAG, "poking wake lock immediately");
+            mViewMediatorCallback.pokeWakelock();
+        }
+    }
+
+    @Override
+    public void verifyUnlock() {
+        SecurityMode securityMode = mSecurityModel.getSecurityMode();
+        if (securityMode == KeyguardSecurityModel.SecurityMode.None) {
+            mViewMediatorCallback.keyguardDone(true);
+        } else if (securityMode != KeyguardSecurityModel.SecurityMode.Pattern
+                && securityMode != KeyguardSecurityModel.SecurityMode.Password) {
+            // can only verify unlock when in pattern/password mode
+            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 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 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:
+                throw new RuntimeException("No layout for securityMode " + securityMode);
+        }
+    }
+
+    private void addWidget(int appId) {
+        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
+        AppWidgetProviderInfo appWidgetInfo = appWidgetManager.getAppWidgetInfo(appId);
+        if (appWidgetInfo != null) {
+            AppWidgetHostView view = getAppWidgetHost().createView(mContext, appId, appWidgetInfo);
+            addWidget(view);
+        } else {
+            Log.w(TAG, "AppWidgetInfo was null; not adding widget id " + appId);
+        }
+    }
+
+    private void maybePopulateWidgets() {
+        DevicePolicyManager dpm =
+                (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+        if (dpm != null && dpm.getKeyguardWidgetsDisabled(null)
+                != DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_NONE) {
+            Log.v(TAG, "Keyguard widgets disabled because of device policy admin");
+            return;
+        }
+        inflateAndAddUserSelectorWidgetIfNecessary();
+
+        final int[] widgets = mLockPatternUtils.getUserDefinedWidgets();
+        for (int i = 0; i < widgets.length; i++) {
+            if (widgets[i] != -1) {
+                addWidget(widgets[i]);
+            }
+        }
+    }
+
+    private void inflateAndAddUserSelectorWidgetIfNecessary() {
+        // if there are multiple users, we need to add the multi-user switcher widget to the
+        // keyguard.
+        UserManager mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        List<UserInfo> users = mUm.getUsers();
+
+        if (users.size() > 1) {
+            KeyguardWidgetFrame userSwitcher = (KeyguardWidgetFrame)
+                LayoutInflater.from(mContext).inflate(R.layout.keyguard_multi_user_selector_widget,
+                        mAppWidgetContainer, false);
+
+            // add the switcher in the first position
+            mAppWidgetContainer.addView(userSwitcher, getWidgetPosition(R.id.keyguard_status_view));
+            KeyguardMultiUserSelectorView multiUser = (KeyguardMultiUserSelectorView)
+                    userSwitcher.getChildAt(0);
+
+            UserSwitcherCallback callback = new UserSwitcherCallback() {
+                @Override
+                public void hideSecurityView(int duration) {
+                    mSecurityViewContainer.animate().alpha(0).setDuration(duration);
+                }
+
+                @Override
+                public void showSecurityView() {
+                    mSecurityViewContainer.setAlpha(1.0f);
+                }
+            };
+            multiUser.setCallback(callback);
+        }
+    }
+
+    @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;
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if (keyCode == KeyEvent.KEYCODE_MENU && mEnableMenuKey) {
+            showNextSecurityScreenOrFinish(false);
+            return true;
+        } else {
+            return super.onKeyDown(keyCode, event);
+        }
+    }
+
+}
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..759068d
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserAvatar.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 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.pm.UserInfo;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.internal.R;
+
+class KeyguardMultiUserAvatar extends FrameLayout {
+
+    private ImageView mUserImage;
+    private TextView mUserName;
+    private UserInfo mUserInfo;
+    private static final int INACTIVE_COLOR = 85;
+    private static final int INACTIVE_ALPHA = 195;
+    private static final float ACTIVE_SCALE = 1.1f;
+    private boolean mActive;
+    private boolean mInit = true;
+    private KeyguardMultiUserSelectorView mUserSelector;
+
+    public static KeyguardMultiUserAvatar fromXml(int resId, Context context,
+            KeyguardMultiUserSelectorView userSelector, UserInfo info) {
+        KeyguardMultiUserAvatar icon = (KeyguardMultiUserAvatar)
+                LayoutInflater.from(context).inflate(resId, userSelector, false);
+
+        icon.setup(info, userSelector);
+        return icon;
+    }
+
+    public KeyguardMultiUserAvatar(Context context) {
+        super(context, null, 0);
+    }
+
+    public KeyguardMultiUserAvatar(Context context, AttributeSet attrs) {
+        super(context, attrs, 0);
+    }
+
+    public KeyguardMultiUserAvatar(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    public void setup(UserInfo user, KeyguardMultiUserSelectorView userSelector) {
+        mUserInfo = user;
+        mUserSelector = userSelector;
+        init();
+    }
+
+    private void init() {
+        mUserImage = (ImageView) findViewById(R.id.keyguard_user_avatar);
+        mUserName = (TextView) findViewById(R.id.keyguard_user_name);
+
+        mUserImage.setImageDrawable(Drawable.createFromPath(mUserInfo.iconPath));
+        mUserName.setText(mUserInfo.name);
+        setOnClickListener(mUserSelector);
+        setActive(false, false, 0, null);
+        mInit = false;
+    }
+
+    public void setActive(boolean active, boolean animate, int duration, final Runnable onComplete) {
+        if (mActive != active || mInit) {
+            mActive = active;
+            final int finalFilterAlpha = mActive ? 0 : INACTIVE_ALPHA;
+            final int initFilterAlpha = mActive ? INACTIVE_ALPHA : 0;
+
+            final float finalScale = mActive ? ACTIVE_SCALE : 1.0f;
+            final float initScale = mActive ? 1.0f : ACTIVE_SCALE;
+
+            if (active) {
+                KeyguardSubdivisionLayout parent = (KeyguardSubdivisionLayout) getParent();
+                parent.setTopChild(parent.indexOfChild(this));
+            }
+
+            if (animate) {
+                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;
+                        int filterAlpha = (int) ((1 - r) * initFilterAlpha + r * finalFilterAlpha);
+                        setScaleX(scale);
+                        setScaleY(scale);
+                        mUserImage.setColorFilter(Color.argb(filterAlpha, INACTIVE_COLOR,
+                                INACTIVE_COLOR, INACTIVE_COLOR));
+                        mUserSelector.invalidate();
+
+                    }
+                });
+                va.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        if (onComplete != null) {
+                            onComplete.run();
+                        }
+                    }
+                });
+                va.setDuration(duration);
+                va.start();
+            } else {
+                setScaleX(finalScale);
+                setScaleY(finalScale);
+                mUserImage.setColorFilter(Color.argb(finalFilterAlpha, INACTIVE_COLOR,
+                        INACTIVE_COLOR, INACTIVE_COLOR));
+                if (onComplete != null) {
+                    post(onComplete);
+                }
+            }
+        }
+    }
+
+    boolean mLockDrawableState = false;
+
+    public void lockDrawableState() {
+        mLockDrawableState = true;
+    }
+
+    public void resetDrawableState() {
+        mLockDrawableState = false;
+        post(new Runnable() {
+            @Override
+            public void run() {
+                refreshDrawableState();
+            }
+        });
+    }
+
+    protected void drawableStateChanged() {
+        if (!mLockDrawableState) {
+            super.drawableStateChanged();
+        }
+    }
+
+    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..01d5d8c
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserSelectorView.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.internal.policy.impl.keyguard;
+
+import android.app.ActivityManagerNative;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.RemoteException;
+import android.os.UserManager;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.view.WindowManagerGlobal;
+import android.widget.FrameLayout;
+
+import com.android.internal.R;
+import com.android.internal.policy.impl.keyguard.KeyguardHostView.UserSwitcherCallback;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+public class KeyguardMultiUserSelectorView extends FrameLayout implements View.OnClickListener {
+    private static final String TAG = "KeyguardMultiUserSelectorView";
+
+    private KeyguardSubdivisionLayout mUsersGrid;
+    private KeyguardMultiUserAvatar mActiveUserAvatar;
+    private UserSwitcherCallback mCallback;
+    private static final int SWITCH_ANIMATION_DURATION = 150;
+    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 () {
+        init();
+    }
+
+    public void setCallback(UserSwitcherCallback callback) {
+        mCallback = callback;
+    }
+
+    public void init() {
+        mUsersGrid = (KeyguardSubdivisionLayout) findViewById(R.id.keyguard_users_grid);
+        mUsersGrid.removeAllViews();
+        setClipChildren(false);
+        setClipToPadding(false);
+
+        UserInfo activeUser;
+        try {
+            activeUser = ActivityManagerNative.getDefault().getCurrentUser();
+        } catch (RemoteException re) {
+            activeUser = null;
+        }
+
+        UserManager mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUm.getUsers());
+        Collections.sort(users, mOrderAddedComparator);
+
+        for (UserInfo user: users) {
+            KeyguardMultiUserAvatar uv = createAndAddUser(user);
+            if (user.id == activeUser.id) {
+                mActiveUserAvatar = uv;
+            }
+        }
+        mActiveUserAvatar.setActive(true, false, 0, 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 void onClick(View v) {
+        if (!(v instanceof KeyguardMultiUserAvatar)) return;
+        final KeyguardMultiUserAvatar avatar = (KeyguardMultiUserAvatar) v;
+        if (mActiveUserAvatar == avatar) {
+            // They clicked the active user, no need to do anything
+            return;
+        } else {
+            // Reset the previously active user to appear inactive
+            avatar.lockDrawableState();
+            mCallback.hideSecurityView(FADE_OUT_ANIMATION_DURATION);
+            mActiveUserAvatar.setActive(false, true,  SWITCH_ANIMATION_DURATION, new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        ActivityManagerNative.getDefault().switchUser(avatar.getUserInfo().id);
+                        WindowManagerGlobal.getWindowManagerService().lockNow();
+                        // Set the new active user, and make it appear active
+                        avatar.resetDrawableState();
+                        mCallback.showSecurityView();
+                        mActiveUserAvatar = avatar;
+                        mActiveUserAvatar.setActive(true, false, 0, null);
+                    } catch (RemoteException re) {
+                        Log.e(TAG, "Couldn't switch user " + re);
+                    }
+                }
+            });
+        }
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardNavigationManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardNavigationManager.java
new file mode 100644
index 0000000..4f29825
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardNavigationManager.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.internal.policy.impl.keyguard;
+
+import android.view.View;
+import android.widget.TextView;
+
+import com.android.internal.R;
+
+public class KeyguardNavigationManager {
+
+    private TextView mMessageArea;
+    private KeyguardSecurityView mKeyguardSecurityView;
+    private View mClickArea;
+
+    public KeyguardNavigationManager(KeyguardSecurityView view) {
+        mKeyguardSecurityView = view;
+        mMessageArea = (TextView) ((View) view).findViewById(R.id.keyguard_message_area);
+        mMessageArea.setSelected(true); // Make marquee work
+
+        mClickArea = ((View) view).findViewById(R.id.keyguard_click_area);
+        mClickArea.setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                mKeyguardSecurityView.getCallback().dismiss(false);
+            }
+        });
+    }
+
+    public void setMessage(CharSequence msg) {
+        mMessageArea.setText(msg);
+    }
+
+    public void setMessage(int resId) {
+        if (resId != 0) {
+            mMessageArea.setText(resId);
+        } else {
+            mMessageArea.setText("");
+        }
+    }
+
+    public void setMessage(int resId, Object... formatArgs) {
+        if (resId != 0) {
+            mMessageArea.setText(mMessageArea.getContext().getString(resId, formatArgs));
+        } else {
+            mMessageArea.setText("");
+        }
+    }
+}
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..01f7af3
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java
@@ -0,0 +1,349 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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 com.android.internal.R;
+import com.android.internal.widget.LockPatternUtils;
+import java.util.List;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+
+import com.android.internal.widget.PasswordEntryKeyboardView;
+
+import android.os.CountDownTimer;
+import android.os.SystemClock;
+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.KeyEvent;
+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.TextView;
+import android.widget.TextView.OnEditorActionListener;
+
+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 KeyguardPasswordView extends LinearLayout
+        implements KeyguardSecurityView, OnEditorActionListener {
+    private KeyguardSecurityCallback mCallback;
+    private EditText mPasswordEntry;
+    private LockPatternUtils mLockPatternUtils;
+    private PasswordEntryKeyboardView mKeyboardView;
+    private PasswordEntryKeyboardHelper mKeyboardHelper;
+    private boolean mIsAlpha;
+    private KeyguardNavigationManager mNavigationManager;
+
+    // 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;
+
+    // Enable this if we want to hide the on-screen PIN keyboard when a physical one is showing
+    private static final boolean ENABLE_HIDE_KEYBOARD = false;
+
+    public KeyguardPasswordView(Context context) {
+        super(context);
+    }
+
+    public KeyguardPasswordView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public void setKeyguardCallback(KeyguardSecurityCallback callback) {
+        mCallback = callback;
+    }
+
+    public void setLockPatternUtils(LockPatternUtils utils) {
+        mLockPatternUtils = utils;
+    }
+
+    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();
+        }
+    }
+
+    private void resetState() {
+        mNavigationManager.setMessage(
+                mIsAlpha ? R.string.kg_password_instructions : R.string.kg_pin_instructions);
+        mPasswordEntry.setEnabled(true);
+        mKeyboardView.setEnabled(true);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        mLockPatternUtils = new LockPatternUtils(mContext); // TODO: use common one
+
+        mNavigationManager = new KeyguardNavigationManager(this);
+
+        final int quality = mLockPatternUtils.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(mContext, 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 {
+            mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
+
+            // Use lockscreen's numeric keyboard if the physical keyboard isn't showing
+            boolean hardKeyboardVisible = getResources().getConfiguration().hardKeyboardHidden
+                    == Configuration.HARDKEYBOARDHIDDEN_NO;
+            mKeyboardView.setVisibility(
+                    (ENABLE_HIDE_KEYBOARD && hardKeyboardVisible) ? 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.delete_button);
+            if (pinDelete != null) {
+                pinDelete.setVisibility(View.VISIBLE);
+                imeOrDeleteButtonVisible = true;
+                pinDelete.setOnClickListener(new OnClickListener() {
+                    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);
+        } else {
+            mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance());
+            mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
+                    | InputType.TYPE_NUMBER_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) {
+                mCallback.userActivity(0);
+            }
+        });
+
+        // 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.userActivity(0); // 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);
+    }
+
+    private void verifyPasswordAndUnlock() {
+        String entry = mPasswordEntry.getText().toString();
+        if (mLockPatternUtils.checkPassword(entry)) {
+            mCallback.reportSuccessfulUnlockAttempt();
+            KeyStore.getInstance().password(entry);
+            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);
+            }
+            mNavigationManager.setMessage(
+                    mIsAlpha ? R.string.kg_wrong_password : R.string.kg_wrong_pin);
+        }
+        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);
+                mNavigationManager.setMessage(
+                        R.string.kg_too_many_failed_attempts_countdown, secondsRemaining);
+            }
+
+            @Override
+            public void onFinish() {
+                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 mIsAlpha;
+    }
+
+    @Override
+    public void onPause() {
+
+    }
+
+    @Override
+    public void onResume() {
+        reset();
+    }
+
+    @Override
+    public KeyguardSecurityCallback getCallback() {
+        return mCallback;
+    }
+
+}
+
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..6de40e4
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.os.Bundle;
+import android.os.CountDownTimer;
+import android.os.SystemClock;
+import android.security.KeyStore;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.Button;
+import android.widget.GridLayout;
+
+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 GridLayout 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;
+    private KeyguardNavigationManager mNavigationManager;
+
+    /**
+     * 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();
+
+    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();
+
+        mNavigationManager = new KeyguardNavigationManager(this);
+        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);
+        mForgotPatternButton.setText(R.string.kg_forgot_pattern_button_text);
+        mForgotPatternButton.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                mCallback.showBackupSecurity();
+            }
+        });
+
+        setFocusableInTouchMode(true);
+
+        maybeEnableFallback(mContext);
+    }
+
+    private void updateFooter(FooterMode mode) {
+        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 dispatchTouchEvent(MotionEvent ev) {
+        boolean result = super.dispatchTouchEvent(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 {
+            mNavigationManager.setMessage(R.string.kg_pattern_instructions);
+        }
+
+        // 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);
+        }
+
+    }
+
+    /** 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)) {
+                mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Correct);
+                mCallback.dismiss(true); // keyguardDone(true)
+                KeyStore.getInstance().password(LockPatternUtils.patternToString(pattern));
+                mTotalFailedPatternAttempts = 0;
+            } 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 {
+                    mNavigationManager.setMessage(R.string.kg_wrong_pattern);
+                    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.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 (mAccountIndex >= mAccounts.length) {
+                mEnableFallback = true;
+                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 handleAttemptLockout(long elapsedRealtimeDeadline) {
+        mLockPatternView.clearPattern();
+        mLockPatternView.setEnabled(false);
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
+        updateFooter(FooterMode.ForgotLockPattern);
+
+        mCountdownTimer = new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) {
+
+            @Override
+            public void onTick(long millisUntilFinished) {
+                final int secondsRemaining = (int) (millisUntilFinished / 1000);
+                mNavigationManager.setMessage(
+                        R.string.kg_too_many_failed_attempts_countdown, secondsRemaining);
+            }
+
+            @Override
+            public void onFinish() {
+                mLockPatternView.setEnabled(true);
+                mNavigationManager.setMessage(R.string.kg_pattern_instructions);
+                // 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() {
+        reset();
+    }
+
+    @Override
+    public KeyguardSecurityCallback getCallback() {
+        return mCallback;
+    }
+
+}
+
+
+
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..3b8df5d
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityCallback.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.internal.policy.impl.keyguard;
+
+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 a runnable to launch after the user successfully enters their credentials.
+     * @param runnable
+     */
+    void setOnDismissRunnable(Runnable runnable);
+
+}
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..75c4a7c
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityModel.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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 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 {
+        None, // No security enabled
+        Pattern, // Unlock by drawing a pattern.
+        Password, // Unlock by entering a password or PIN
+        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;
+    }
+
+    /**
+     * 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 isBiometricUnlockEnabled() {
+        KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
+        final boolean backupIsTimedOut =
+                monitor.getFailedUnlockAttempts() >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
+        return mLockPatternUtils.usingBiometricWeak()
+                && mLockPatternUtils.isBiometricWeakInstalled()
+                && !monitor.getMaxBiometricUnlockAttemptsReached()
+                && !backupIsTimedOut;
+    }
+
+    SecurityMode getSecurityMode() {
+        KeyguardUpdateMonitor mUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
+        final IccCardConstants.State simState = mUpdateMonitor.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:
+                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()
+                && (mode == SecurityMode.Password || 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.
+     *
+     * @param mode the mode we want the backup for
+     * @return backup method or given mode
+     */
+    SecurityMode getBackupFor(SecurityMode mode) {
+        switch(mode) {
+            case Biometric:
+                return getSecurityMode();
+            case Pattern:
+                return SecurityMode.Account;
+        }
+        return mode; // no backup, return what was given
+    }
+}
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..d80c1db
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityView.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.internal.policy.impl.keyguard;
+
+import com.android.internal.widget.LockPatternUtils;
+
+public interface KeyguardSecurityView {
+    /**
+     * 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.
+     */
+    void onResume();
+
+    /**
+     * 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();
+
+}
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..911cfe0
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewFlipper.java
@@ -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.
+ */
+
+package com.android.internal.policy.impl.keyguard;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+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 {
+    private Rect mTempRect = new Rect();
+
+    public KeyguardSecurityViewFlipper(Context context) {
+        this(context, null);
+    }
+
+    public KeyguardSecurityViewFlipper(Context context, AttributeSet attr) {
+        super(context, attr);
+    }
+
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent ev) {
+        boolean result = super.dispatchTouchEvent(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;
+    }
+
+}
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..7554236
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.ActivityManagerNative;
+import android.app.SearchManager;
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.provider.MediaStore;
+import android.telephony.TelephonyManager;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Slog;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+import com.android.internal.telephony.IccCardConstants;
+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 static final int EMERGENCY_CALL_TIMEOUT = 10000; // screen timeout after starting e.d.
+    static final String ACTION_EMERGENCY_DIAL = "com.android.phone.EmergencyDialer.DIAL";
+
+    private KeyguardSecurityCallback mCallback;
+    private GlowPadView mGlowPadView;
+    private Button mEmergencyCallButton;
+    private ObjectAnimator mAnim;
+    private boolean mCameraDisabled;
+    private boolean mSearchDisabled;
+    private LockPatternUtils mLockPatternUtils;
+
+    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) {
+                        launchActivity(assistIntent, false);
+                    } else {
+                        Log.w(TAG, "Failed to get intent for assist activity");
+                    }
+                    mCallback.userActivity(0);
+                    break;
+
+                case com.android.internal.R.drawable.ic_lockscreen_camera:
+                    launchCamera();
+                    mCallback.userActivity(0);
+                    break;
+
+                case com.android.internal.R.drawable.ic_lockscreen_unlock_phantom:
+                case com.android.internal.R.drawable.ic_lockscreen_unlock:
+                    mCallback.dismiss(false);
+                break;
+            }
+        }
+
+        public void onReleased(View v, int handle) {
+            doTransition(mEmergencyCallButton, 1.0f);
+        }
+
+        public void onGrabbed(View v, int handle) {
+            doTransition(mEmergencyCallButton, 0.0f);
+        }
+
+        public void onGrabbedStateChange(View v, int handle) {
+
+        }
+
+        public void onFinishFinalAnimation() {
+
+        }
+
+    };
+
+    private void updateEmergencyCallButton(State simState, int phoneState) {
+        if (mEmergencyCallButton != null) {
+            boolean en = mLockPatternUtils.isEmergencyCallCapable()
+                || (phoneState == TelephonyManager.CALL_STATE_OFFHOOK); // voice call in progress
+            if (en && KeyguardUpdateMonitor.isSimLocked(simState)) {
+                // Some countries can't handle emergency calls while SIM is locked.
+                en = mLockPatternUtils.isEmergencyCallEnabledWhileSimLocked();
+            }
+            mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton, phoneState, en);
+        }
+    }
+
+    KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
+
+        @Override
+        public void onDevicePolicyManagerStateChanged() {
+            updateTargets();
+        }
+
+        @Override
+        public void onSimStateChanged(State simState) {
+            int phoneState = KeyguardUpdateMonitor.getInstance(mContext).getPhoneState();
+            updateEmergencyCallButton(simState, phoneState);
+            updateTargets();
+        }
+
+        void onPhoneStateChanged(int phoneState) {
+            State simState = KeyguardUpdateMonitor.getInstance(mContext).getSimState();
+            updateEmergencyCallButton(simState, phoneState);
+        };
+    };
+
+    public KeyguardSelectorView(Context context) {
+        this(context, null);
+    }
+
+    protected void launchCamera() {
+        if (mLockPatternUtils.isSecure()) {
+            // Launch the secure version of the camera
+            Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
+            intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+            launchActivity(intent, true);
+        } else {
+            // Launch the normal camera
+            launchActivity(new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA), false);
+        }
+    }
+
+    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);
+        mEmergencyCallButton = (Button) findViewById(R.id.emergency_call_button);
+        mEmergencyCallButton.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                takeEmergencyCallAction();
+            }
+        });
+        updateTargets();
+    }
+
+    /**
+     * Shows the emergency dialer or returns the user to the existing call.
+     */
+    public void takeEmergencyCallAction() {
+        mCallback.userActivity(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 boolean isTargetPresent(int resId) {
+        return mGlowPadView.getTargetPosition(resId) != -1;
+    }
+
+    private void updateTargets() {
+        boolean disabledByAdmin = mLockPatternUtils.getDevicePolicyManager()
+                .getCameraDisabled(null);
+        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 (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;
+        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(Object v, float to) {
+        if (mAnim != null) {
+            mAnim.cancel();
+        }
+        mAnim = ObjectAnimator.ofFloat(mEmergencyCallButton, "alpha", to);
+        mAnim.start();
+    }
+
+    public void setKeyguardCallback(KeyguardSecurityCallback callback) {
+        mCallback = callback;
+    }
+
+    public void setLockPatternUtils(LockPatternUtils utils) {
+        mLockPatternUtils = utils;
+    }
+
+    /**
+     * 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}
+     */
+    private void launchActivity(final Intent intent, boolean showsWhileLocked) {
+        intent.addFlags(
+                Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_SINGLE_TOP
+                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        boolean isSecure = mLockPatternUtils.isSecure();
+        if (!isSecure || showsWhileLocked) {
+            if (!isSecure) 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());
+            }
+        } else {
+            // Create a runnable to start the activity and ask the user to enter their
+            // credentials.
+            mCallback.setOnDismissRunnable(new Runnable() {
+                @Override
+                public void run() {
+                    mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+                }
+            });
+            mCallback.dismiss(false);
+        }
+    }
+
+    @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() {
+        KeyguardUpdateMonitor.getInstance(getContext()).registerCallback(mInfoCallback);
+    }
+
+    @Override
+    public KeyguardSecurityCallback getCallback() {
+        return mCallback;
+    }
+
+}
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..bc55008
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPinView.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.internal.policy.impl.keyguard;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.graphics.Rect;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import com.android.internal.telephony.ITelephony;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.PasswordEntryKeyboardHelper;
+import com.android.internal.widget.PasswordEntryKeyboardView;
+import com.android.internal.R;
+
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.inputmethod.EditorInfo;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
+
+/**
+ * Displays a dialer like interface to unlock the SIM PIN.
+ */
+public class KeyguardSimPinView extends LinearLayout
+        implements KeyguardSecurityView, OnEditorActionListener {
+
+    private static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
+
+    private EditText mPinEntry;
+    private ProgressDialog mSimUnlockProgressDialog = null;
+    private KeyguardSecurityCallback mCallback;
+    private PasswordEntryKeyboardView mKeyboardView;
+    private PasswordEntryKeyboardHelper mKeyboardHelper;
+    private LockPatternUtils mLockPatternUtils;
+    private KeyguardNavigationManager mNavigationManager;
+
+    private volatile boolean mSimCheckInProgress;
+
+    public KeyguardSimPinView(Context context) {
+        this(context, null);
+    }
+
+    public KeyguardSimPinView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mLockPatternUtils = new LockPatternUtils(getContext());
+    }
+
+    public void setKeyguardCallback(KeyguardSecurityCallback callback) {
+        mCallback = callback;
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        mNavigationManager = new KeyguardNavigationManager(this);
+
+        mPinEntry = (EditText) findViewById(R.id.sim_pin_entry);
+        mPinEntry.setOnEditorActionListener(this);
+
+        mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
+        mKeyboardHelper = new PasswordEntryKeyboardHelper(mContext, mKeyboardView, this, false);
+        mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
+        mKeyboardHelper.setEnableHaptics(mLockPatternUtils.isTactileFeedbackEnabled());
+
+        final View deleteButton = findViewById(R.id.delete_button);
+        if (deleteButton != null) {
+            deleteButton.setOnClickListener(new OnClickListener() {
+                public void onClick(View v) {
+                    mKeyboardHelper.handleBackspace();
+                }
+            });
+        }
+        reset();
+    }
+
+    @Override
+    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
+        return mPinEntry.requestFocus(direction, previouslyFocusedRect);
+    }
+
+    public void reset() {
+        // start fresh
+        mNavigationManager.setMessage(R.string.kg_sim_pin_instructions);
+
+        // make sure that the number of entered digits is consistent when we
+        // erase the SIM unlock code, including orientation changes.
+        mPinEntry.setText("");
+        mPinEntry.requestFocus();
+    }
+
+    /** {@inheritDoc} */
+    public void cleanUp() {
+        // 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);
+                    }
+                });
+            }
+        }
+    }
+
+    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+        // Check if this was the result of hitting the enter key
+        mCallback.userActivity(DIGIT_PRESS_WAKE_MILLIS);
+        if (event.getAction() == MotionEvent.ACTION_DOWN && (
+                actionId == EditorInfo.IME_NULL
+                || actionId == EditorInfo.IME_ACTION_DONE
+                || actionId == EditorInfo.IME_ACTION_NEXT)) {
+            checkPin();
+            return true;
+        }
+        return 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 void checkPin() {
+        if (mPinEntry.getText().length() < 4) {
+            // otherwise, display a message to the user, and don't submit.
+            mNavigationManager.setMessage(R.string.kg_invalid_sim_pin_hint);
+            mPinEntry.setText("");
+            mCallback.userActivity(0);
+            return;
+        }
+
+        getSimUnlockProgressDialog().show();
+
+        if (!mSimCheckInProgress) {
+            mSimCheckInProgress = true; // there should be only one
+            new CheckSimPin(mPinEntry.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 {
+                                mNavigationManager.setMessage(R.string.kg_password_wrong_pin_code);
+                                mPinEntry.setText("");
+                            }
+                            mCallback.userActivity(0);
+                            mSimCheckInProgress = false;
+                        }
+                    });
+                }
+            }.start();
+        }
+    }
+
+    public void setLockPatternUtils(LockPatternUtils utils) {
+        mLockPatternUtils = utils;
+    }
+
+    public boolean needsInput() {
+        return false; // This view provides its own keypad
+    }
+
+    public void onPause() {
+
+    }
+
+    public void onResume() {
+        reset();
+    }
+
+    public KeyguardSecurityCallback getCallback() {
+        return mCallback;
+    }
+
+}
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..e04bff9
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPukView.java
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.text.Editable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.inputmethod.EditorInfo;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
+
+import com.android.internal.telephony.ITelephony;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.PasswordEntryKeyboardHelper;
+import com.android.internal.widget.PasswordEntryKeyboardView;
+import com.android.internal.R;
+
+public class KeyguardSimPukView extends LinearLayout implements View.OnClickListener,
+    View.OnFocusChangeListener, KeyguardSecurityView, OnEditorActionListener {
+
+    private static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
+
+    private TextView mPukText;
+    private TextView mPinText;
+    private TextView mFocusedEntry;
+
+    private View mDelPukButton;
+    private View mDelPinButton;
+
+    private ProgressDialog mSimUnlockProgressDialog = null;
+    private KeyguardSecurityCallback mCallback;
+
+    private KeyguardNavigationManager mNavigationManager;
+
+    private PasswordEntryKeyboardView mKeyboardView;
+
+    private PasswordEntryKeyboardHelper mKeyboardHelper;
+
+    private LockPatternUtils mLockPatternUtils;
+
+    private volatile boolean mCheckInProgress;
+
+    public KeyguardSimPukView(Context context) {
+        this(context, null);
+    }
+
+    public KeyguardSimPukView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mLockPatternUtils = new LockPatternUtils(getContext());
+    }
+
+    public void setKeyguardCallback(KeyguardSecurityCallback callback) {
+        mCallback = callback;
+        mLockPatternUtils = new LockPatternUtils(getContext());
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        mNavigationManager = new KeyguardNavigationManager(this);
+
+        mPukText = (TextView) findViewById(R.id.sim_puk_entry);
+        mPukText.setOnEditorActionListener(this);
+        mPinText = (TextView) findViewById(R.id.sim_pin_entry);
+        mPinText.setOnEditorActionListener(this);
+        mDelPukButton = findViewById(R.id.puk_delete_button);
+        mDelPukButton.setOnClickListener(this);
+        mDelPinButton = findViewById(R.id.pin_delete_button);
+        mDelPinButton.setOnClickListener(this);
+
+        mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
+        mKeyboardHelper = new PasswordEntryKeyboardHelper(mContext, mKeyboardView, this, false);
+        mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
+        mKeyboardHelper.setEnableHaptics(mLockPatternUtils.isTactileFeedbackEnabled());
+
+        mNavigationManager.setMessage(R.string.kg_sim_puk_recovery_hint);
+
+        mPinText.setFocusableInTouchMode(true);
+        mPinText.setOnFocusChangeListener(this);
+        mPukText.setFocusableInTouchMode(true);
+        mPukText.setOnFocusChangeListener(this);
+
+        setFocusableInTouchMode(true);
+
+        reset();
+    }
+
+    @Override
+    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
+        return mPukText.requestFocus(direction, previouslyFocusedRect);
+    }
+
+    public boolean needsInput() {
+        return false; // This view provides its own keypad
+    }
+
+    public void onPause() {
+
+    }
+
+    public void onResume() {
+        reset();
+    }
+
+    /** {@inheritDoc} */
+    public void cleanUp() {
+        // 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);
+                    }
+                });
+            }
+        }
+    }
+
+    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);
+            }
+        }
+        mCallback.userActivity(DIGIT_PRESS_WAKE_MILLIS);
+    }
+
+    @Override
+    public void onFocusChange(View view, boolean hasFocus) {
+        if (hasFocus)
+            mFocusedEntry = (TextView) view;
+    }
+
+    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 void checkPuk() {
+        // make sure the puk is at least 8 digits long.
+        if (mPukText.getText().length() < 8) {
+            // otherwise, display a message to the user, and don't submit.
+            mNavigationManager.setMessage(R.string.kg_invalid_sim_puk_hint);
+            mPukText.setText("");
+            return;
+        }
+
+        // make sure the PIN is between 4 and 8 digits
+        if (mPinText.getText().length() < 4
+                || mPinText.getText().length() > 8) {
+            // otherwise, display a message to the user, and don't submit.
+            mNavigationManager.setMessage(R.string.kg_invalid_sim_pin_hint);
+            mPinText.setText("");
+            return;
+        }
+
+        getSimUnlockProgressDialog().show();
+
+        if (!mCheckInProgress) {
+            mCheckInProgress = true;
+            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) {
+                                mCallback.dismiss(true);
+                            } else {
+                                mNavigationManager.setMessage(R.string.kg_invalid_puk);
+                                mPukText.setText("");
+                                mPinText.setText("");
+                            }
+                            mCheckInProgress = false;
+                        }
+                    });
+                }
+            }.start();
+        }
+    }
+
+    @Override
+    public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
+        // Check if this was the result of hitting the enter key
+        mCallback.userActivity(DIGIT_PRESS_WAKE_MILLIS);
+        if (event.getAction() == MotionEvent.ACTION_DOWN) {
+            if (actionId == EditorInfo.IME_NULL
+                || actionId == EditorInfo.IME_ACTION_DONE
+                || actionId == EditorInfo.IME_ACTION_NEXT) {
+                if (view == mPukText && mPukText.getText().length() < 8) {
+                    mNavigationManager.setMessage(R.string.kg_invalid_sim_puk_hint);
+                    mPukText.setText("");
+                    mPukText.requestFocus();
+                    return true;
+                } else if (view == mPinText) {
+                    if (mPinText.getText().length() < 4 || mPinText.getText().length() > 8) {
+                        mNavigationManager.setMessage(R.string.kg_invalid_sim_pin_hint);
+                        mPinText.setText("");
+                        mPinText.requestFocus();
+                    } else {
+                        checkPuk();
+                    }
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public void setLockPatternUtils(LockPatternUtils utils) {
+        mLockPatternUtils = utils;
+    }
+
+    @Override
+    public void reset() {
+        mNavigationManager.setMessage(R.string.kg_sim_puk_recovery_hint);
+        mPinText.setText("");
+        mPukText.setText("");
+        mPukText.requestFocus();
+    }
+
+    @Override
+    public KeyguardSecurityCallback getCallback() {
+        return mCallback;
+    }
+
+}
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..5704425
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusView.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.internal.policy.impl.keyguard;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.GridLayout;
+
+public class KeyguardStatusView extends GridLayout {
+    @SuppressWarnings("unused")
+    private KeyguardStatusViewManager mStatusViewManager;
+
+    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();
+
+        // StatusView manages all of the widgets in this view.
+        mStatusViewManager = new KeyguardStatusViewManager(this);
+    }
+
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java
new file mode 100644
index 0000000..8d83484
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java
@@ -0,0 +1,534 @@
+/*
+ * 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 com.android.internal.R;
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.widget.DigitalClock;
+import com.android.internal.widget.LockPatternUtils;
+
+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.widget.TextView;
+
+/***
+ * Manages a number of views inside of the given layout. See below for a list of widgets.
+ */
+class KeyguardStatusViewManager {
+    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 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 CharSequence mDateFormatString;
+
+    // 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;
+
+    // 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;
+
+    // Shadowed text values
+    private CharSequence mCarrierText;
+    private CharSequence mCarrierHelpText;
+    private String mHelpMessageText;
+    private String mInstructionText;
+    private CharSequence mOwnerInfoText;
+    private boolean mShowingStatus;
+    private CharSequence mPlmn;
+    private CharSequence mSpn;
+    private DigitalClock mDigitalClock;
+    protected boolean mBatteryCharged;
+    protected boolean mBatteryIsLow;
+
+    /**
+     * @param view the containing view of all widgets
+     */
+    public KeyguardStatusViewManager(View view) {
+        if (DEBUG) Log.v(TAG, "KeyguardStatusViewManager()");
+        mContainer = view;
+        mDateFormatString = getContext().getResources()
+            .getText(R.string.abbrev_wday_month_day_no_year);
+        mLockPatternUtils = new LockPatternUtils(view.getContext());
+        mUpdateMonitor = KeyguardUpdateMonitor.getInstance(view.getContext());
+
+        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);
+        mDigitalClock = (DigitalClock) findViewById(R.id.time);
+
+        // 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);
+            }
+        }
+    }
+
+    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) {
+        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();
+    }
+
+    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() {
+        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 (mOwnerInfoView == null && mOwnerInfoText != null) {
+            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;
+        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;
+                break;
+
+            case SimMissingLocked:
+                carrierText =  makeCarrierStringOnEmergencyCapable(
+                        getContext().getText(R.string.lockscreen_missing_sim_message_short),
+                        mPlmn);
+                carrierHelpTextId = R.string.lockscreen_missing_sim_instructions;
+                break;
+
+            case SimLocked:
+                carrierText = makeCarrierStringOnEmergencyCapable(
+                        getContext().getText(R.string.lockscreen_sim_locked_message),
+                        mPlmn);
+                break;
+
+            case SimPukLocked:
+                carrierText = makeCarrierStringOnEmergencyCapable(
+                        getContext().getText(R.string.lockscreen_sim_puk_locked_message),
+                        mPlmn);
+                break;
+        }
+
+        setCarrierText(carrierText);
+        setCarrierHelpText(carrierHelpTextId);
+    }
+
+    /*
+     * 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 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();
+            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 onSimStateChanged(IccCardConstants.State simState) {
+            updateCarrierStateWithSimStatus(simState);
+        }
+    };
+
+    /**
+     * 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/KeyguardSubdivisionLayout.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSubdivisionLayout.java
new file mode 100644
index 0000000..1cd796c
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSubdivisionLayout.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.ArrayList;
+
+/**
+ * A layout that arranges its children into a special type of grid.
+ */
+public class KeyguardSubdivisionLayout extends ViewGroup {
+    ArrayList<BiTree> mCells = new ArrayList<BiTree>();
+    int mNumChildren = -1;
+    int mWidth = -1;
+    int mHeight = -1;
+    int mTopChild = 0;
+
+    public KeyguardSubdivisionLayout(Context context) {
+        this(context, null, 0);
+    }
+
+    public KeyguardSubdivisionLayout(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public KeyguardSubdivisionLayout(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        setClipChildren(false);
+        setClipToPadding(false);
+        setChildrenDrawingOrderEnabled(true);
+    }
+
+    private class BiTree {
+        Rect rect;
+        BiTree left;
+        BiTree right;
+        int nodeDepth;
+        ArrayList<BiTree> leafs;
+
+        public BiTree(Rect r) {
+            rect = r;
+        }
+
+        public BiTree() {
+        }
+
+        boolean isLeaf() {
+            return (left == null) && (right == null);
+        }
+
+        int depth() {
+            if (left != null && right != null) {
+                return Math.max(left.depth(), right.depth()) + 1;
+            } else if (left != null) {
+                return left.depth() + 1;
+            } else if (right != null) {
+                return right.depth() + 1;
+            } else {
+                return 1;
+            }
+        }
+
+        int numLeafs() {
+            if (left != null && right != null) {
+                return left.numLeafs() + right.numLeafs();
+            } else if (left != null) {
+                return left.numLeafs();
+            } else if (right != null) {
+                return right.numLeafs();
+            } else {
+                return 1;
+            }
+        }
+
+        BiTree getNextNodeToBranch() {
+            if (leafs == null) {
+                leafs = new ArrayList<BiTree>();
+            }
+            leafs.clear();
+            getLeafs(leafs, 1);
+
+            // If the tree is complete, then we start a new level at the rightmost side.
+            double r = log2(leafs.size());
+            if (Math.ceil(r) == Math.floor(r)) {
+                return leafs.get(leafs.size() - 1);
+            }
+
+            // Tree is not complete, find the first leaf who's depth is less than the depth of
+            // the tree.
+            int treeDepth = depth();
+            for (int i = leafs.size() - 1; i >= 0; i--) {
+                BiTree n = leafs.get(i);
+                if (n.nodeDepth < treeDepth) {
+                    return n;
+                }
+            }
+            return null;
+        }
+
+        // Gets leafs in left to right order
+        void getLeafs(ArrayList<BiTree> leafs, int depth) {
+            if (isLeaf()) {
+                this.nodeDepth = depth;
+                leafs.add(this);
+            } else {
+                if (left != null) {
+                    left.getLeafs(leafs, depth + 1);
+                }
+                if (right != null) {
+                    right.getLeafs(leafs, depth + 1);
+                }
+            }
+        }
+    }
+
+    double log2(double d) {
+        return Math.log(d) / Math.log(2);
+    }
+
+    private void addCell(BiTree tree) {
+        BiTree branch = tree.getNextNodeToBranch();
+        Rect r = branch.rect;
+        branch.left = new BiTree();
+        branch.right = new BiTree();
+        int newDepth = tree.depth();
+
+        // For each level of the tree, we alternate between horizontal and vertical division
+        if (newDepth % 2 == 0) {
+            // Divide the cell vertically
+            branch.left.rect = new Rect(r.left, r.top, r.right, r.top + r.height() / 2);
+            branch.right.rect = new Rect(r.left, r.top + r.height() / 2, r.right, r.bottom);
+        } else {
+            // Divide the cell horizontally
+            branch.left.rect = new Rect(r.left, r.top, r.left + r.width() / 2, r.bottom);
+            branch.right.rect = new Rect(r.left + r.width() / 2, r.top, r.right, r.bottom);
+        }
+    }
+
+    private void constructGrid(int width, int height, int numChildren) {
+        mCells.clear();
+        BiTree root = new BiTree(new Rect(0, 0, width, height));
+
+        // We add nodes systematically until the number of leafs matches the number of children
+        while (root.numLeafs() < numChildren) {
+            addCell(root);
+        }
+
+        // Spit out the final list of cells
+        root.getLeafs(mCells, 1);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int width = MeasureSpec.getSize(widthMeasureSpec);
+        int height =  MeasureSpec.getSize(heightMeasureSpec);
+        int childCount = getChildCount();
+
+        if (mNumChildren != childCount || width != getMeasuredWidth() ||
+                height != getMeasuredHeight()) {
+            constructGrid(width, height, childCount);
+        }
+
+        for (int i = 0; i < childCount; i++) {
+            final View child = getChildAt(i);
+            Rect rect = mCells.get(i).rect;
+            child.measure(MeasureSpec.makeMeasureSpec(rect.width(), MeasureSpec.EXACTLY),
+                    MeasureSpec.makeMeasureSpec(rect.height(), MeasureSpec.EXACTLY));
+        }
+        setMeasuredDimension(width, height);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            final View child = getChildAt(i);
+            Rect rect = mCells.get(i).rect;
+            child.layout(rect.left, rect.top, rect.right, rect.bottom);
+        }
+    }
+
+    public void setTopChild(int top) {
+        mTopChild = top;
+        invalidate();
+    }
+
+    protected int getChildDrawingOrder(int childCount, int i) {
+        int ret = i;
+        if (i == childCount - 1) {
+            ret = mTopChild;
+        } else if (i >= mTopChild){
+            ret = i + 1;
+        }
+        return ret;
+    }
+}
\ No newline at end of file
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..3b4ed13
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardTransportControlView.java
@@ -0,0 +1,534 @@
+/*
+ * 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 java.lang.ref.WeakReference;
+
+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.MediaMetadataRetriever;
+import android.media.RemoteControlClient;
+import android.media.IRemoteControlDisplay;
+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 com.android.internal.policy.impl.keyguard.KeyguardHostView.TransportCallback;
+
+/**
+ * This is the widget responsible for showing music controls in keyguard.
+ */
+public class KeyguardTransportControlView extends KeyguardWidgetFrame 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 MAXDIM = 512;
+    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;
+
+    /**
+     * 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.
+                    hide();
+                }
+                if (DEBUG) Log.v(TAG, "New genId = " + msg.arg1 + ", clearing = " + msg.arg2);
+                mClientGeneration = msg.arg1;
+                mClientIntent = (PendingIntent) msg.obj;
+                break;
+
+            }
+        }
+    };
+    private 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 hide() {
+        if (DEBUG) Log.v(TAG, "Transport was told to hide");
+        if (mTransportCallback != null) {
+            mTransportCallback.hide();
+        } else {
+            Log.w(TAG, "Hide music, but callback wasn't set");
+        }
+    }
+
+    private void show() {
+        if (DEBUG) Log.v(TAG, "Transport was told to show");
+        if (mTransportCallback != null) {
+            mTransportCallback.show();
+        } else {
+            Log.w(TAG, "Show music, but callback wasn't set");
+        }
+    }
+
+    private void userActivity() {
+        // TODO Auto-generated method stub
+    }
+
+    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;
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        int dim = Math.min(MAXDIM, Math.max(getWidth(), getHeight()));
+//        Log.v(TAG, "setting max bitmap size: " + dim + "x" + dim);
+//        mAudioManager.remoteControlDisplayUsesBitmapSize(mIRCD, dim, dim);
+    }
+
+    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);
+    }
+
+    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;
+        boolean showIfHidden = false;
+        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;
+                showIfHidden = true;
+                break;
+
+            case RemoteControlClient.PLAYSTATE_BUFFERING:
+                imageResId = com.android.internal.R.drawable.ic_media_stop;
+                imageDescId = com.android.internal.R.string.lockscreen_transport_stop_description;
+                showIfHidden = true;
+                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;
+                showIfHidden = false;
+                break;
+        }
+        mBtnPlay.setImageResource(imageResId);
+        mBtnPlay.setContentDescription(getResources().getString(imageDescId));
+        if (showIfHidden) {
+            show();
+        }
+        mCurrentPlayState = state;
+    }
+
+    static class SavedState extends BaseSavedState {
+        boolean wasShowing;
+
+        SavedState(Parcelable superState) {
+            super(superState);
+        }
+
+        private SavedState(Parcel in) {
+            super(in);
+            this.wasShowing = in.readInt() != 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel out, int flags) {
+            super.writeToParcel(out, flags);
+            out.writeInt(this.wasShowing ? 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() {
+        if (DEBUG) Log.v(TAG, "onSaveInstanceState()");
+        Parcelable superState = super.onSaveInstanceState();
+        SavedState ss = new SavedState(superState);
+        ss.wasShowing = getVisibility() == View.VISIBLE;
+        return ss;
+    }
+
+    @Override
+    public void onRestoreInstanceState(Parcelable state) {
+        if (DEBUG) Log.v(TAG, "onRestoreInstanceState()");
+        if (!(state instanceof SavedState)) {
+            super.onRestoreInstanceState(state);
+            return;
+        }
+        SavedState ss = (SavedState) state;
+        super.onRestoreInstanceState(ss.getSuperState());
+        if (ss.wasShowing) {
+            show();
+        }
+    }
+
+    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);
+            userActivity();
+        }
+    }
+
+    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(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..4524c94
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java
@@ -0,0 +1,739 @@
+/*
+ * 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 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;
+
+    // Device provisioning state
+    private boolean mDeviceProvisioned;
+
+    // Battery status
+    private BatteryStatus mBatteryStatus;
+
+    // Password attempts
+    private int mFailedAttempts = 0;
+    private int mFailedBiometricUnlockAttempts = 0;
+
+    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;
+            }
+        }
+    };
+
+    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));
+            }
+        }
+    };
+
+    /**
+     * 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, 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.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) {
+            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);
+
+        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.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));
+            }
+        }
+    }
+
+    /**
+     * 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);
+            }
+        }
+        try {
+            reply.sendResult(null);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * 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();
+            }
+        }
+    }
+
+    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 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 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..3d65e68
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/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;
+
+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/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewBase.java
new file mode 100644
index 0000000..ad5de0e
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewBase.java
@@ -0,0 +1,254 @@
+/*
+ * 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.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.view.KeyEvent;
+import android.widget.LinearLayout;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Slog;
+
+/**
+ * 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 LinearLayout {
+
+    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();
+
+    @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);
+        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..d9088e0
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
@@ -0,0 +1,318 @@
+/*
+ * 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.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.IBinder;
+import android.os.SystemProperties;
+import android.util.Log;
+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.widget.LockPatternUtils;
+import com.android.internal.R;
+
+/**
+ * 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 {
+    private final static boolean DEBUG = false;
+    private static String TAG = "KeyguardViewManager";
+
+    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() {
+        if (DEBUG) Log.d(TAG, "show(); mKeyguardView==" + mKeyguardView);
+
+        boolean enableScreenRotation = shouldEnableScreenRotation();
+
+        maybeCreateKeyguardLocked(enableScreenRotation);
+        maybeEnableScreenRotation(enableScreenRotation);
+
+        // 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;
+        if (DEBUG) Log.v(TAG, "KGVM: Set visibility on " + mKeyguardHost + " to " + 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);
+        }
+
+        @Override
+        protected void onConfigurationChanged(Configuration newConfig) {
+            super.onConfigurationChanged(newConfig);
+            maybeCreateKeyguardLocked(shouldEnableScreenRotation());
+        }
+    }
+
+    private void maybeCreateKeyguardLocked(boolean enableScreenRotation) {
+        final boolean isActivity = (mContext instanceof Activity); // for test activity
+
+        if (mKeyguardHost == null) {
+            if (DEBUG) Log.d(TAG, "keyguard host is null, creating it...");
+
+            mKeyguardHost = new ViewManagerHost(mContext);
+
+            int flags = WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN
+                    | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER
+                    | WindowManager.LayoutParams.FLAG_SLIPPERY;
+
+            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;
+            lp.setTitle(isActivity ? "KeyguardMock" : "Keyguard");
+            mWindowLayoutParams = lp;
+            mViewManager.addView(mKeyguardHost, lp);
+        }
+        inflateKeyguardView();
+        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
+    }
+
+    private void inflateKeyguardView() {
+        if (mKeyguardView != null) {
+            mKeyguardHost.removeView(mKeyguardView);
+        }
+        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);
+
+        if (mScreenOn) {
+            mKeyguardView.show();
+        }
+    }
+
+    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() {
+        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());
+    }
+
+    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/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
new file mode 100644
index 0000000..372b0fc
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
@@ -0,0 +1,1355 @@
+/*
+ * 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 com.android.internal.telephony.IccCardConstants;
+import com.android.internal.widget.LockPatternUtils;
+
+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.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.WindowManagerGlobal;
+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 {
+    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;
+
+    /** UserManager for querying number of users */
+    private UserManager mUserManager;
+
+    /**
+     * 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;
+
+    /**
+     * 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 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 {
+
+        /**
+         * 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(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);
+    }
+
+    KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
+
+        @Override
+        public void onUserSwitched(int userId) {
+            mLockPatternUtils.setCurrentUser(userId);
+            synchronized (KeyguardViewMediator.this) {
+                resetStateLocked();
+            }
+            // We should always go back to the locked state when a user
+            // switch happens.  Is there a more direct way to do this?
+            try {
+                WindowManagerGlobal.getWindowManagerService().lockNow();
+            } catch (RemoteException e) {
+            }
+        }
+
+        @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.sendBroadcast(mUserPresentIntent);
+        }
+
+        @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;
+            }
+        }
+
+    };
+
+    ViewMediatorCallback mViewMediatorCallback = new ViewMediatorCallback() {
+        public void pokeWakelock() {
+            KeyguardViewMediator.this.pokeWakelock();
+        }
+
+        public void pokeWakelock(long holdMs) {
+            KeyguardViewMediator.this.pokeWakelock(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);
+        }
+    };
+
+    public void pokeWakelock() {
+        pokeWakelock(AWAKE_INTERVAL_DEFAULT_MS);
+    }
+
+    public void pokeWakelock(long 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);
+        }
+    }
+
+    /**
+     * 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);
+        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 = KeyguardUpdateMonitor.getInstance(context);
+
+        mLockPatternUtils = lockPatternUtils != null
+                ? lockPatternUtils : new LockPatternUtils(mContext);
+
+        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.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, (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 (mUserManager.getUsers().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();
+    }
+
+    /**
+     * 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 mLockPatternUtils.isSecure()
+            || KeyguardUpdateMonitor.getInstance(mContext).isSimPinSecure();
+    }
+
+    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;
+    }
+
+    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.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 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, 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();
+
+        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);
+            }
+        }
+    }
+
+    /**
+     * 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/KeyguardWidgetFrame.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java
new file mode 100644
index 0000000..70a6ffa
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java
@@ -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.
+ */
+
+package com.android.internal.policy.impl.keyguard;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.NinePatchDrawable;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+import com.android.internal.R;
+
+public class KeyguardWidgetFrame extends FrameLayout {
+    private final static PorterDuffXfermode sAddBlendMode =
+            new PorterDuffXfermode(PorterDuff.Mode.ADD);
+    private static int sWidgetPagePadding;
+    private static Drawable sLeftOverscrollDrawable;
+    private static Drawable sRightOverscrollDrawable;
+
+    private Drawable mForegroundDrawable;
+    private float mOverScrollAmount = 0f;
+    private final Rect mForegroundRect = new Rect();
+    private int mForegroundAlpha = 0;
+
+    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);
+        if (sLeftOverscrollDrawable == null) {
+            Resources res = context.getResources();
+            sLeftOverscrollDrawable = res.getDrawable(R.drawable.kg_widget_overscroll_layer_left);
+            sRightOverscrollDrawable = res.getDrawable(R.drawable.kg_widget_overscroll_layer_right);
+            sWidgetPagePadding = res.getDimensionPixelSize(R.dimen.kg_widget_page_padding);
+        }
+        setPadding(sWidgetPagePadding, sWidgetPagePadding, sWidgetPagePadding, sWidgetPagePadding);
+    }
+
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        super.dispatchDraw(canvas);
+        if (mForegroundAlpha > 0) {
+            mForegroundDrawable.setBounds(mForegroundRect);
+            Paint p = ((NinePatchDrawable) mForegroundDrawable).getPaint();
+            p.setXfermode(sAddBlendMode);
+            mForegroundDrawable.draw(canvas);
+            p.setXfermode(null);
+        }
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+        mForegroundRect.set(sWidgetPagePadding, sWidgetPagePadding,
+                w - sWidgetPagePadding, h - sWidgetPagePadding);
+    }
+
+    void setOverScrollAmount(float r, boolean left) {
+        if (Float.compare(mOverScrollAmount, r) != 0) {
+            mOverScrollAmount = r;
+            if (left && mForegroundDrawable != sLeftOverscrollDrawable) {
+                mForegroundDrawable = sLeftOverscrollDrawable;
+            } else if (!left && mForegroundDrawable != sRightOverscrollDrawable) {
+                mForegroundDrawable = sRightOverscrollDrawable;
+            }
+
+            mForegroundAlpha = (int) Math.round((r * 255));
+            mForegroundDrawable.setAlpha(mForegroundAlpha);
+            if (getLayerType() != LAYER_TYPE_HARDWARE) {
+                setLayerType(LAYER_TYPE_HARDWARE, null);
+            }
+            invalidate();
+        } else {
+            if (getLayerType() != LAYER_TYPE_NONE) {
+                setLayerType(LAYER_TYPE_NONE, null);
+            }
+        }
+    }
+}
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..fd9362a
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.TimeInterpolator;
+import android.appwidget.AppWidgetHostView;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.View;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+
+import android.widget.FrameLayout;
+
+public class KeyguardWidgetPager extends PagedView {
+    ZInterpolator mZInterpolator = new ZInterpolator(0.5f);
+    private static float CAMERA_DISTANCE = 10000;
+    private static float TRANSITION_SCALE_FACTOR = 0.74f;
+    private static float TRANSITION_PIVOT = 0.65f;
+    private static float TRANSITION_MAX_ROTATION = 30;
+    private static final boolean PERFORM_OVERSCROLL_ROTATION = true;
+    private AccelerateInterpolator mAlphaInterpolator = new AccelerateInterpolator(0.9f);
+    private DecelerateInterpolator mLeftScreenAlphaInterpolator = new DecelerateInterpolator(4);
+
+    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);
+    }
+
+    /*
+     * We wrap widgets in a special frame which handles drawing the overscroll foreground.
+     */
+    public void addWidget(AppWidgetHostView widget) {
+        KeyguardWidgetFrame frame = new KeyguardWidgetFrame(getContext());
+        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
+                LayoutParams.MATCH_PARENT);
+        lp.gravity = Gravity.CENTER;
+        // 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);
+        addView(frame);
+    }
+
+    /*
+     * 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);
+    }
+
+    // In apps customize, we have a scrolling effect which emulates pulling cards off of a stack.
+    @Override
+    protected void screenScrolled(int screenCenter) {
+        super.screenScrolled(screenCenter);
+
+        for (int i = 0; i < getChildCount(); i++) {
+            View v = getPageAt(i);
+            if (v != null) {
+                float scrollProgress = getScrollProgress(screenCenter, v, i);
+
+                float interpolatedProgress =
+                        mZInterpolator.getInterpolation(Math.abs(Math.min(scrollProgress, 0)));
+                float scale = (1 - interpolatedProgress) +
+                        interpolatedProgress * TRANSITION_SCALE_FACTOR;
+                float translationX = Math.min(0, scrollProgress) * v.getMeasuredWidth();
+
+                float alpha;
+
+                if (scrollProgress < 0) {
+                    alpha = scrollProgress < 0 ? mAlphaInterpolator.getInterpolation(
+                        1 - Math.abs(scrollProgress)) : 1.0f;
+                } else {
+                    // On large screens we need to fade the page as it nears its leftmost position
+                    alpha = mLeftScreenAlphaInterpolator.getInterpolation(1 - scrollProgress);
+                }
+
+                v.setCameraDistance(mDensity * CAMERA_DISTANCE);
+                int pageWidth = v.getMeasuredWidth();
+                int pageHeight = v.getMeasuredHeight();
+
+                if (PERFORM_OVERSCROLL_ROTATION) {
+                    if (i == 0 && scrollProgress < 0) {
+                        // Overscroll to the left
+                        v.setPivotX(TRANSITION_PIVOT * pageWidth);
+                        v.setRotationY(-TRANSITION_MAX_ROTATION * scrollProgress);
+                        if (v instanceof KeyguardWidgetFrame) {
+                            ((KeyguardWidgetFrame) v).setOverScrollAmount(Math.abs(scrollProgress),
+                                    true);
+                        }
+                        scale = 1.0f;
+                        alpha = 1.0f;
+                        // On the first page, we don't want the page to have any lateral motion
+                        translationX = 0;
+                    } else if (i == getChildCount() - 1 && scrollProgress > 0) {
+                        // Overscroll to the right
+                        v.setPivotX((1 - TRANSITION_PIVOT) * pageWidth);
+                        v.setRotationY(-TRANSITION_MAX_ROTATION * scrollProgress);
+                        scale = 1.0f;
+                        alpha = 1.0f;
+                        if (v instanceof KeyguardWidgetFrame) {
+                            ((KeyguardWidgetFrame) v).setOverScrollAmount(Math.abs(scrollProgress),
+                                    false);
+                        }
+                        // On the last page, we don't want the page to have any lateral motion.
+                        translationX = 0;
+                    } else {
+                        v.setPivotY(pageHeight / 2.0f);
+                        v.setPivotX(pageWidth / 2.0f);
+                        v.setRotationY(0f);
+                        if (v instanceof KeyguardWidgetFrame) {
+                            ((KeyguardWidgetFrame) v).setOverScrollAmount(0, false);
+                        }
+                    }
+                }
+
+                v.setTranslationX(translationX);
+                v.setScaleX(scale);
+                v.setScaleY(scale);
+                v.setAlpha(alpha);
+
+                // 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);
+                }
+            }
+        }
+    }
+}
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..fc7c90f
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java
@@ -0,0 +1,1708 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+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.Interpolator;
+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 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 = 550;
+    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;
+
+    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 mNextPage = INVALID_PAGE;
+    protected int mMaxScrollX;
+    protected Scroller mScroller;
+    private VelocityTracker mVelocityTracker;
+
+    private float mDownMotionX;
+    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 float ALPHA_QUANTIZE_LEVEL = 0.0001f;
+
+    protected int mTouchState = TOUCH_STATE_REST;
+    protected boolean mForceScreenScrolled = false;
+
+    protected OnLongClickListener mLongClickListener;
+
+    protected boolean mAllowLongPress = true;
+
+    protected int mTouchSlop;
+    private int mPagingTouchSlop;
+    private int mMaximumVelocity;
+    private int mMinimumWidth;
+    protected int mPageSpacing;
+    protected int mPageLayoutPaddingTop;
+    protected int mPageLayoutPaddingBottom;
+    protected int mPageLayoutPaddingLeft;
+    protected int mPageLayoutPaddingRight;
+    protected int mPageLayoutWidthGap;
+    protected int mPageLayoutHeightGap;
+    protected int mCellCountX = 0;
+    protected int mCellCountY = 0;
+    protected boolean mCenterPagesVertically;
+    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 = true;
+
+    // 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;
+
+    public interface PageSwitchListener {
+        void onPageSwitch(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));
+        mPageLayoutPaddingTop = a.getDimensionPixelSize(
+                R.styleable.PagedView_pageLayoutPaddingTop, 0);
+        mPageLayoutPaddingBottom = a.getDimensionPixelSize(
+                R.styleable.PagedView_pageLayoutPaddingBottom, 0);
+        mPageLayoutPaddingLeft = a.getDimensionPixelSize(
+                R.styleable.PagedView_pageLayoutPaddingLeft, 0);
+        mPageLayoutPaddingRight = a.getDimensionPixelSize(
+                R.styleable.PagedView_pageLayoutPaddingRight, 0);
+        mPageLayoutWidthGap = a.getDimensionPixelSize(
+                R.styleable.PagedView_pageLayoutWidthGap, 0);
+        mPageLayoutHeightGap = a.getDimensionPixelSize(
+                R.styleable.PagedView_pageLayoutHeightGap, 0);
+        mScrollIndicatorPaddingLeft =
+            a.getDimensionPixelSize(R.styleable.PagedView_scrollIndicatorPaddingLeft, 0);
+        mScrollIndicatorPaddingRight =
+            a.getDimensionPixelSize(R.styleable.PagedView_scrollIndicatorPaddingRight, 0);
+        a.recycle();
+
+        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;
+        mCenterPagesVertically = true;
+
+        final ViewConfiguration configuration = ViewConfiguration.get(getContext());
+        mTouchSlop = configuration.getScaledTouchSlop();
+        mPagingTouchSlop = configuration.getScaledPagingTouchSlop();
+        mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
+        mDensity = getResources().getDisplayMetrics().density;
+
+        mFlingThresholdVelocity = (int) (FLING_THRESHOLD_VELOCITY * mDensity);
+        mMinFlingVelocity = (int) (MIN_FLING_VELOCITY * mDensity);
+        mMinSnapVelocity = (int) (MIN_SNAP_VELOCITY * mDensity);
+        setOnHierarchyChangeListener(this);
+    }
+
+    public void setPageSwitchListener(PageSwitchListener pageSwitchListener) {
+        mPageSwitchListener = pageSwitchListener;
+        if (mPageSwitchListener != null) {
+            mPageSwitchListener.onPageSwitch(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) {
+        if (!mScroller.isFinished()) {
+            mScroller.abortAnimation();
+        }
+        // don't introduce any checks like mCurrentPage == currentPage here-- if we change the
+        // the default
+        if (getChildCount() == 0) {
+            return;
+        }
+
+        mCurrentPage = Math.max(0, Math.min(currentPage, getPageCount() - 1));
+        updateCurrentPageScroll();
+        updateScrollingIndicator();
+        notifyPageSwitchListener();
+        invalidate();
+    }
+
+    protected void notifyPageSwitchListener() {
+        if (mPageSwitchListener != null) {
+            mPageSwitchListener.onPageSwitch(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;
+    }
+
+    // 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;
+            notifyPageSwitchListener();
+
+            // 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();
+            }
+
+            // Notify the user when the page changes
+            AccessibilityManager accessibilityManager = (AccessibilityManager)
+                    getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
+            if (accessibilityManager.isEnabled()) {
+                AccessibilityEvent ev =
+                    AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_SCROLLED);
+                ev.getText().add(getCurrentPageDescription());
+                sendAccessibilityEventUnchecked(ev);
+            }
+            return true;
+        }
+        return false;
+    }
+
+    public String getCurrentPageDescription() {
+        return "";
+    }
+
+    @Override
+    public void computeScroll() {
+        computeScrollHelper();
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        if (!mIsDataReady || getChildCount() == 0) {
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+            return;
+        }
+
+        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+
+        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);
+        final int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            // disallowing padding in paged view (just pass 0)
+            final View child = getPageAt(i);
+
+            int childWidthMode = MeasureSpec.EXACTLY;
+            int childHeightMode = MeasureSpec.EXACTLY;
+
+            final int childWidthMeasureSpec =
+                MeasureSpec.makeMeasureSpec(widthSize - horizontalPadding, childWidthMode);
+            final int childHeightMeasureSpec =
+                MeasureSpec.makeMeasureSpec(heightSize - verticalPadding, childHeightMode);
+
+            child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+        }
+
+        setMeasuredDimension(widthSize, heightSize);
+
+        // 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 (childCount > 0) {
+            if (DEBUG) Log.d(TAG, "getRelativeChildOffset(): " + getMeasuredWidth() + ", "
+                    + 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 verticalPadding = getPaddingTop() + getPaddingBottom();
+        final int childCount = getChildCount();
+        int childLeft = getRelativeChildOffset(0);
+
+        for (int i = 0; i < childCount; i++) {
+            final View child = getPageAt(i);
+            if (child.getVisibility() != View.GONE) {
+                final int childWidth = getScaledMeasuredWidth(child);
+                final int childHeight = child.getMeasuredHeight();
+                int childTop = getPaddingTop();
+                if (mCenterPagesVertically) {
+                    childTop += ((getMeasuredHeight() - verticalPadding) - childHeight) / 2;
+                }
+
+                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) {
+        if (isScrollingIndicatorEnabled()) {
+            updateScrollingIndicator();
+        }
+        boolean isInOverscroll = mOverScrollX < 0 || mOverScrollX > mMaxScrollX;
+
+        if (mFadeInAdjacentScreens && !isInOverscroll) {
+            for (int i = 0; i < getChildCount(); i++) {
+                View child = getChildAt(i);
+                if (child != null) {
+                    float scrollProgress = getScrollProgress(screenCenter, child, i);
+                    float alpha = 1 - Math.abs(scrollProgress);
+                    child.setAlpha(alpha);
+                }
+            }
+            invalidate();
+        }
+    }
+
+    @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) {
+        invalidate();
+        invalidateCachedOffsets();
+        // This prevents a crash when a child is removed that was the current page.
+        mCurrentPage = Math.min(mCurrentPage, getChildCount() - 1);
+    }
+
+    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) {
+        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 (mChildRelativeOffsets != null && mChildRelativeOffsets[index] != -1) {
+            return mChildRelativeOffsets[index];
+        } else {
+            final int padding = getPaddingLeft() + getPaddingRight();
+            final int offset = getPaddingLeft() +
+                    (getMeasuredWidth() - 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);
+    }
+
+    protected void getVisiblePages(int[] range) {
+        final int pageCount = getChildCount();
+
+        if (pageCount > 0) {
+            final int screenWidth = getMeasuredWidth();
+            int leftScreen = 0;
+            int rightScreen = 0;
+            View currPage = getPageAt(leftScreen);
+            while (leftScreen < pageCount - 1 &&
+                    currPage.getX() + currPage.getWidth() -
+                    currPage.getPaddingRight() < getScrollX()) {
+                leftScreen++;
+                currPage = getPageAt(leftScreen);
+            }
+            rightScreen = leftScreen;
+            currPage = getPageAt(rightScreen + 1);
+            while (rightScreen < pageCount - 1 &&
+                    currPage.getX() - currPage.getPaddingLeft() < getScrollX() + screenWidth) {
+                rightScreen++;
+                currPage = getPageAt(rightScreen + 1);
+            }
+            range[0] = leftScreen;
+            range[1] = rightScreen;
+        } else {
+            range[0] = -1;
+            range[1] = -1;
+        }
+    }
+
+    protected boolean shouldDrawChild(View child) {
+        return child.getAlpha() > 0;
+    }
+
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        int halfScreenSize = getMeasuredWidth() / 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());
+
+                for (int i = getChildCount() - 1; i >= 0; i--) {
+                    final View v = getPageAt(i);
+                    if (mForceDrawAllChildrenNextFrame ||
+                               (leftScreen <= i && i <= rightScreen && shouldDrawChild(v))) {
+                        drawChild(canvas, v, 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;
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+        if (disallowIntercept) {
+            // We need to make sure to cancel our long press if
+            // a scrollable widget takes over touch events
+            final View currentPage = getPageAt(mCurrentPage);
+            currentPage.cancelLongPress();
+        }
+        super.requestDisallowInterceptTouchEvent(disallowIntercept);
+    }
+
+    /**
+     * 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 < 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 > (getMeasuredWidth() - getRelativeChildOffset(mCurrentPage) + mPageSpacing));
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        /*
+         * 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;
+                mLastMotionX = x;
+                mLastMotionY = y;
+                mLastMotionXRemainder = 0;
+                mTotalMotionX = 0;
+                mActivePointerId = ev.getPointerId(0);
+                mAllowLongPress = 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 {
+                    mTouchState = TOUCH_STATE_SCROLLING;
+                }
+
+                // check if this can be the beginning of a tap on the side of the pages
+                // to scroll the current page
+                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:
+                mTouchState = TOUCH_STATE_REST;
+                mAllowLongPress = false;
+                mActivePointerId = INVALID_POINTER;
+                releaseVelocityTracker();
+                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) {
+        /*
+         * Locally do absolute value. mLastMotionX is set to the y value
+         * of the down event.
+         */
+        final int pointerIndex = ev.findPointerIndex(mActivePointerId);
+        if (pointerIndex == -1) {
+            return;
+        }
+        final float x = ev.getX(pointerIndex);
+        final float y = ev.getY(pointerIndex);
+        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 = getScrollX();
+                mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
+                pageBeginMoving();
+            }
+            // Either way, cancel any pending longpress
+            cancelCurrentPageLongPress();
+        }
+    }
+
+    protected void cancelCurrentPageLongPress() {
+        if (mAllowLongPress) {
+            mAllowLongPress = false;
+            // Try canceling the long press. It could also have been scheduled
+            // by a distant descendant, so use the mAllowLongPress flag to block
+            // everything
+            final View currentPage = getPageAt(mCurrentPage);
+            if (currentPage != null) {
+                currentPage.cancelLongPress();
+            }
+        }
+    }
+
+    protected float getScrollProgress(int screenCenter, View v, int page) {
+        final int halfScreenSize = getMeasuredWidth() / 2;
+
+        int totalDistance = getScaledMeasuredWidth(v) + mPageSpacing;
+        int delta = screenCenter - (getChildOffset(page) -
+                getRelativeChildOffset(page) + halfScreenSize);
+
+        float scrollProgress = delta / (totalDistance * 1.0f);
+        scrollProgress = Math.min(scrollProgress, 1.0f);
+        scrollProgress = Math.max(scrollProgress, -1.0f);
+        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 = getMeasuredWidth();
+
+        // 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 = getMeasuredWidth();
+
+        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) {
+        // 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();
+            mLastMotionXRemainder = 0;
+            mTotalMotionX = 0;
+            mActivePointerId = ev.getPointerId(0);
+            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 {
+                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 {
+                onUnhandledTap(ev);
+            }
+            mTouchState = TOUCH_STATE_REST;
+            mActivePointerId = INVALID_POINTER;
+            releaseVelocityTracker();
+            break;
+
+        case MotionEvent.ACTION_CANCEL:
+            if (mTouchState == TOUCH_STATE_SCROLLING) {
+                snapToDestination();
+            }
+            mTouchState = TOUCH_STATE_REST;
+            mActivePointerId = INVALID_POINTER;
+            releaseVelocityTracker();
+            break;
+
+        case MotionEvent.ACTION_POINTER_UP:
+            onSecondaryPointerUp(ev);
+            break;
+        }
+
+        return true;
+    }
+
+    @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();
+            }
+        }
+    }
+
+    protected void onUnhandledTap(MotionEvent ev) {}
+
+    @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 getPageNearestToCenterOfScreen() {
+        int minDistanceFromScreenCenter = Integer.MAX_VALUE;
+        int minDistanceFromScreenCenterIndex = -1;
+        int screenCenter = getScrollX() + (getMeasuredWidth() / 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 = 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 = getMeasuredWidth() / 2;
+
+        if (DEBUG) Log.d(TAG, "snapToPage.getChildOffset(): " + getChildOffset(whichPage));
+        if (DEBUG) Log.d(TAG, "snapToPageWithVelocity.getRelativeChildOffset(): "
+                + getMeasuredWidth() + ", " + 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 snapToPage(int whichPage, int duration) {
+        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(): " + getMeasuredWidth() + ", "
+                + getChildWidth(whichPage));
+        int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage);
+        final int sX = mUnboundedScrollX;
+        final int delta = newX - sX;
+        snapToPage(whichPage, delta, duration);
+    }
+
+    protected void snapToPage(int whichPage, int delta, int duration) {
+        mNextPage = whichPage;
+
+        View focusedChild = getFocusedChild();
+        if (focusedChild != null && whichPage != mCurrentPage &&
+                focusedChild == getPageAt(mCurrentPage)) {
+            focusedChild.clearFocus();
+        }
+
+        pageBeginMoving();
+        awakenScrollBars(duration);
+        if (duration == 0) {
+            duration = Math.abs(delta);
+        }
+
+        if (!mScroller.isFinished()) mScroller.abortAnimation();
+        mScroller.startScroll(mUnboundedScrollX, 0, delta, 0, duration);
+
+        notifyPageSwitchListener();
+        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;
+    }
+
+    /**
+     * @return True is long presses are still allowed for the current touch
+     */
+    public boolean allowLongPress() {
+        return mAllowLongPress;
+    }
+
+    /**
+     * Set true to allow long-press events to be triggered, usually checked by
+     * {@link Launcher} to accept or block dpad-initiated long-presses.
+     */
+    public void setAllowLongPress(boolean allowLongPress) {
+        mAllowLongPress = allowLongPress;
+    }
+
+    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 = getMeasuredWidth();
+        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);
+    }
+
+    /* 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_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..e4d9215
--- /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..d990f5f
--- /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.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) {
+            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.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));
+            }
+        }
+    }
+
+    /**
+     * 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..8ff8dad
--- /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.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, (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/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/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index e63da05..87a6c1b 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>");
@@ -423,11 +427,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 +449,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;
@@ -826,7 +834,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 +1128,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 +1138,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 +1165,7 @@
         mTempTouchState.down = down;
         mTempTouchState.deviceId = entry->deviceId;
         mTempTouchState.source = entry->source;
+        mTempTouchState.displayId = displayId;
         isSplit = false;
     } else {
         mTempTouchState.copyFrom(mTouchState);
@@ -1174,8 +1188,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 +1317,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 +1456,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 +1515,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 +1631,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 +1640,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 +1716,7 @@
 }
 
 void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
-    int32_t eventType = POWER_MANAGER_OTHER_EVENT;
+    int32_t eventType = USER_ACTIVITY_EVENT_OTHER;
     switch (eventEntry->type) {
     case EventEntry::TYPE_MOTION: {
         const MotionEntry* motionEntry = static_cast<const MotionEntry*>(eventEntry);
@@ -1702,7 +1725,7 @@
         }
 
         if (MotionEvent::isTouchEvent(motionEntry->source, motionEntry->action)) {
-            eventType = POWER_MANAGER_TOUCH_EVENT;
+            eventType = USER_ACTIVITY_EVENT_TOUCH;
         }
         break;
     }
@@ -1711,7 +1734,7 @@
         if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) {
             return;
         }
-        eventType = POWER_MANAGER_BUTTON_EVENT;
+        eventType = USER_ACTIVITY_EVENT_BUTTON;
         break;
     }
     }
@@ -1845,7 +1868,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 +2294,7 @@
             originalMotionEntry->xPrecision,
             originalMotionEntry->yPrecision,
             originalMotionEntry->downTime,
+            originalMotionEntry->displayId,
             splitPointerCount, splitPointerProperties, splitPointerCoords);
 
     if (originalMotionEntry->injectionState) {
@@ -2351,7 +2375,7 @@
     { // acquire lock
         mLock.lock();
 
-        if (mInputFilterEnabled) {
+        if (shouldSendKeyToInputFilterLocked(args)) {
             mLock.unlock();
 
             policyFlags |= POLICY_FLAG_FILTERED;
@@ -2377,6 +2401,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 +2443,7 @@
     { // acquire lock
         mLock.lock();
 
-        if (mInputFilterEnabled) {
+        if (shouldSendMotionToInputFilterLocked(args)) {
             mLock.unlock();
 
             MotionEvent event;
@@ -2438,6 +2466,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,6 +2478,11 @@
     }
 }
 
+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",
@@ -2532,6 +2566,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 +2588,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 +2600,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 +2974,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 +3081,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 +3101,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),
@@ -3802,14 +3845,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 +3863,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 +3907,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 +4070,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 +4101,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 +4137,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 +4156,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 +4289,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 +4300,7 @@
     split = false;
     deviceId = -1;
     source = 0;
+    displayId = -1;
     windows.clear();
 }
 
@@ -4259,6 +4309,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..af7ff5e 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -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;
@@ -899,6 +902,10 @@
     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 +935,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..c2705b0 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]);
diff --git a/services/input/InputListener.h b/services/input/InputListener.h
index b1dc0b8..486852b 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);
 
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index cd6a2ec..d56b9a9 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;
 }
 
 
@@ -2001,9 +1985,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 +2003,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 +2072,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 +2303,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 +2332,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 +2408,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 +2431,7 @@
 
     mPointerVelocityControl.move(when, &deltaX, &deltaY);
 
+    int32_t displayId;
     if (mPointerController != NULL) {
         if (moved || scrolled || buttonsChanged) {
             mPointerController->setPresentation(
@@ -2463,9 +2452,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 +2488,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 +2498,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 +2511,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 +2545,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 +2608,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 +2617,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 +2779,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 +2819,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 +2859,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 +2878,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 +2984,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 +3011,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 +3104,6 @@
         }
 
         // Orientation
-        mOrientationCenter = 0;
         mOrientationScale = 0;
         if (mHaveTilt) {
             mOrientedRanges.haveOrientation = true;
@@ -3067,10 +3119,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 +3163,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 +3202,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 +3238,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 +3337,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 +3459,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 +4012,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 +4109,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 +4147,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 +4424,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 +5333,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 +5346,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 +5361,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 +5371,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 +5385,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 +5395,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 +5416,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 +5478,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 +6282,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 +6290,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..e1a8dd8 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;
 };
 
 
@@ -992,7 +1041,7 @@
 
     // Immutable configuration parameters.
     struct Parameters {
-        int32_t associatedDisplayId;
+        bool hasAssociatedDisplay;
         bool orientationAware;
     } mParameters;
 
@@ -1042,7 +1091,7 @@
         };
 
         Mode mode;
-        int32_t associatedDisplayId;
+        bool hasAssociatedDisplay;
         bool orientationAware;
     } mParameters;
 
@@ -1143,7 +1192,7 @@
         };
 
         DeviceType deviceType;
-        int32_t associatedDisplayId;
+        bool hasAssociatedDisplay;
         bool associatedDisplayIsExternal;
         bool orientationAware;
 
@@ -1162,6 +1211,7 @@
             SIZE_CALIBRATION_NONE,
             SIZE_CALIBRATION_GEOMETRIC,
             SIZE_CALIBRATION_DIAMETER,
+            SIZE_CALIBRATION_BOX,
             SIZE_CALIBRATION_AREA,
         };
 
@@ -1271,20 +1321,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 +1354,6 @@
 
     float mSizeScale;
 
-    float mOrientationCenter;
     float mOrientationScale;
 
     float mDistanceScale;
@@ -1346,8 +1405,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..3118099 100644
--- a/services/input/InputWindow.h
+++ b/services/input/InputWindow.h
@@ -132,6 +132,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/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index abda10b..c6dbbf3 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;
     }
 
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..f960833 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;
@@ -242,32 +243,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 +311,7 @@
             }
         }
     }
-    
+
     public void removeLocked(String packageName) {
         removeLocked(mRtcWakeupAlarms, packageName);
         removeLocked(mRtcAlarms, packageName);
@@ -327,6 +335,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 +668,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 +853,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 +873,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..385681e 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -27,10 +27,10 @@
 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.os.UserHandle;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -150,13 +150,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,75 +165,95 @@
         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);
         mContext.registerReceiver(new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
-                onUserRemoved(intent.getIntExtra(Intent.EXTRA_USERID, -1));
+                onUserRemoved(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1));
             }
         }, userFilter);
+
+        IntentFilter userStopFilter = new IntentFilter();
+        userStopFilter.addAction(Intent.ACTION_USER_STOPPED);
+        mContext.registerReceiverAsUser(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                onUserStopped(getSendingUserId());
+            }
+        }, UserHandle.ALL, userFilter, null, null);
     }
 
     @Override
     public int allocateAppWidgetId(String packageName, int hostId) throws RemoteException {
-        return getImplForUser().allocateAppWidgetId(packageName, hostId);
+        return getImplForUser(UserHandle.getCallingUserId()).allocateAppWidgetId(
+                packageName, hostId);
     }
     
     @Override
     public void deleteAppWidgetId(int appWidgetId) throws RemoteException {
-        getImplForUser().deleteAppWidgetId(appWidgetId);
+        getImplForUser(UserHandle.getCallingUserId()).deleteAppWidgetId(appWidgetId);
     }
 
     @Override
     public void deleteHost(int hostId) throws RemoteException {
-        getImplForUser().deleteHost(hostId);
+        getImplForUser(UserHandle.getCallingUserId()).deleteHost(hostId);
     }
 
     @Override
     public void deleteAllHosts() throws RemoteException {
-        getImplForUser().deleteAllHosts();
+        getImplForUser(UserHandle.getCallingUserId()).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(UserHandle.getCallingUserId()).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(UserHandle.getCallingUserId()).bindAppWidgetIdIfAllowed(
+                packageName, appWidgetId, provider, options);
     }
 
     @Override
     public boolean hasBindAppWidgetPermission(String packageName) throws RemoteException {
-        return getImplForUser().hasBindAppWidgetPermission(packageName);
+        return getImplForUser(UserHandle.getCallingUserId()).hasBindAppWidgetPermission(
+                packageName);
     }
 
     @Override
     public void setBindAppWidgetPermission(String packageName, boolean permission)
             throws RemoteException {
-        getImplForUser().setBindAppWidgetPermission(packageName, permission);
+        getImplForUser(UserHandle.getCallingUserId()).setBindAppWidgetPermission(
+                packageName, permission);
     }
 
     @Override
     public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection)
             throws RemoteException {
-        getImplForUser().bindRemoteViewsService(appWidgetId, intent, connection);
+        getImplForUser(UserHandle.getCallingUserId()).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(UserHandle.getCallingUserId()).startListening(host,
+                packageName, hostId, updatedViews);
     }
 
     public void onUserRemoved(int userId) {
@@ -247,8 +267,10 @@
         }
     }
 
-    private AppWidgetServiceImpl getImplForUser() {
-        final int userId = Binder.getOrigCallingUser();
+    public void onUserStopped(int userId) {
+    }
+
+    private AppWidgetServiceImpl getImplForUser(int userId) {
         AppWidgetServiceImpl service = mAppWidgetServices.get(userId);
         if (service == null) {
             Slog.e(TAG, "Unable to find AppWidgetServiceImpl for the current user");
@@ -265,27 +287,27 @@
 
     @Override
     public int[] getAppWidgetIds(ComponentName provider) throws RemoteException {
-        return getImplForUser().getAppWidgetIds(provider);
+        return getImplForUser(UserHandle.getCallingUserId()).getAppWidgetIds(provider);
     }
 
     @Override
     public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) throws RemoteException {
-        return getImplForUser().getAppWidgetInfo(appWidgetId);
+        return getImplForUser(UserHandle.getCallingUserId()).getAppWidgetInfo(appWidgetId);
     }
 
     @Override
     public RemoteViews getAppWidgetViews(int appWidgetId) throws RemoteException {
-        return getImplForUser().getAppWidgetViews(appWidgetId);
+        return getImplForUser(UserHandle.getCallingUserId()).getAppWidgetViews(appWidgetId);
     }
 
     @Override
     public void updateAppWidgetOptions(int appWidgetId, Bundle options) {
-        getImplForUser().updateAppWidgetOptions(appWidgetId, options);
+        getImplForUser(UserHandle.getCallingUserId()).updateAppWidgetOptions(appWidgetId, options);
     }
 
     @Override
     public Bundle getAppWidgetOptions(int appWidgetId) {
-        return getImplForUser().getAppWidgetOptions(appWidgetId);
+        return getImplForUser(UserHandle.getCallingUserId()).getAppWidgetOptions(appWidgetId);
     }
 
     static int[] getAppWidgetIds(Provider p) {
@@ -299,40 +321,43 @@
 
     @Override
     public List<AppWidgetProviderInfo> getInstalledProviders() throws RemoteException {
-        return getImplForUser().getInstalledProviders();
+        return getImplForUser(UserHandle.getCallingUserId()).getInstalledProviders();
     }
 
     @Override
     public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId)
             throws RemoteException {
-        getImplForUser().notifyAppWidgetViewDataChanged(appWidgetIds, viewId);
+        getImplForUser(UserHandle.getCallingUserId()).notifyAppWidgetViewDataChanged(
+                appWidgetIds, viewId);
     }
 
     @Override
     public void partiallyUpdateAppWidgetIds(int[] appWidgetIds, RemoteViews views)
             throws RemoteException {
-        getImplForUser().partiallyUpdateAppWidgetIds(appWidgetIds, views);
+        getImplForUser(UserHandle.getCallingUserId()).partiallyUpdateAppWidgetIds(
+                appWidgetIds, views);
     }
 
     @Override
     public void stopListening(int hostId) throws RemoteException {
-        getImplForUser().stopListening(hostId);
+        getImplForUser(UserHandle.getCallingUserId()).stopListening(hostId);
     }
 
     @Override
     public void unbindRemoteViewsService(int appWidgetId, Intent intent) throws RemoteException {
-        getImplForUser().unbindRemoteViewsService(appWidgetId, intent);
+        getImplForUser(UserHandle.getCallingUserId()).unbindRemoteViewsService(
+                appWidgetId, intent);
     }
 
     @Override
     public void updateAppWidgetIds(int[] appWidgetIds, RemoteViews views) throws RemoteException {
-        getImplForUser().updateAppWidgetIds(appWidgetIds, views);
+        getImplForUser(UserHandle.getCallingUserId()).updateAppWidgetIds(appWidgetIds, views);
     }
 
     @Override
     public void updateAppWidgetProvider(ComponentName provider, RemoteViews views)
             throws RemoteException {
-        getImplForUser().updateAppWidgetProvider(provider, views);
+        getImplForUser(UserHandle.getCallingUserId()).updateAppWidgetProvider(provider, views);
     }
 
     @Override
@@ -349,16 +374,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, -1);
+                if (userId >= 0) {
+                    getImplForUser(userId).sendInitialBroadcasts();
+                } else {
+                    Slog.w(TAG, "Not 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..499c15e 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;
@@ -188,11 +192,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) {
@@ -210,11 +215,19 @@
 
             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();
             }
@@ -225,6 +238,7 @@
         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 +270,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 +288,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 +317,8 @@
                 pw.print(info.updatePeriodMillis);
                 pw.print(" resizeMode=");
                 pw.print(info.resizeMode);
+                pw.print(info.widgetCategory);
+                pw.print(info.widgetFeatures);
                 pw.print(" autoAdvanceViewId=");
                 pw.print(info.autoAdvanceViewId);
                 pw.print(" initialLayout=#");
@@ -386,7 +410,7 @@
     }
 
     public int allocateAppWidgetId(String packageName, int hostId) {
-        int callingUid = enforceCallingUid(packageName);
+        int callingUid = enforceSystemOrCallingUid(packageName);
         synchronized (mAppWidgetIds) {
             ensureStateLoadedLocked();
             int appWidgetId = mNextAppWidgetId++;
@@ -479,7 +503,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,7 +511,7 @@
                     // 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));
                 }
             }
         }
@@ -506,7 +530,7 @@
         }
     }
 
-    private void bindAppWidgetIdImpl(int appWidgetId, ComponentName provider) {
+    private void bindAppWidgetIdImpl(int appWidgetId, ComponentName provider, Bundle options) {
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized (mAppWidgetIds) {
@@ -529,6 +553,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,14 +586,14 @@
         }
     }
 
-    public void bindAppWidgetId(int appWidgetId, ComponentName provider) {
+    public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options) {
         mContext.enforceCallingPermission(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);
         } catch (SecurityException se) {
@@ -566,14 +601,14 @@
                 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) {
@@ -645,7 +680,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 +771,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();
@@ -852,15 +887,18 @@
             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();
         }
     }
 
@@ -1006,7 +1044,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 {
@@ -1185,7 +1223,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 +1231,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));
         }
     }
 
@@ -1304,6 +1342,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 +1358,12 @@
             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);
+            info.widgetFeatures = sa.getInt(
+                    com.android.internal.R.styleable.AppWidgetProviderInfo_widgetFeatures,
+                    AppWidgetProviderInfo.WIDGET_FEATURES_NONE);
 
             sa.recycle();
         } catch (Exception e) {
@@ -1346,6 +1392,15 @@
         return pkgInfo.applicationInfo.uid;
     }
 
+    int enforceSystemOrCallingUid(String packageName) throws IllegalArgumentException {
+        int callingUid = Binder.getCallingUid();
+        int uid = Process.myUid();
+        if (UserHandle.getAppId(uid) == Process.SYSTEM_UID || uid == 0) {
+            return callingUid;
+        }
+        return enforceCallingUid(packageName);
+    }
+
     int enforceCallingUid(String packageName) throws IllegalArgumentException {
         int callingUid = Binder.getCallingUid();
         int packageUid;
@@ -1355,7 +1410,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 +1510,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 +1542,7 @@
         }
     }
 
+    @SuppressWarnings("unused")
     void readStateFromFileLocked(FileInputStream stream) {
         boolean success = false;
         try {
@@ -1494,11 +1562,12 @@
                         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,
+                                    UserHandle.getCallingUserId());
+                        } catch (RemoteException e) {
+                            String[] pkgs = mContext.getPackageManager()
                                     .currentToCanonicalPackageNames(new String[] { pkg });
                             pkg = pkgs[0];
                         }
@@ -1547,6 +1616,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 (minWidthString != null) {
+                            options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT,
+                                    Integer.parseInt(minHeightString, 16));
+                        }
+                        String maxWidthString = parser.getAttributeValue(null, "max_height");
+                        if (minWidthString != null) {
+                            options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH,
+                                    Integer.parseInt(maxWidthString, 16));
+                        }
+                        String maxHeightString = parser.getAttributeValue(null, "max_height");
+                        if (minWidthString != null) {
+                            options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT,
+                                    Integer.parseInt(maxHeightString, 16));
+                        }
+                        String categoryString = parser.getAttributeValue(null, "host_category");
+                        if (minWidthString != 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 +1710,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()) {
@@ -1642,7 +1739,8 @@
         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 +1750,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 +1761,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 +1786,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 +1803,7 @@
                 if (p == null) {
                     if (addProviderLocked(ri)) {
                         keep.add(ai.name);
+                        providersUpdated = true;
                     }
                 } else {
                     Provider parsed = parseProviderInfoXml(component, ri);
@@ -1729,6 +1838,7 @@
                             }
                             // Now that we've told the host, push out an update.
                             sendUpdateIntentLocked(p, appWidgetIds);
+                            providersUpdated = true;
                         }
                     }
                 }
@@ -1741,17 +1851,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 +1884,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 2167c49..5e2b425 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;
@@ -1662,8 +1664,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
             }
@@ -2720,9 +2721,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();
@@ -4401,6 +4406,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
@@ -4845,6 +4862,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 + "'"
@@ -4937,6 +4966,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) {
@@ -5001,6 +5035,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 {
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java
index ab9ae69..fe8529b 100644
--- a/services/java/com/android/server/BatteryService.java
+++ b/services/java/com/android/server/BatteryService.java
@@ -33,6 +33,7 @@
 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;
@@ -68,7 +69,7 @@
  * a degree Centigrade</p>
  * <p>&quot;technology&quot; - String, the type of battery installed, e.g. "Li-ion"</p>
  */
-class BatteryService extends Binder {
+public class BatteryService extends Binder {
     private static final String TAG = BatteryService.class.getSimpleName();
 
     private static final boolean LOCAL_LOGV = false;
@@ -93,6 +94,7 @@
 
     private boolean mAcOnline;
     private boolean mUsbOnline;
+    private boolean mWirelessOnline;
     private int mBatteryStatus;
     private int mBatteryHealth;
     private boolean mBatteryPresent;
@@ -114,6 +116,7 @@
 
     private int mLowBatteryWarningLevel;
     private int mLowBatteryCloseWarningLevel;
+    private int mShutdownBatteryTemperature;
 
     private int mPlugType;
     private int mLastPlugType = -1; // Extra state so we can detect first run
@@ -136,6 +139,8 @@
                 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");
 
@@ -148,12 +153,13 @@
         update();
     }
 
-    final boolean isPowered() {
+    public final boolean isPowered() {
         // assume we are powered if battery state is unknown so the "stay on while plugged in" option will work.
-        return (mAcOnline || mUsbOnline || mBatteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN);
+        return (mAcOnline || mUsbOnline || mWirelessOnline
+                || mBatteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN);
     }
 
-    final boolean isPowered(int plugTypeSet) {
+    public final boolean isPowered(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) {
@@ -169,10 +175,13 @@
         if (mUsbOnline) {
             plugTypeBit |= BatteryManager.BATTERY_PLUGGED_USB;
         }
+        if (mWirelessOnline) {
+            plugTypeBit |= BatteryManager.BATTERY_PLUGGED_WIRELESS;
+        }
         return (plugTypeSet & plugTypeBit) != 0;
     }
 
-    final int getPlugType() {
+    public final int getPlugType() {
         return mPlugType;
     }
 
@@ -195,10 +204,15 @@
     };
 
     // returns battery level as a percentage
-    final int getBatteryLevel() {
+    public final int getBatteryLevel() {
         return mBatteryLevel;
     }
 
+    // true if battery level is below the first warning threshold
+    public final boolean isBatteryLow() {
+        return mBatteryPresent && mBatteryLevel <= mLowBatteryWarningLevel;
+    }
+
     void systemReady() {
         // check our power situation now that it is safe to display the shutdown dialog.
         shutdownIfNoPower();
@@ -217,9 +231,11 @@
     }
 
     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()) {
+        // 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
+                && ActivityManagerNative.isSystemReady()) {
             Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
             intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -243,10 +259,12 @@
             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;
         }
-        
+
         // Let the battery stats keep track of the current level.
         try {
             mBatteryStats.setBatteryState(mBatteryStatus, mBatteryHealth,
@@ -255,7 +273,7 @@
         } catch (RemoteException e) {
             // Should never happen.
         }
-        
+
         shutdownIfNoPower();
         shutdownIfOverTemp();
 
@@ -333,21 +351,21 @@
             statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
             if (mPlugType != 0 && mLastPlugType == 0) {
                 statusIntent.setAction(Intent.ACTION_POWER_CONNECTED);
-                mContext.sendBroadcast(statusIntent);
+                mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
             }
             else if (mPlugType == 0 && mLastPlugType != 0) {
                 statusIntent.setAction(Intent.ACTION_POWER_DISCONNECTED);
-                mContext.sendBroadcast(statusIntent);
+                mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
             }
 
             if (sendBatteryLow) {
                 mSentLowBatteryBroadcast = true;
                 statusIntent.setAction(Intent.ACTION_BATTERY_LOW);
-                mContext.sendBroadcast(statusIntent);
+                mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
             } else if (mSentLowBatteryBroadcast && mLastBatteryLevel >= mLowBatteryCloseWarningLevel) {
                 mSentLowBatteryBroadcast = false;
                 statusIntent.setAction(Intent.ACTION_BATTERY_OKAY);
-                mContext.sendBroadcast(statusIntent);
+                mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
             }
 
             // Update the battery LED
@@ -398,10 +416,11 @@
                     " temperature: " + mBatteryTemperature +
                     " technology: " + mBatteryTechnology +
                     " AC powered:" + mAcOnline + " USB powered:" + mUsbOnline +
+                    " Wireless powered:" + mWirelessOnline +
                     " icon:" + icon  + " invalid charger:" + mInvalidCharger);
         }
 
-        ActivityManagerNative.broadcastStickyIntent(intent, null);
+        ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL);
     }
 
     private final void logBatteryStats() {
@@ -503,6 +522,7 @@
                 pw.println("Current Battery Service state:");
                 pw.println("  AC powered: " + mAcOnline);
                 pw.println("  USB powered: " + mUsbOnline);
+                pw.println("  Wireless powered: " + mWirelessOnline);
                 pw.println("  status: " + mBatteryStatus);
                 pw.println("  health: " + mBatteryHealth);
                 pw.println("  present: " + mBatteryPresent);
@@ -523,6 +543,8 @@
                         mAcOnline = Integer.parseInt(value) != 0;
                     } else if ("usb".equals(key)) {
                         mUsbOnline = Integer.parseInt(value) != 0;
+                    } else if ("wireless".equals(key)) {
+                        mWirelessOnline = Integer.parseInt(value) != 0;
                     } else if ("status".equals(key)) {
                         mBatteryStatus = Integer.parseInt(value);
                     } else if ("level".equals(key)) {
@@ -603,4 +625,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..e68686d
--- /dev/null
+++ b/services/java/com/android/server/BluetoothManagerService.java
@@ -0,0 +1,773 @@
+/*
+ * Copyright (C) 2012 Google Inc.
+ */
+
+package com.android.server;
+
+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.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.os.Binder;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Log;
+import java.util.List;
+import java.util.ArrayList;
+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_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;
+
+    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 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 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
+                        handleDisable(false);
+                } else {
+                    if (isBluetoothPersistedStateOn()) {
+                        // enable without persisting the setting
+                        handleEnable(false, false);
+                    }
+                }
+            }
+        }
+    };
+
+    BluetoothManagerService(Context context) {
+        mContext = context;
+        mBluetooth = null;
+        mBinding = false;
+        mUnbinding = false;
+        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);
+        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.");
+            enable();
+        } else 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.Secure.getInt(mContentResolver,
+                Settings.Secure.BLUETOOTH_ON, 0) ==1;
+    }
+
+    /**
+     *  Save the Bluetooth on/off state
+     *
+     */
+    private void persistBluetoothSetting(boolean setOn) {
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                               Settings.Secure.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");
+        mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME);
+        mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS);
+        if (mName == null || mAddress == null) {
+            if (DBG) Log.d(TAG, "Name or address not cached...");
+        }
+    }
+
+    /**
+     * 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));
+        }
+    }
+
+    public IBluetooth registerAdapter(IBluetoothManagerCallback callback){
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+                                                "Need BLUETOOTH permission");
+        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() {
+        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);
+        }
+        synchronized(mConnection) {
+            if (mBinding) return;
+            if (mConnection == null) mBinding = true;
+        }
+        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 (DBG) {
+            Log.d(TAG,"enableNoAutoConnect():  mBluetooth =" + mBluetooth +
+                    " mBinding = " + mBinding);
+        }
+        if (Binder.getCallingUid() != android.os.Process.NFC_UID) {
+            throw new SecurityException("no permission to enable Bluetooth quietly");
+        }
+        synchronized(mConnection) {
+            if (mBinding) {
+                Log.w(TAG,"enableNoAutoConnect(): binding in progress. Returning..");
+                return true;
+            }
+            if (mConnection == null) mBinding = true;
+        }
+
+        Message msg = mHandler.obtainMessage(MESSAGE_ENABLE);
+        msg.arg1=0; //No persist
+        msg.arg2=1; //Quiet mode
+        mHandler.sendMessage(msg);
+        return true;
+
+    }
+    public boolean enable() {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+                                                "Need BLUETOOTH ADMIN permission");
+        if (DBG) {
+            Log.d(TAG,"enable():  mBluetooth =" + mBluetooth +
+                    " mBinding = " + mBinding);
+        }
+
+        synchronized(mConnection) {
+            if (mBinding) {
+                Log.w(TAG,"enable(): binding in progress. Returning..");
+                return true;
+            }
+            if (mConnection == null) mBinding = true;
+        }
+
+        Message msg = mHandler.obtainMessage(MESSAGE_ENABLE);
+        msg.arg1=1; //persist
+        msg.arg2=0; //No Quiet Mode
+        mHandler.sendMessage(msg);
+        return true;
+    }
+
+    public boolean disable(boolean persist) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+                                                "Need BLUETOOTH ADMIN permissicacheNameAndAddresson");
+        if (DBG) {
+            Log.d(TAG,"disable(): mBluetooth = " + mBluetooth +
+                " mBinding = " + mBinding);
+        }
+
+        synchronized(mConnection) {
+             if (mBluetooth == null) return false;
+        }
+        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 (mConnection != null) {
+                if (!mConnection.isGetNameAddressOnly()) {
+                    //Unregister callback object
+                    try {
+                        mBluetooth.unregisterCallback(mBluetoothCallback);
+                    } catch (RemoteException re) {
+                        Log.e(TAG, "Unable to register BluetoothCallback",re);
+                    }
+                }
+                if (DBG) Log.d(TAG, "Sending unbind request.");
+                mBluetooth = null;
+                //Unbind
+                mContext.unbindService(mConnection);
+                mUnbinding = 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 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");
+        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");
+        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 final Handler mHandler = new Handler() {
+        @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) {
+                            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)) {
+                                mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
+                                Log.e(TAG, "fail to bind to: " + IBluetooth.class.getName());
+                            }
+                        }
+                        else {
+                            Message saveMsg= mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS);
+                            mHandler.sendMessage(saveMsg);
+                        }
+                    }
+                    break;
+                }
+                case MESSAGE_SAVE_NAME_AND_ADDRESS: {
+                    if (DBG) Log.d(TAG,"MESSAGE_SAVE_NAME_AND_ADDRESS");
+                    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);
+                                sendBluetoothServiceDownCallback();
+                                unbindAndFinish();
+                            } 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");
+                                    sendBluetoothServiceDownCallback();
+                                    unbindAndFinish();
+                                }
+                            }
+                        }
+                    }
+                    break;
+                }
+                case MESSAGE_ENABLE:
+                    if (DBG) {
+                        Log.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth);
+                    }
+
+                    handleEnable(msg.arg1 == 1, msg.arg2 ==1);
+                    break;
+
+                case MESSAGE_DISABLE:
+                    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);
+                            return;
+                        }
+
+                        //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
+                        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();
+
+                        //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);
+                        }
+                    }
+                    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);
+                    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) {
+                                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);
+                    }
+                    break;
+                }
+                case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED:
+                {
+                    if (DBG) Log.d(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED");
+                    sendBluetoothServiceDownCallback();
+
+                    // Send BT state broadcast to update
+                    // the BT icon correctly
+                    Message stateChangeMsg = mHandler.obtainMessage(
+                        MESSAGE_BLUETOOTH_STATE_CHANGE);
+                    stateChangeMsg.arg1 = BluetoothAdapter.STATE_ON;
+                    stateChangeMsg.arg2 =
+                        BluetoothAdapter.STATE_TURNING_OFF;
+                    mHandler.sendMessage(stateChangeMsg);
+                    synchronized(mConnection) {
+                        mBluetooth = null;
+                    }
+                    // Send a Bluetooth Restart message
+                    Message restartMsg = mHandler.obtainMessage(
+                        MESSAGE_RESTART_BLUETOOTH_SERVICE);
+                    mHandler.sendMessageDelayed(restartMsg,
+                        SERVICE_RESTART_TIME_MS);
+                    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 */
+                    handleEnable(false, mQuietEnable);
+                    break;
+                }
+
+                case MESSAGE_TIMEOUT_UNBIND:
+                {
+                    Log.e(TAG, "MESSAGE_TIMEOUT_UNBIND");
+                    synchronized(mConnection) {
+                        mUnbinding = false;
+                    }
+                    break;
+                }
+            }
+        }
+    };
+
+    private void handleEnable(boolean persist, boolean quietMode) {
+        if (persist) {
+            persistBluetoothSetting(true);
+        }
+
+        mQuietEnable = quietMode;
+
+        synchronized(mConnection) {
+            if (mBluetooth == null) {
+                //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)) {
+                    mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
+                    Log.e(TAG, "Fail to bind to: " + IBluetooth.class.getName());
+                }
+            } else {
+                //Check if name and address is loaded if not get it first.
+                if (!isNameAndAddressSet()) {
+                    try {
+                        if (DBG) Log.d(TAG,"Getting and storing Bluetooth name and address prior to enable.");
+                        storeNameAndAddress(mBluetooth.getName(),mBluetooth.getAddress());
+                    } catch (RemoteException e) {Log.e(TAG, "", e);};
+                }
+
+                //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) {
+        synchronized(mConnection) {
+            if (mBluetooth != null ) {
+                if (persist) {
+                    persistBluetoothSetting(false);
+                }
+                mConnection.setGetNameAddressOnly(false);
+                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);
+                }
+            }
+        }
+    }
+}
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..5c7a3ed 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -16,25 +16,38 @@
 
 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.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 +77,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 +93,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 +126,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 +148,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 +170,9 @@
      */
     private NetworkStateTracker mNetTrackers[];
 
+    /* Handles captive portal check on a network */
+    private CaptivePortalTracker mCaptivePortalTracker;
+
     /**
      * The link properties that define the current links
      */
@@ -186,95 +217,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 +347,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"))) {
@@ -358,8 +390,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 +505,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);
         }
@@ -548,8 +550,55 @@
 
         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 +611,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);
                 wimaxClassLoader =  new DexClassLoader(wimaxJarLocation,
-                        new ContextWrapper(mContext).getCacheDir().getAbsolutePath(),
+                        new ContextWrapper(context).getCacheDir().getAbsolutePath(),
                         wimaxLibLocation, ClassLoader.getSystemClassLoader());
 
                 try {
@@ -601,13 +650,13 @@
 
                 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 +672,7 @@
 
         return wimaxStateTracker;
     }
+
     /**
      * Sets the preferred network.
      * @param preference the new preference
@@ -630,7 +680,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() {
@@ -749,6 +800,9 @@
             info = new NetworkInfo(info);
             info.setDetailedState(DetailedState.BLOCKED, null, null);
         }
+        if (mLockdownTracker != null) {
+            info = mLockdownTracker.augmentNetworkInfo(info);
+        }
         return info;
     }
 
@@ -766,6 +820,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 +988,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 +1090,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 +1370,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 " +
@@ -1591,6 +1672,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
@@ -1610,6 +1695,7 @@
 
         Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
         intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
+        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
         if (info.isFailover()) {
             intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
             info.setFailover(false);
@@ -1719,7 +1805,7 @@
         }
     }
 
-    private void sendConnectedBroadcast(NetworkInfo info) {
+    public void sendConnectedBroadcast(NetworkInfo info) {
         sendGeneralBroadcast(info, CONNECTIVITY_ACTION_IMMEDIATE);
         sendGeneralBroadcast(info, CONNECTIVITY_ACTION);
     }
@@ -1734,8 +1820,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_TYPE, info.getType());
         if (info.isFailover()) {
             intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
             info.setFailover(false);
@@ -1759,6 +1850,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
@@ -1779,6 +1883,7 @@
 
         Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
         intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
+        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
         if (getActiveNetworkInfo() == null) {
             intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
         }
@@ -1829,7 +1934,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 +1960,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 +2021,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 +2042,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 +2054,99 @@
         }
         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 = CaptivePortalTracker.detect(mContext, info,
+                            ConnectivityService.this);
+                    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();
+        mCaptivePortalTracker = null;
+    }
+
+    /**
+     * 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.Secure.getInt(mContext.getContentResolver(),
+                                             Settings.Secure.DATA_ACTIVITY_TIMEOUT_MOBILE,
+                                             0);
+            // Canonicalize mobile network type
+            type = ConnectivityManager.TYPE_MOBILE;
+        } else if (ConnectivityManager.TYPE_WIFI == type) {
+            timeout = Settings.Secure.getInt(mContext.getContentResolver(),
+                                             Settings.Secure.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;
                 }
             }
         }
@@ -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 {
@@ -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..28a4310 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -55,6 +55,7 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.PrintWriterPrinter;
 import android.util.Printer;
@@ -176,6 +177,9 @@
         static final long DEF_PASSWORD_EXPIRATION_DATE = 0;
         long passwordExpirationDate = DEF_PASSWORD_EXPIRATION_DATE;
 
+        static final int DEF_KEYGUARD_WIDGET_DISABLED = 0; // none
+        int disableKeyguardWidgets = DEF_KEYGUARD_WIDGET_DISABLED;
+
         boolean encryptionRequested = false;
         boolean disableCamera = false;
 
@@ -285,6 +289,11 @@
                 out.attribute(null, "value", Boolean.toString(disableCamera));
                 out.endTag(null, "disable-camera");
             }
+            if (disableKeyguardWidgets != DEF_KEYGUARD_WIDGET_DISABLED) {
+                out.startTag(null, "disable-keyguard-widgets");
+                out.attribute(null, "value", Integer.toString(disableKeyguardWidgets));
+                out.endTag(null, "disable-keyguard-widgets");
+            }
         }
 
         void readFromXml(XmlPullParser parser)
@@ -570,10 +579,10 @@
             intent.putExtra("expiration", admin.passwordExpirationDate);
         }
         if (result != null) {
-            mContext.sendOrderedBroadcast(intent, null, result, mHandler,
-                    Activity.RESULT_OK, null, null);
+            mContext.sendOrderedBroadcastAsUser(intent, UserHandle.OWNER,
+                    null, result, mHandler, Activity.RESULT_OK, null, null);
         } else {
-            mContext.sendBroadcast(intent);
+            mContext.sendBroadcastAsUser(intent, UserHandle.OWNER);
         }
     }
 
@@ -712,7 +721,13 @@
     private void sendChangedNotification() {
         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 {
+            // TODO: This shouldn't be sent to all users, if DPM is per user.
+            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
     }
 
     private void loadSettingsLocked() {
@@ -1619,14 +1634,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;
 
             try {
-                getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
+                getIPowerManager().setMaximumScreenOffTimeoutFromDeviceAdmin((int)timeMs);
             } catch (RemoteException e) {
                 Slog.w(TAG, "Failure talking with power manager", e);
             }
@@ -1667,8 +1682,8 @@
             long ident = Binder.clearCallingIdentity();
             try {
                 // Power off the display
-                mIPowerManager.goToSleepWithReason(SystemClock.uptimeMillis(),
-                        WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN);
+                getIPowerManager().goToSleep(SystemClock.uptimeMillis(),
+                        PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN);
                 // Ensure the device is locked
                 getWindowManager().lockNow();
             } catch (RemoteException e) {
@@ -1734,7 +1749,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, UserHandle.OWNER,
+                    null, new BroadcastReceiver() {
                 @Override
                 public void onReceive(Context context, Intent intent) {
                     try {
@@ -2091,6 +2107,46 @@
         }
     }
 
+    /**
+     * Selectively disable keyguard widgets.
+     */
+    public void setKeyguardWidgetsDisabled(ComponentName who, int which) {
+        synchronized (this) {
+            if (who == null) {
+                throw new NullPointerException("ComponentName is null");
+            }
+            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
+                    DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_WIDGETS);
+            if ((ap.disableKeyguardWidgets & which) != which) {
+                ap.disableKeyguardWidgets |= which;
+                saveSettingsLocked();
+            }
+            syncDeviceCapabilitiesLocked();
+        }
+    }
+
+    /**
+     * Gets the disabled state for widgets in keyguard for the given admin,
+     * or the aggregate of all active admins if who is null.
+     */
+    public int getKeyguardWidgetsDisabled(ComponentName who) {
+        synchronized (this) {
+            if (who != null) {
+                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+                return (admin != null) ? admin.disableKeyguardWidgets : 0;
+            }
+
+            // Determine whether or not keyguard widgets are disabled for any active admins.
+            final int N = mAdminList.size();
+            int which = 0;
+            for (int i = 0; i < N; i++) {
+                ActiveAdmin admin = mAdminList.get(i);
+                which |= admin.disableKeyguardWidgets;
+            }
+            return which;
+        }
+    }
+
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
diff --git a/services/java/com/android/server/DeviceStorageMonitorService.java b/services/java/com/android/server/DeviceStorageMonitorService.java
index 0ed5189..c919595 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;
 
     /**
@@ -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();
@@ -276,7 +314,7 @@
                               Settings.Secure.SYS_STORAGE_THRESHOLD_PERCENTAGE,
                               DEFAULT_THRESHOLD_PERCENTAGE);
         if(localLOGV) Slog.v(TAG, "Threshold Percentage="+value);
-        value *= mTotalMemory;
+        value = (value*mTotalMemory)/100;
         long maxValue = Settings.Secure.getInt(
                 mContentResolver,
                 Settings.Secure.SYS_STORAGE_THRESHOLD_MAX_BYTES,
@@ -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();
@@ -375,8 +417,8 @@
         //cancel notification since memory has been freed
         mNotificationMgr.cancel(LOW_MEMORY_NOTIFICATION_ID);
 
-        mContext.removeStickyBroadcast(mStorageLowIntent);
-        mContext.sendBroadcast(mStorageOkIntent);
+        mContext.removeStickyBroadcastAsUser(mStorageLowIntent, UserHandle.ALL);
+        mContext.sendBroadcastAsUser(mStorageOkIntent, UserHandle.ALL);
     }
 
     /**
@@ -392,8 +434,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 +477,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..65c39f2 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -16,8 +16,9 @@
 
 package com.android.server;
 
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
+import static android.provider.Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK;
+import static android.provider.Settings.Secure.SCREENSAVER_ENABLED;
+
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -26,11 +27,16 @@
 import android.media.RingtoneManager;
 import android.net.Uri;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+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.service.dreams.IDreamManager;
 import android.util.Log;
 import android.util.Slog;
 
@@ -40,14 +46,19 @@
 /**
  * <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 DEFAULT_SCREENSAVER_ENABLED = 1;
+    private static final int DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK = 1;
+
+    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;
@@ -56,11 +67,8 @@
 
     private final Context mContext;
 
-    private PowerManagerService mPowerManager;
-
-    public DockObserver(Context context, PowerManagerService pm) {
+    public DockObserver(Context context) {
         mContext = context;
-        mPowerManager = pm;
         init();  // set initial status
 
         startObserving(DOCK_UEVENT_MATCH);
@@ -72,7 +80,7 @@
             Slog.v(TAG, "Dock UEVENT: " + event.toString());
         }
 
-        synchronized (this) {
+        synchronized (mLock) {
             try {
                 int newState = Integer.parseInt(event.get("SWITCH_STATE"));
                 if (newState != mDockState) {
@@ -86,10 +94,11 @@
                                 && 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);
+                            PowerManager pm =
+                                    (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
+                            pm.wakeUp(SystemClock.uptimeMillis());
                         }
-                        update();
+                        updateLocked();
                     }
                 }
             } catch (NumberFormatException e) {
@@ -98,102 +107,147 @@
         }
     }
 
-    private final void init() {
-        char[] buffer = new char[1024];
-
-        try {
-            FileReader file = new FileReader(DOCK_STATE_PATH);
-            int len = file.read(buffer, 0, 1024);
-            file.close();
-            mPreviousDockState = mDockState = Integer.valueOf((new String(buffer, 0, len)).trim());
-        } catch (FileNotFoundException e) {
-            Slog.w(TAG, "This kernel does not have dock station support");
-        } catch (Exception e) {
-            Slog.e(TAG, "" , e);
+    private void init() {
+        synchronized (mLock) {
+            try {
+                char[] buffer = new char[1024];
+                FileReader file = new FileReader(DOCK_STATE_PATH);
+                try {
+                    int len = file.read(buffer, 0, 1024);
+                    mDockState = Integer.valueOf((new String(buffer, 0, len)).trim());
+                    mPreviousDockState = mDockState;
+                } finally {
+                    file.close();
+                }
+            } catch (FileNotFoundException e) {
+                Slog.w(TAG, "This kernel does not have dock station support");
+            } catch (Exception e) {
+                Slog.e(TAG, "" , e);
+            }
         }
     }
 
     void systemReady() {
-        synchronized (this) {
+        synchronized (mLock) {
             // don't bother broadcasting undocked here
             if (mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
-                update();
+                updateLocked();
             }
             mSystemReady = true;
         }
     }
 
-    private final void update() {
-        mHandler.sendEmptyMessage(MSG_DOCK_STATE);
+    private void updateLocked() {
+        mHandler.sendEmptyMessage(MSG_DOCK_STATE_CHANGED);
     }
 
-    private final Handler mHandler = new Handler() {
+    private void handleDockStateChange() {
+        synchronized (mLock) {
+            Slog.i(TAG, "Dock state changed: " + mDockState);
+
+            final ContentResolver cr = mContext.getContentResolver();
+
+            if (Settings.Secure.getInt(cr,
+                    Settings.Secure.DEVICE_PROVISIONED, 0) == 0) {
+                Slog.i(TAG, "Device not provisioned, skipping dock broadcast");
+                return;
+            }
+
+            // Pack up the values and broadcast them to everyone
+            Intent intent = new Intent(Intent.ACTION_DOCK_EVENT);
+            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+            intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
+
+            // Check if this is Bluetooth Dock
+            // TODO(BT): Get Dock address.
+            // String address = null;
+            // if (address != null) {
+            //    intent.putExtra(BluetoothDevice.EXTRA_DEVICE,
+            //            BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address));
+            // }
+
+            // User feedback to confirm dock connection. Particularly
+            // useful for flaky contact pins...
+            if (Settings.System.getInt(cr,
+                    Settings.System.DOCK_SOUNDS_ENABLED, 1) == 1) {
+                String whichSound = null;
+                if (mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
+                    if ((mPreviousDockState == Intent.EXTRA_DOCK_STATE_DESK) ||
+                        (mPreviousDockState == Intent.EXTRA_DOCK_STATE_LE_DESK) ||
+                        (mPreviousDockState == Intent.EXTRA_DOCK_STATE_HE_DESK)) {
+                        whichSound = Settings.System.DESK_UNDOCK_SOUND;
+                    } else if (mPreviousDockState == Intent.EXTRA_DOCK_STATE_CAR) {
+                        whichSound = Settings.System.CAR_UNDOCK_SOUND;
+                    }
+                } else {
+                    if ((mDockState == Intent.EXTRA_DOCK_STATE_DESK) ||
+                        (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK) ||
+                        (mDockState == Intent.EXTRA_DOCK_STATE_HE_DESK)) {
+                        whichSound = Settings.System.DESK_DOCK_SOUND;
+                    } else if (mDockState == Intent.EXTRA_DOCK_STATE_CAR) {
+                        whichSound = Settings.System.CAR_DOCK_SOUND;
+                    }
+                }
+
+                if (whichSound != null) {
+                    final String soundPath = Settings.System.getString(cr, whichSound);
+                    if (soundPath != null) {
+                        final Uri soundUri = Uri.parse("file://" + soundPath);
+                        if (soundUri != null) {
+                            final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
+                            if (sfx != null) {
+                                sfx.setStreamType(AudioManager.STREAM_SYSTEM);
+                                sfx.play();
+                            }
+                        }
+                    }
+                }
+            }
+
+            IDreamManager mgr = IDreamManager.Stub.asInterface(ServiceManager.getService("dreams"));
+            if (mgr != null) {
+                // dreams feature enabled
+                boolean undocked = mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED;
+                if (undocked) {
+                    try {
+                        if (mgr.isDreaming()) {
+                            mgr.awaken();
+                        }
+                    } catch (RemoteException e) {
+                        Slog.w(TAG, "Unable to awaken!", e);
+                    }
+                } else {
+                    if (isScreenSaverEnabled(mContext) && isScreenSaverActivatedOnDock(mContext)) {
+                        try {
+                            mgr.dream();
+                        } catch (RemoteException e) {
+                            Slog.w(TAG, "Unable to dream!", e);
+                        }
+                    }
+                }
+            } else {
+                // dreams feature not enabled, send legacy intent
+                mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+            }
+        }
+    }
+
+    private static boolean isScreenSaverEnabled(Context context) {
+        return Settings.Secure.getInt(context.getContentResolver(),
+                SCREENSAVER_ENABLED, DEFAULT_SCREENSAVER_ENABLED) != 0;
+    }
+
+    private static boolean isScreenSaverActivatedOnDock(Context context) {
+        return Settings.Secure.getInt(context.getContentResolver(),
+                SCREENSAVER_ACTIVATE_ON_DOCK, DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK) != 0;
+    }
+
+    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..0b12410 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;
@@ -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);
                 }
             }
         };
diff --git a/services/java/com/android/server/EventLogTags.logtags b/services/java/com/android/server/EventLogTags.logtags
index 41f7335..840e006 100644
--- a/services/java/com/android/server/EventLogTags.logtags
+++ b/services/java/com/android/server/EventLogTags.logtags
@@ -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..c685473 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;
@@ -74,6 +74,7 @@
 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;
@@ -2024,7 +2025,7 @@
 
     @Override
     public boolean handleMessage(Message msg) {
-        HandlerCaller.SomeArgs args;
+        SomeArgs args;
         switch (msg.what) {
             case MSG_SHOW_IM_PICKER:
                 showInputMethodMenu();
@@ -2035,8 +2036,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 +2055,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 +2109,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 +2120,7 @@
                             (EditorInfo)args.arg3);
                 } catch (RemoteException e) {
                 }
+                args.recycle();
                 return true;
 
             // ---------------------------------------------------------
@@ -2124,13 +2133,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 {
@@ -3569,7 +3579,7 @@
         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) {
             if (methodMap == null) {
@@ -3585,18 +3595,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 +3620,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;
             }
         }
 
diff --git a/services/java/com/android/server/IntentResolver.java b/services/java/com/android/server/IntentResolver.java
index f7e841e..d4769e8 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;
@@ -65,11 +66,17 @@
             register_intent_filter(f, f.actionsIterator(),
                     mTypedActionToFilter, "      TypedAction: ");
         }
+
+        mOldResolver.addFilter(f);
+        verifyDataStructures(f);
     }
 
     public void removeFilter(F f) {
         removeFilterInternal(f);
         mFilters.remove(f);
+
+        mOldResolver.removeFilter(f);
+        verifyDataStructures(f);
     }
 
     void removeFilterInternal(F f) {
@@ -93,18 +100,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 +208,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 +238,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 +314,14 @@
         }
         sortResults(finalList);
 
+        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 +355,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 +372,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 +414,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 +445,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 +467,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 +483,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 +526,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 +606,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 +729,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 +745,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..197f6ab 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -16,27 +16,22 @@
 
 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.PackageInfo;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
-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 +40,8 @@
 import android.location.Location;
 import android.location.LocationManager;
 import android.location.LocationProvider;
+import android.location.LocationRequest;
 import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
@@ -57,17 +51,22 @@
 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.provider.Settings.NameValueTable;
 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,12 +75,9 @@
 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;
@@ -91,154 +87,264 @@
 /**
  * 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;
+            android.Manifest.permission.ACCESS_FINE_LOCATION;
     private static final String ACCESS_COARSE_LOCATION =
-        android.Manifest.permission.ACCESS_COARSE_LOCATION;
+            android.Manifest.permission.ACCESS_COARSE_LOCATION;
     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>();
 
-    /**
-     * Object used internally for synchronization
-     */
-    private final Object mLock = new Object();
+    // real providers, saved here when mocked out
+    private final HashMap<String, LocationProviderInterface> mRealProviders =
+            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 provider
+    private final HashMap<String, LocationProviderInterface> mProvidersByName =
+            new HashMap<String, LocationProviderInterface>();
 
-    /**
-     * Temporary filled in when computing min time for a provider.  Access is
-     * protected by global lock mLock.
-     */
-    private final WorkSource mTmpWorkSource = new WorkSource();
+    // mapping from provider name to all its UpdateRecords
+    private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
+            new HashMap<String, ArrayList<UpdateRecord>>();
 
-    // 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>();
+    // mapping from provider name to last known location
+    private final HashMap<String, Location> mLastLocation = new HashMap<String, Location>();
 
-    // Last known location for each provider
-    private HashMap<String,Location> mLastKnownLocation =
-        new HashMap<String,Location>();
+    // all providers that operate over proxy, for authorizing incoming location
+    private final ArrayList<LocationProviderProxy> mProxyProviders =
+            new ArrayList<LocationProviderProxy>();
 
-    private int mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
+    public LocationManagerService(Context context) {
+        super();
+        mContext = context;
 
-    // for prefix blacklist
-    private String[] mWhitelist = new String[0];
-    private String[] mBlacklist = new String[0];
+        if (D) Log.d(TAG, "Constructed");
 
-    // for Settings change notification
-    private ContentQueryMap mSettings;
+        // 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();
+               }
+            }
+        });
+        mPackageMonitor.register(mContext, Looper.myLooper(), true);
+
+        updateProvidersLocked();
+    }
+
+    private void loadProvidersLocked() {
+        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);
+        }
+
+        // create a passive location provider, which is always enabled
+        PassiveProvider passiveProvider = new PassiveProvider(this);
+        addProviderLocked(passiveProvider);
+        mEnabledProviders.add(passiveProvider.getName());
+        mPassiveProvider = passiveProvider;
+
+        /*
+        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[] pkgs1 = resources.getStringArray(
+                com.android.internal.R.array.config_locationProviderPackageNames);
+        String[] pkgs2 = resources.getStringArray(
+                com.android.internal.R.array.config_overlay_locationProviderPackageNames);
+        if (D) Log.d(TAG, "built-in location providers: " + Arrays.toString(pkgs1));
+        if (D) Log.d(TAG, "overlay location providers: " + Arrays.toString(pkgs2));
+        if (pkgs1 != null) providerPackageNames.addAll(Arrays.asList(pkgs1));
+        if (pkgs2 != null) providerPackageNames.addAll(Arrays.asList(pkgs2));
+
+        // bind to network provider
+        LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
+                mContext,
+                LocationManager.NETWORK_PROVIDER,
+                NETWORK_LOCATION_SERVICE_ACTION,
+                providerPackageNames, mLocationHandler);
+        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);
+        if (fusedLocationProvider != null) {
+            addProviderLocked(fusedLocationProvider);
+            mProxyProviders.add(fusedLocationProvider);
+            mEnabledProviders.add(fusedLocationProvider.getName());
+        } 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);
+        if (mGeocodeProvider == null) {
+            Slog.e(TAG,  "no geocoder provider found");
+        }
+    }
 
     /**
      * 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 String mPermission;  // best permission that receiver has
+
         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;
+            }
+            mPermission = checkPermission();
+            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 +356,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 +386,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 +393,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 +409,7 @@
                         // synchronize to ensure incrementPendingBroadcastsLocked()
                         // is called before decrementPendingBroadcasts()
                         mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
-                                mRequiredPermissions);
+                                mPermission);
                         // call this after broadcasting so we do not increment
                         // if we throw an exeption.
                         incrementPendingBroadcastsLocked();
@@ -330,11 +428,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 +443,7 @@
                         // synchronize to ensure incrementPendingBroadcastsLocked()
                         // is called before decrementPendingBroadcasts()
                         mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
-                                mRequiredPermissions);
+                                mPermission);
                         // call this after broadcasting so we do not increment
                         // if we throw an exeption.
                         incrementPendingBroadcastsLocked();
@@ -370,11 +466,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 +481,7 @@
                         // synchronize to ensure incrementPendingBroadcastsLocked()
                         // is called before decrementPendingBroadcasts()
                         mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
-                                mRequiredPermissions);
+                                mPermission);
                         // call this after broadcasting so we do not increment
                         // if we throw an exeption.
                         incrementPendingBroadcastsLocked();
@@ -401,9 +495,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 +508,7 @@
             }
         }
 
+        @Override
         public void onSendFinished(PendingIntent pendingIntent, Intent intent,
                 int resultCode, String resultData, Bundle resultExtras) {
             synchronized (this) {
@@ -437,6 +531,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,198 +549,17 @@
         }
     }
 
-    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 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)) {
@@ -660,317 +574,141 @@
         return Settings.Secure.isLocationProviderEnabled(resolver, provider);
     }
 
-    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");
-            }
+    /**
+     * Throw SecurityException if caller has neither COARSE or FINE.
+     * Otherwise, return the best permission.
+     */
+    private String checkPermission() {
+        if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) ==
+                PackageManager.PERMISSION_GRANTED) {
             return ACCESS_FINE_LOCATION;
+        } else if (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION) ==
+                PackageManager.PERMISSION_GRANTED) {
+            return ACCESS_COARSE_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");
+        throw new SecurityException("Location requires either ACCESS_COARSE_LOCATION or" +
+                " ACCESS_FINE_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;
+    /**
+     * Throw SecurityException if caller lacks permission to use Geofences.
+     */
+    private void checkGeofencePermission() {
+        if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) !=
+                PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
         }
-        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;
     }
 
+    /**
+     * Returns all providers by name, including passive, but excluding
+     * fused.
+     */
+    @Override
     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;
-        }
-    }
+        checkPermission();
 
-    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;
-        }
-    }
-
-    private List<String> _getProvidersLocked(Criteria criteria, boolean enabledOnly) {
-        if (LOCAL_LOGV) {
-            Slog.v(TAG, "getProviders");
-        }
-        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;
-                }
-                if (criteria != null && !p.meetsCriteria(criteria)) {
+        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;
-        }
-    }
+    @Override
+    public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
+        checkPermission();
 
-    /**
-     * 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;
+        ArrayList<String> out;
         synchronized (mLock) {
-            providers = new ArrayList<LocationProviderInterface>(providerNames.size());
-            for (String name : providerNames) {
-                providers.add(mProvidersByName.get(name));
+            out = new ArrayList<String>(mProviders.size());
+            for (LocationProviderInterface provider : mProviders) {
+                String name = provider.getName();
+                if (LocationManager.FUSED_PROVIDER.equals(name)) {
+                    continue;
+                }
+                if (enabledOnly && !isAllowedBySettingsLocked(name)) {
+                    continue;
+                }
+                if (criteria != null && !LocationProvider.propertiesMeetCriteria(
+                        name, provider.getProperties(), criteria)) {
+                    continue;
+                }
+                out.add(name);
             }
         }
 
-        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 LoactionProvider (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;
+        checkPermission();
+
+        List<String> providers = getProviders(criteria, enabledOnly);
+        if (providers.size() < 1) {
+            result = pickBest(providers);
+            if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
+            return result;
+        }
+        providers = getProviders(null, enabledOnly);
+        if (providers.size() >= 1) {
+            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.NETWORK_PROVIDER)) {
+            return LocationManager.NETWORK_PROVIDER;
+        } else if (providers.contains(LocationManager.GPS_PROVIDER)) {
+            return LocationManager.GPS_PROVIDER;
+        } else {
+            return providers.get(0);
+        }
+    }
+
+    @Override
     public boolean providerMeetsCriteria(String provider, Criteria criteria) {
+        checkPermission();
+
         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() {
@@ -989,7 +727,8 @@
             }
         }
         if (changesMade) {
-            mContext.sendBroadcast(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION));
+            mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
+                    UserHandle.ALL);
         }
     }
 
@@ -997,16 +736,14 @@
         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)) {
@@ -1020,67 +757,74 @@
         }
 
         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) {
+                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) {
+                    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 +840,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,251 +891,257 @@
         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;
-                }
-           }
+    private String checkPermissionAndRequest(LocationRequest request) {
+        String perm = checkPermission();
+
+        if (ACCESS_COARSE_LOCATION.equals(perm)) {
+             switch (request.getQuality()) {
+                 case LocationRequest.ACCURACY_FINE:
+                     request.setQuality(LocationRequest.ACCURACY_BLOCK);
+                     break;
+                 case LocationRequest.POWER_HIGH:
+                     request.setQuality(LocationRequest.POWER_LOW);
+                     break;
+             }
+             // throttle
+             if (request.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
+                 request.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
+             }
+             if (request.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
+                 request.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
+             }
         }
-        for (ProximityAlert alert : mProximityAlerts.values()) {
-            if (alert.mUid == uid) {
-                return true;
-            }
+        // make getFastestInterval() the minimum of interval and fastest interval
+        if (request.getFastestInterval() > request.getInterval()) {
+            request.setFastestInterval(request.getInterval());
         }
-        return false;
+        return perm;
     }
 
-    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);
+        checkPermissionAndRequest(request);
 
-        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(request, 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) name = LocationManager.FUSED_PROVIDER;
+        LocationProviderInterface provider = mProvidersByName.get(name);
+        if (provider == null) {
+            throw new IllegalArgumentException("provider doesn't exisit: " + provider);
+        }
+
+        Log.i(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);
+        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);
+        checkPermission();
+        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);
+        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)) {
+                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;
+        String perm = checkPermissionAndRequest(request);
+        checkPackageName(packageName);
+
+        if (mBlacklist.isBlacklisted(packageName)) {
+            if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
+                    packageName);
+            return null;
+        }
+
+        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)) return null;
+
+            Location location = mLastLocation.get(name);
+            if (ACCESS_FINE_LOCATION.equals(perm)) {
+                return location;
+            } else {
+                return mLocationFudger.getOrCreate(location);
+            }
+        }
+    }
+
+    @Override
+    public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
+            String packageName) {
+        if (request == null) request = DEFAULT_LOCATION_REQUEST;
+        checkGeofencePermission();
+        checkPermissionAndRequest(request);
+        checkPendingIntent(intent);
+        checkPackageName(packageName);
+
+        if (D) Log.d(TAG, "requestGeofence: " + request + " " + geofence + " " + intent);
+
+        // geo-fence manager uses the public location API, need to clear identity
+        int uid = Binder.getCallingUid();
         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;
-                    }
-                }
-            }
-
-            // 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);
-                        }
-                    }
-                    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);
-                    }
-                }
-            }
+            mGeofenceManager.addFence(request, geofence, intent, uid, packageName);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
     }
 
+    @Override
+    public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
+        checkGeofencePermission();
+        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;
@@ -1406,6 +1160,7 @@
         return true;
     }
 
+    @Override
     public void removeGpsStatusListener(IGpsStatusListener listener) {
         synchronized (mLock) {
             try {
@@ -1416,14 +1171,14 @@
         }
     }
 
+    @Override
     public boolean sendExtraCommand(String provider, String command, Bundle extras) {
         if (provider == null) {
             // throw NullPointerException to remain compatible with previous implementation
             throw new NullPointerException();
         }
 
-        // first check for permission to the provider
-        checkPermissionsSafe(provider, null);
+        checkPermission();
         // and check for ACCESS_LOCATION_EXTRA_COMMANDS
         if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
                 != PackageManager.PERMISSION_GRANTED)) {
@@ -1432,423 +1187,112 @@
 
         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;
-        }
-    }
+    @Override
+    public ProviderProperties getProviderProperties(String provider) {
+        checkPermission();
 
-    private Bundle _getProviderInfoLocked(String provider) {
-        LocationProviderInterface p = mProvidersByName.get(provider);
-        if (p == null) {
-            return null;
+        LocationProviderInterface p;
+        synchronized (mLock) {
+            p = mProvidersByName.get(provider);
         }
 
-        checkPermissionsSafe(provider, null);
-
-        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());
-
-        return b;
+        if (p == null) return null;
+        return p.getProperties();
     }
 
+    @Override
     public boolean isProviderEnabled(String provider) {
-        try {
-            synchronized (mLock) {
-                return _isProviderEnabledLocked(provider);
-            }
-        } catch (SecurityException se) {
-            throw se;
-        } catch (Exception e) {
-            Slog.e(TAG, "isProviderEnabled got exception:", e);
+        checkPermission();
+        if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
+
+        synchronized (mLock) {
+            LocationProviderInterface p = mProvidersByName.get(provider);
+            if (p == null) return false;
+
+            return isAllowedBySettingsLocked(provider);
+        }
+    }
+
+    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) {
         // Always broadcast the first update
@@ -1857,13 +1301,14 @@
         }
 
         // 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.getElapsedRealtimeNano() - lastLoc.getElapsedRealtimeNano()) / 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;
@@ -1874,24 +1319,26 @@
     }
 
     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;
-        }
+        if (records == null || records.size() == 0) return;
 
         LocationProviderInterface p = mProvidersByName.get(provider);
-        if (p == null) {
-            return;
-        }
+        if (p == null) return;
 
-        // Update last known location for provider
-        Location lastLocation = mLastKnownLocation.get(provider);
+        // Add the coarse location as an extra
+        Location coarse = mLocationFudger.getOrCreate(location);
+
+        // Update last known locations
+        Location lastLocation = mLastLocation.get(provider);
         if (lastLocation == null) {
-            mLastKnownLocation.put(provider, new Location(location));
-        } else {
-            lastLocation.set(location);
+            lastLocation = new Location(provider);
+            mLastLocation.put(provider, lastLocation);
         }
+        lastLocation.set(location);
 
         // Fetch latest status update time
         long newStatusUpdateTime = p.getStatusUpdateTime();
@@ -1901,18 +1348,25 @@
         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)) {
+            if (mBlacklist.isBlacklisted(receiver.mPackageName)) {
+                if (D) Log.d(TAG, "skipping loc update for blacklisted app: " +
+                        receiver.mPackageName);
                 continue;
             }
 
+            if (ACCESS_FINE_LOCATION.equals(receiver.mPermission)) {
+                location = lastLocation;  // use fine location
+            } else {
+                location = coarse;  // use coarse location
+            }
+
             Location lastLoc = r.mLastFixBroadcast;
             if ((lastLoc == null) || shouldBroadcastSafe(location, lastLoc, r)) {
                 if (lastLoc == null) {
@@ -1938,8 +1392,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 +1409,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)) {
+                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 +1514,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 +1530,7 @@
     }
 
 
+    @Override
     public String getFromLocationName(String locationName,
             double lowerLeftLatitude, double lowerLeftLongitude,
             double upperRightLatitude, double upperRightLongitude, int maxResults,
@@ -2205,12 +1556,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 +1569,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 +1599,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 +1628,7 @@
         }
     }
 
+    @Override
     public void clearTestProviderLocation(String provider) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2292,6 +1640,7 @@
         }
     }
 
+    @Override
     public void setTestProviderEnabled(String provider, boolean enabled) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2314,6 +1663,7 @@
         }
     }
 
+    @Override
     public void clearTestProviderEnabled(String provider) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2329,6 +1679,7 @@
         }
     }
 
+    @Override
     public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2340,6 +1691,7 @@
         }
     }
 
+    @Override
     public void clearTestProviderStatus(String provider) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2351,119 +1703,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 +1718,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..32ab154 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,18 @@
 import android.util.Slog;
 import android.util.Xml;
 
-import org.xmlpull.v1.XmlPullParser;
+import com.android.internal.app.IMediaContainerService;
+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 +86,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 +100,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 +172,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.
@@ -303,6 +318,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 +454,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 +502,119 @@
         }
     }
 
-    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 mBootReceiver = 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;
+            Slog.d(TAG, "BOOT_COMPLETED for " + user);
 
-                /*
-                 * 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;
-                }
-                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]);
-                                }
-                            }
+            // Broadcast mounted volumes to newly booted user. This kicks off
+            // media scanner when a user becomes active.
+            synchronized (mVolumesLock) {
+                for (StorageVolume volume : mVolumes) {
+                    final UserHandle owner = volume.getOwner();
+                    final boolean ownerMatch = owner == null
+                            || owner.getIdentifier() == user.getIdentifier();
 
-                            for (int i = 0; i < count; i++) {
-                                String path = paths[i];
-                                String state = states[i];
+                    final String state = mVolumeStates.get(volume.getPath());
 
-                                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);
-                        }
+                    if (ownerMatch && (Environment.MEDIA_MOUNTED.equals(state)
+                            || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state))) {
+                        sendStorageIntent(Intent.ACTION_MEDIA_MOUNTED, volume, user);
                     }
-                }.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);
+                }
             }
         }
     };
+
+    private final BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+            if (userId == -1) return;
+            final UserHandle user = new UserHandle(userId);
+
+            final String action = intent.getAction();
+            if (Intent.ACTION_USER_ADDED.equals(action)) {
+                synchronized (mVolumesLock) {
+                    createEmulatedVolumeForUserLocked(user);
+                }
+
+            } 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);
+                        }
+                    }
+                    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 +645,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 +660,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 +694,6 @@
     }
 
     /**
-     *
      * Callback from NativeDaemonConnector
      */
     public void onDaemonConnected() {
@@ -661,6 +717,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 +739,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 +813,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 +843,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 +873,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 +897,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 +920,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 +935,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 +966,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 +974,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 +985,7 @@
              * Send broadcast intent (if required for the failure)
              */
             if (action != null) {
-                sendStorageIntent(action, path);
+                sendStorageIntent(action, volume, UserHandle.ALL);
             }
         }
 
@@ -1011,14 +1093,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 +1126,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 +1149,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 +1171,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 +1196,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()) {
+                            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 +1227,105 @@
         } 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 boot completion
+        mContext.registerReceiverAsUser(mBootReceiver, UserHandle.ALL,
+                new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, mHandler);
+
+        // 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 +1345,11 @@
         }
     }
 
+    public void systemReady() {
+        mSystemReady = true;
+        mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
+    }
+
     /**
      * Exposed API calls below here
      */
@@ -1232,7 +1382,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 +1463,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 +1501,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 +1529,9 @@
         }
     }
 
+    @Override
     public boolean isExternalStorageEmulated() {
-        return mEmulateExternalStorage;
+        return mEmulatedTemplate != null;
     }
 
     public int mountVolume(String path) {
@@ -1437,7 +1597,9 @@
     }
 
     private void warnOnNotMounted() {
-        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+        final StorageVolume primary = getPrimaryPhysicalVolume();
+        if (primary != null
+                && Environment.MEDIA_MOUNTED.equals(getVolumeState(primary.getPath()))) {
             Slog.w(TAG, "getSecureContainerList() called when storage not mounted");
         }
     }
@@ -1713,7 +1875,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 = " +
@@ -1935,14 +2097,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()]);
         }
     }
 
@@ -2458,7 +2629,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/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index f6d3b608..3caba1f 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,11 +50,13 @@
 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.service.dreams.IDreamManager;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
+import android.util.AtomicFile;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
@@ -61,7 +65,6 @@
 import android.view.accessibility.AccessibilityManager;
 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();
@@ -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,17 +866,11 @@
 
     // 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) {
@@ -865,7 +881,7 @@
     // 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 +889,9 @@
         checkCallerIsSystemOrSameApp(pkg);
         final boolean isSystemNotification = ("android".equals(pkg));
 
+        userId = ActivityManager.handleIncomingUser(callingPid,
+                callingUid, userId, false, true, "enqueueNotification", pkg);
+
         // Limit the number of notifications that any given package except the android
         // package can enqueue.  Prevents DOS attacks and deals with leaks.
         if (!isSystemNotification) {
@@ -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 {
@@ -1014,6 +1033,7 @@
             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)
                     && mSystemReady) {
 
                 final AudioManager audioManager = (AudioManager) mContext
@@ -1173,12 +1193,12 @@
      * and none of the {@code mustNotHaveFlags}.
      */
     private void cancelNotification(String pkg, String tag, int id, int mustHaveFlags,
-            int mustNotHaveFlags, boolean sendDelete) {
+            int mustNotHaveFlags, boolean sendDelete, int userId) {
         EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL, pkg, id, tag,
                 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);
 
@@ -1202,7 +1222,7 @@
      * {@code mustHaveFlags}.
      */
     boolean cancelAllNotificationsInt(String pkg, int mustHaveFlags,
-            int mustNotHaveFlags, boolean doit) {
+            int mustNotHaveFlags, boolean doit, int userId) {
         EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL_ALL, pkg, mustHaveFlags,
                 mustNotHaveFlags);
 
@@ -1211,6 +1231,9 @@
             boolean canceledSomething = false;
             for (int i = N-1; i >= 0; --i) {
                 NotificationRecord r = mNotificationList.get(i);
+                if (userId != UserHandle.USER_ALL && r.userId != userId) {
+                    continue;
+                }
                 if ((r.notification.flags & mustHaveFlags) != mustHaveFlags) {
                     continue;
                 }
@@ -1234,30 +1257,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, false, true, "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, true, "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 +1288,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 (r.userId != userId) {
+                    continue;
+                }
+
                 if ((r.notification.flags & (Notification.FLAG_ONGOING_EVENT
                                 | Notification.FLAG_NO_CLEAR)) == 0) {
                     mNotificationList.remove(i);
@@ -1330,12 +1357,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 (r.userId != userId || r.id != id) {
+                continue;
+            }
             if (tag == null) {
                 if (r.tag != null) {
                     continue;
@@ -1345,7 +1375,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..2a7a2eb 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;
@@ -448,7 +449,7 @@
         } else {
             intent.putExtra(NsdManager.EXTRA_NSD_STATE, NsdManager.NSD_STATE_DISABLED);
         }
-        mContext.sendStickyBroadcast(intent);
+        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     private boolean isNsdEnabled() {
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/ServiceWatcher.java b/services/java/com/android/server/ServiceWatcher.java
new file mode 100644
index 0000000..0dfaa05
--- /dev/null
+++ b/services/java/com/android/server/ServiceWatcher.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.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;
+    private static final String EXTRA_VERSION = "version";
+
+    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;  // current best version
+
+    public ServiceWatcher(Context context, String logTag, String action,
+            List<String> initialPackageNames, Runnable newServiceWork, Handler handler) {
+        mContext = context;
+        mTag = logTag;
+        mAction = action;
+        mPm = mContext.getPackageManager();
+        mNewServiceWork = newServiceWork;
+        mHandler = handler;
+
+        mSignatureSets = new ArrayList<HashSet<Signature>>();
+        for (int i=0; i < initialPackageNames.size(); i++) {
+            String pkg = initialPackageNames.get(i);
+            HashSet<Signature> set = new HashSet<Signature>();
+            try {
+                Signature[] sigs =
+                        mPm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES).signatures;
+                set.addAll(Arrays.asList(sigs));
+                mSignatureSets.add(set);
+            } catch (NameNotFoundException e) {
+                Log.w(logTag, pkg + " not found");
+            }
+        }
+
+    }
+
+    public boolean start() {
+        if (!bindBestPackage(null)) return false;
+
+        mPackageMonitor.register(mContext, null, 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 bindBestPackage(String justCheckThisPackage) {
+        Intent intent = new Intent(mAction);
+        if (justCheckThisPackage != null) {
+            intent.setPackage(justCheckThisPackage);
+        }
+        List<ResolveInfo> rInfos = mPm.queryIntentServices(new Intent(mAction),
+                PackageManager.GET_META_DATA);
+        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_VERSION, 0);
+            }
+            if (version > mVersion) {
+                bestVersion = version;
+                bestPackage = packageName;
+            }
+        }
+
+        if (D) Log.d(mTag, String.format("bindBestPackage %s found %d, %s",
+                (justCheckThisPackage == null ? "" : "(" + justCheckThisPackage + ") "),
+                rInfos.size(),
+                (bestPackage == null ? "no new best package" : "new best packge: " + bestPackage)));
+
+        if (bestPackage != null) {
+            bindToPackage(bestPackage, bestVersion);
+            return true;
+        }
+        return false;
+    }
+
+    private void unbind() {
+        String pkg;
+        synchronized (mLock) {
+            pkg = mPackageName;
+            mPackageName = null;
+            mVersion = Integer.MIN_VALUE;
+        }
+        if (pkg != null) {
+            if (D) Log.d(mTag, "unbinding " + pkg);
+            mContext.unbindService(this);
+        }
+    }
+
+    private void bindToPackage(String packageName, int version) {
+        unbind();
+        Intent intent = new Intent(mAction);
+        intent.setPackage(packageName);
+        synchronized (mLock) {
+            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);
+    }
+
+    private boolean isSignatureMatch(Signature[] signatures) {
+        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 : mSignatureSets) {
+            if (referenceSet.equals(inputSet)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private final PackageMonitor mPackageMonitor = new PackageMonitor() {
+        /**
+         * Called when package has been reinstalled
+         */
+        @Override
+        public void onPackageUpdateFinished(String packageName, int uid) {
+            if (packageName.equals(mPackageName)) {
+                // package updated, make sure to rebind
+                unbind();
+            }
+            // check the updated package in case it is better
+            bindBestPackage(packageName);
+        }
+
+        @Override
+        public void onPackageAdded(String packageName, int uid) {
+            if (packageName.equals(mPackageName)) {
+                // package updated, make sure to rebind
+                unbind();
+            }
+            // check the new package is case it is better
+            bindBestPackage(packageName);
+        }
+
+        @Override
+        public void onPackageRemoved(String packageName, int uid) {
+            if (packageName.equals(mPackageName)) {
+                unbind();
+                // the currently bound package was removed,
+                // need to search for a new package
+                bindBestPackage(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;
+        }
+    }
+}
diff --git a/services/java/com/android/server/ShutdownActivity.java b/services/java/com/android/server/ShutdownActivity.java
index d85abe6..a4341b7 100644
--- a/services/java/com/android/server/ShutdownActivity.java
+++ b/services/java/com/android/server/ShutdownActivity.java
@@ -17,13 +17,12 @@
 package com.android.server;
 
 import android.app.Activity;
-import android.content.BroadcastReceiver;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.Handler;
 import android.util.Slog;
 
-import com.android.server.pm.ShutdownThread;
+import com.android.server.power.ShutdownThread;
 
 public class ShutdownActivity extends Activity {
 
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java
index 78c0c12..9f53fad 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/java/com/android/server/StatusBarManagerService.java
@@ -27,7 +27,6 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Slog;
-import android.view.View;
 
 import com.android.internal.statusbar.IStatusBar;
 import com.android.internal.statusbar.IStatusBarService;
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 e55e7fe..90783b7 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,9 +37,6 @@
 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.server.search.SearchManagerService;
 import android.service.dreams.DreamManagerService;
 import android.util.DisplayMetrics;
@@ -51,11 +50,16 @@
 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.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 +118,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,11 +138,11 @@
         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;
@@ -143,8 +150,60 @@
         CommonTimeManagementService commonTimeMgmtService = null;
         InputManagerService inputManager = 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 UI 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,6 +214,10 @@
             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));
 
@@ -164,10 +227,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 +243,7 @@
                 onlyCore = true;
             }
 
-            pm = PackageManagerService.main(context,
+            pm = PackageManagerService.main(context, installer,
                     factoryTest != SystemServer.FACTORY_TEST_OFF,
                     onlyCore);
             boolean firstBoot = false;
@@ -186,6 +253,11 @@
             }
 
             ActivityManagerService.setSystemProcess();
+            
+            Slog.i(TAG, "User Service");
+            ServiceManager.addService(Context.USER_SERVICE,
+                    UserManagerService.getInstance());
+
 
             mContentResolver = context.getContentResolver();
 
@@ -218,7 +290,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);
@@ -229,7 +302,8 @@
                     ActivityManagerService.self());
 
             Slog.i(TAG, "Window Manager");
-            wm = WindowManagerService.main(context, power,
+            wm = WindowManagerService.main(context, power, display,
+                    uiHandler, wmHandler,
                     factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,
                     !firstBoot, onlyCore);
             ServiceManager.addService(Context.WINDOW_SERVICE, wm);
@@ -237,6 +311,8 @@
             ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
 
             ActivityManagerService.self().setWindowManager(wm);
+            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
@@ -246,23 +322,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 +384,6 @@
         }
 
         if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
-            MountService mountService = null;
             if (!"0".equals(SystemProperties.get("system_init.startmountservice"))) {
                 try {
                     /*
@@ -555,7 +616,7 @@
             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);
             }
@@ -587,9 +648,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);
             }
@@ -710,6 +778,12 @@
         }
 
         try {
+            lockSettings.systemReady();
+        } catch (Throwable e) {
+            reportWtf("making Lock Settings Service ready", e);
+        }
+
+        try {
             wm.systemReady();
         } catch (Throwable e) {
             reportWtf("making Window Manager Service ready", e);
@@ -728,20 +802,27 @@
         w.getDefaultDisplay().getMetrics(metrics);
         context.getResources().updateConfiguration(config, metrics);
 
-        power.systemReady();
+        try {
+            power.systemReady(twilight);
+        } catch (Throwable e) {
+            reportWtf("making Power Manager Service ready", e);
+        }
+
         try {
             pm.systemReady();
         } catch (Throwable e) {
             reportWtf("making Package Manager Service ready", e);
         }
+
         try {
-            lockSettings.systemReady();
+            display.systemReady(safeMode, onlyCore);
         } catch (Throwable e) {
-            reportWtf("making Lock Settings Service ready", 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;
@@ -750,6 +831,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;
@@ -763,7 +845,6 @@
         final StatusBarManagerService statusBarF = statusBar;
         final DreamManagerService dreamyF = dreamy;
         final InputManagerService inputManagerF = inputManager;
-        final BluetoothService bluetoothF = bluetooth;
 
         // 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
@@ -776,6 +857,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);
@@ -811,6 +897,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);
@@ -876,7 +967,8 @@
                     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);
                 }
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index c23a1d9..8361477 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -25,6 +25,7 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.telephony.CellLocation;
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
@@ -35,6 +36,7 @@
 import android.util.Slog;
 
 import java.util.ArrayList;
+import java.util.List;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.net.NetworkInterface;
@@ -109,7 +111,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 |
@@ -242,7 +244,7 @@
                     }
                     if ((events & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
                         try {
-                            r.callback.onCellInfoChanged(new CellInfo(mCellInfo));
+                            r.callback.onCellInfoChanged(mCellInfo);
                         } catch (RemoteException ex) {
                             remove(r.binder);
                         }
@@ -336,7 +338,7 @@
         broadcastSignalStrengthChanged(signalStrength);
     }
 
-    public void notifyCellInfo(CellInfo cellInfo) {
+    public void notifyCellInfo(List<CellInfo> cellInfo) {
         if (!checkNotifyPermission("notifyCellInfo()")) {
             return;
         }
@@ -346,7 +348,7 @@
             for (Record r : mRecords) {
                 if ((r.events & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
                     try {
-                        r.callback.onCellInfoChanged(new CellInfo(cellInfo));
+                        r.callback.onCellInfoChanged(cellInfo);
                     } catch (RemoteException ex) {
                         mRemoveList.add(r.binder);
                     }
@@ -587,7 +589,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 +607,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 +630,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 +664,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) {
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index f35a5af..49f39fe 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) {}
     }
 
 
@@ -367,7 +369,7 @@
         }
 
         if (mPollStickyBroadcast != null) {
-            mContext.removeStickyBroadcast(mPollStickyBroadcast);
+            mContext.removeStickyBroadcastAsUser(mPollStickyBroadcast, UserHandle.ALL);
         }
     }
 
@@ -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 {
@@ -698,7 +700,7 @@
                 }
                 Intent broadcast = new Intent(ThrottleManager.THROTTLE_ACTION);
                 broadcast.putExtra(ThrottleManager.EXTRA_THROTTLE_LEVEL, -1);
-                mContext.sendStickyBroadcast(broadcast);
+                mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL);
                 mNotificationManager.cancel(R.drawable.stat_sys_throttled);
                 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..a7bce54
--- /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.getElapsedRealtimeNano() < from.getElapsedRealtimeNano()) {
+            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.getElapsedRealtimeNano() <
+                        lastKnownLocation.getElapsedRealtimeNano())) {
+                    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.setElapsedRealtimeNano(SystemClock.elapsedRealtimeNano());
+
+                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..3e83baa 100644
--- a/services/java/com/android/server/UiModeManagerService.java
+++ b/services/java/com/android/server/UiModeManagerService.java
@@ -18,7 +18,6 @@
 
 import android.app.Activity;
 import android.app.ActivityManagerNative;
-import android.app.AlarmManager;
 import android.app.IUiModeManager;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -32,55 +31,34 @@
 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.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 {
     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,10 +84,6 @@
 
     private NotificationManager mNotificationManager;
 
-    private AlarmManager mAlarmManager;
-
-    private LocationManager mLocationManager;
-    private Location mLocation;
     private StatusBarManager mStatusBarManager;
     private final PowerManager.WakeLock mWakeLock;
 
@@ -191,7 +165,7 @@
                     try {
                         ActivityManagerNative.getDefault().startActivityWithConfig(
                                 null, homeIntent, null, null, null, 0, 0,
-                                newConfig, null);
+                                newConfig, null, UserHandle.USER_CURRENT);
                         mHoldingConfiguration = false;
                     } catch (RemoteException e) {
                         Slog.w(TAG, e.getCause());
@@ -206,15 +180,6 @@
         }
     };
 
-    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);
-            }
-        }
-    };
-
     private final BroadcastReceiver mDockModeReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -236,113 +201,24 @@
         }
     };
 
-    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);
@@ -360,6 +236,8 @@
 
         mNightMode = Settings.Secure.getInt(mContext.getContentResolver(),
                 Settings.Secure.UI_NIGHT_MODE, UiModeManager.MODE_NIGHT_AUTO);
+
+        mTwilightService.registerListener(mTwilightListener, mHandler);
     }
 
     public void disableCarMode(int flags) {
@@ -419,8 +297,8 @@
         synchronized (mLock) {
             mSystemReady = true;
             mCarModeEnabled = mDockState == Intent.EXTRA_DOCK_STATE_CAR;
+            updateComputedNightModeLocked();
             updateLocked(0, 0);
-            mHandler.sendEmptyMessage(MSG_ENABLE_LOCATION_UPDATES);
         }
     }
 
@@ -467,7 +345,7 @@
         }
         if (mCarModeEnabled) {
             if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
-                updateTwilightLocked();
+                updateComputedNightModeLocked();
                 uiMode |= mComputedNightMode ? Configuration.UI_MODE_NIGHT_YES
                         : Configuration.UI_MODE_NIGHT_NO;
             } else {
@@ -520,7 +398,7 @@
                     adjustStatusBarCarModeLocked();
 
                     if (oldAction != null) {
-                        mContext.sendBroadcast(new Intent(oldAction));
+                        mContext.sendBroadcastAsUser(new Intent(oldAction), UserHandle.ALL);
                     }
                     mLastBroadcastState = Intent.EXTRA_DOCK_STATE_CAR;
                     action = UiModeManager.ACTION_ENTER_CAR_MODE;
@@ -528,7 +406,7 @@
             } else if (isDeskDockState(mDockState)) {
                 if (!isDeskDockState(mLastBroadcastState)) {
                     if (oldAction != null) {
-                        mContext.sendBroadcast(new Intent(oldAction));
+                        mContext.sendBroadcastAsUser(new Intent(oldAction), UserHandle.ALL);
                     }
                     mLastBroadcastState = mDockState;
                     action = UiModeManager.ACTION_ENTER_DESK_MODE;
@@ -554,7 +432,7 @@
                 Intent intent = new Intent(action);
                 intent.putExtra("enableFlags", enableFlags);
                 intent.putExtra("disableFlags", disableFlags);
-                mContext.sendOrderedBroadcast(intent, null,
+                mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, 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
@@ -585,7 +463,7 @@
 
                 if (homeIntent != null) {
                     try {
-                        mContext.startActivity(homeIntent);
+                        mContext.startActivityAsUser(homeIntent, UserHandle.CURRENT);
                     } catch (ActivityNotFoundException e) {
                     }
                 }
@@ -651,189 +529,20 @@
         }
     }
 
-    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 (isDoingNightMode() && 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 +567,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/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index 8a08277..b027c1f 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,6 +33,7 @@
 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;
@@ -41,6 +44,7 @@
 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 +52,7 @@
 import android.os.SELinux;
 import android.os.ServiceManager;
 import android.os.SystemClock;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.service.wallpaper.IWallpaperConnection;
 import android.service.wallpaper.IWallpaperEngine;
 import android.service.wallpaper.IWallpaperService;
@@ -77,7 +81,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,8 +93,6 @@
      * 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";
 
@@ -136,7 +137,7 @@
                             mWallpaper.imageWallpaperPending = false;
                         }
                         bindWallpaperComponentLocked(mWallpaper.imageWallpaperComponent, true,
-                                false, mWallpaper);
+                                false, mWallpaper, null);
                         saveSettingsLocked(mWallpaper);
                     }
                 }
@@ -146,6 +147,7 @@
 
     final Context mContext;
     final IWindowManager mIWindowManager;
+    final IPackageManager mIPackageManager;
     final MyPackageMonitor mMonitor;
     WallpaperData mLastWallpaper;
 
@@ -213,12 +215,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 +238,7 @@
             }
         }
 
+        @Override
         public void onServiceDisconnected(ComponentName name) {
             synchronized (mLock) {
                 mService = null;
@@ -245,16 +250,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) {
@@ -278,9 +302,10 @@
                         clearWallpaperComponentLocked(wallpaper);
                         // Do this only for the current user's wallpaper
                         if (wallpaper.userId == mCurrentUserId
-                                && !bindWallpaperComponentLocked(comp, false, false, wallpaper)) {
+                                && !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);
                         }
                     }
                 }
@@ -348,7 +373,7 @@
                     if (doit) {
                         Slog.w(TAG, "Wallpaper uninstalled, removing: "
                                 + wallpaper.wallpaperComponent);
-                        clearWallpaperLocked(false, wallpaper.userId);
+                        clearWallpaperLocked(false, wallpaper.userId, null);
                     }
                 }
             }
@@ -368,7 +393,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 +414,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);
+        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,29 +436,44 @@
 
     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);
         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)) {
+                    removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
                 }
             }
         }, 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) {
@@ -449,7 +490,7 @@
         }
     }
 
-    void switchUser(int userId) {
+    void switchUser(int userId, IRemoteCallback reply) {
         synchronized (mLock) {
             mCurrentUserId = userId;
             WallpaperData wallpaper = mWallpaperMap.get(userId);
@@ -460,35 +501,35 @@
                 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()) {
@@ -501,7 +542,7 @@
             if (userId != mCurrentUserId) return;
             if (bindWallpaperComponentLocked(defaultFailed
                     ? wallpaper.imageWallpaperComponent
-                    : null, true, false, wallpaper)) {
+                    : null, true, false, wallpaper, reply)) {
                 return;
             }
         } catch (IllegalArgumentException e1) {
@@ -516,21 +557,38 @@
         // 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) {
+            for (int i=0; i<mWallpaperMap.size(); i++) {
+                WallpaperData wd = mWallpaperMap.valueAt(i);
+                if (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 +610,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 +632,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 +655,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 +666,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 +713,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 +732,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) {
@@ -710,8 +768,9 @@
                     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
@@ -728,8 +787,10 @@
             Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
             if (componentName != null && !componentName.equals(wallpaper.imageWallpaperComponent)) {
                 // 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 +828,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 +850,7 @@
             wallpaper.wallpaperComponent = componentName;
             wallpaper.connection = newConn;
             wallpaper.lastDiedTime = SystemClock.uptimeMillis();
+            newConn.mReply = reply;
             try {
                 if (wallpaper.userId == mCurrentUserId) {
                     if (DEBUG)
@@ -804,8 +861,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 +874,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 +913,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 +931,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 +942,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"));
     }
 
@@ -1032,11 +1096,11 @@
             if (wallpaper.nextWallpaperComponent != null
                     && !wallpaper.nextWallpaperComponent.equals(wallpaper.imageWallpaperComponent)) {
                 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 +1116,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..9edfad6 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;
@@ -348,7 +349,7 @@
         }
 
         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..5c38e63 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import android.app.ActivityManager;
 import android.app.AlarmManager;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -55,9 +56,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 +113,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 +135,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 +160,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 +242,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 +251,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 +305,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 +414,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 +433,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 +504,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 +516,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 +566,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 +588,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 +609,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 +640,11 @@
          */
 
         long ident = Binder.clearCallingIdentity();
-        handleWifiToggled(enable);
-        Binder.restoreCallingIdentity(ident);
+        try {
+            handleWifiToggled(enable);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
 
         if (enable) {
             if (!mIsReceiverRegistered) {
@@ -791,7 +839,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 +933,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 +943,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 +986,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 +1012,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 +1070,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,
@@ -1142,17 +1195,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 +1214,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 +1229,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 +1260,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 +1379,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 +1389,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;
         }
     }
@@ -1753,8 +1795,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 +1809,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/WiredAccessoryObserver.java b/services/java/com/android/server/WiredAccessoryObserver.java
index 96ac493..56c0fdf 100644
--- a/services/java/com/android/server/WiredAccessoryObserver.java
+++ b/services/java/com/android/server/WiredAccessoryObserver.java
@@ -16,12 +16,12 @@
 
 package com.android.server;
 
-import android.app.ActivityManagerNative;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.PowerManager.WakeLock;
@@ -39,7 +39,7 @@
 /**
  * <p>WiredAccessoryObserver monitors for a wired headset on the main board or dock.
  */
-class WiredAccessoryObserver extends UEventObserver {
+final class WiredAccessoryObserver extends UEventObserver {
     private static final String TAG = WiredAccessoryObserver.class.getSimpleName();
     private static final boolean LOG = true;
     private static final int BIT_HEADSET = (1 << 0);
@@ -50,40 +50,177 @@
     private static final int SUPPORTED_HEADSETS = (BIT_HEADSET|BIT_HEADSET_NO_MIC|
                                                    BIT_USB_HEADSET_ANLG|BIT_USB_HEADSET_DGTL|
                                                    BIT_HDMI_AUDIO);
-    private static final int HEADSETS_WITH_MIC = BIT_HEADSET;
 
-    private static class UEventInfo {
-        private final String mDevName;
-        private final int mState1Bits;
-        private final int mState2Bits;
+    private final Object mLock = new Object();
 
-        public UEventInfo(String devName, int state1Bits, int state2Bits) {
-            mDevName = devName;
-            mState1Bits = state1Bits;
-            mState2Bits = state2Bits;
+    private final Context mContext;
+    private final WakeLock mWakeLock;  // held while there is a pending route change
+    private final AudioManager mAudioManager;
+    private final List<UEventInfo> mUEventInfo;
+
+    private int mHeadsetState;
+    private int mPrevHeadsetState;
+    private String mHeadsetName;
+
+    public WiredAccessoryObserver(Context context) {
+        mContext = context;
+
+        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WiredAccessoryObserver");
+        mWakeLock.setReferenceCounted(false);
+        mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
+
+        mUEventInfo = makeObservedUEventList();
+
+        context.registerReceiver(new BootCompletedReceiver(),
+            new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
+    }
+
+    @Override
+    public void onUEvent(UEventObserver.UEvent event) {
+        if (LOG) Slog.v(TAG, "Headset UEVENT: " + event.toString());
+
+        try {
+            String devPath = event.get("DEVPATH");
+            String name = event.get("SWITCH_NAME");
+            int state = Integer.parseInt(event.get("SWITCH_STATE"));
+            synchronized (mLock) {
+                updateStateLocked(devPath, name, state);
+            }
+        } catch (NumberFormatException e) {
+            Slog.e(TAG, "Could not parse switch state from event " + event);
+        }
+    }
+
+    private void bootCompleted() {
+        synchronized (mLock) {
+            char[] buffer = new char[1024];
+            mPrevHeadsetState = mHeadsetState;
+
+            if (LOG) Slog.v(TAG, "init()");
+
+            for (int i = 0; i < mUEventInfo.size(); ++i) {
+                UEventInfo uei = mUEventInfo.get(i);
+                try {
+                    int curState;
+                    FileReader file = new FileReader(uei.getSwitchStatePath());
+                    int len = file.read(buffer, 0, 1024);
+                    file.close();
+                    curState = Integer.valueOf((new String(buffer, 0, len)).trim());
+
+                    if (curState > 0) {
+                        updateStateLocked(uei.getDevPath(), uei.getDevName(), curState);
+                    }
+                } catch (FileNotFoundException e) {
+                    Slog.w(TAG, uei.getSwitchStatePath() +
+                            " not found while attempting to determine initial switch state");
+                } catch (Exception e) {
+                    Slog.e(TAG, "" , e);
+                }
+            }
         }
 
-        public String getDevName() { return mDevName; }
+        // At any given time accessories could be inserted
+        // one on the board, one on the dock and one on HDMI:
+        // observe three UEVENTs
+        for (int i = 0; i < mUEventInfo.size(); ++i) {
+            UEventInfo uei = mUEventInfo.get(i);
+            startObserving("DEVPATH="+uei.getDevPath());
+        }
+    }
 
-        public String getDevPath() {
-            return String.format("/devices/virtual/switch/%s", mDevName);
+    private void updateStateLocked(String devPath, String name, int state) {
+        for (int i = 0; i < mUEventInfo.size(); ++i) {
+            UEventInfo uei = mUEventInfo.get(i);
+            if (devPath.equals(uei.getDevPath())) {
+                updateLocked(name, uei.computeNewHeadsetState(mHeadsetState, state));
+                return;
+            }
+        }
+    }
+
+    private void updateLocked(String newName, int newState) {
+        // Retain only relevant bits
+        int headsetState = newState & SUPPORTED_HEADSETS;
+        int usb_headset_anlg = headsetState & BIT_USB_HEADSET_ANLG;
+        int usb_headset_dgtl = headsetState & BIT_USB_HEADSET_DGTL;
+        int h2w_headset = headsetState & (BIT_HEADSET | BIT_HEADSET_NO_MIC);
+        boolean h2wStateChange = true;
+        boolean usbStateChange = true;
+        // reject all suspect transitions: only accept state changes from:
+        // - a: 0 heaset to 1 headset
+        // - b: 1 headset to 0 headset
+        if (LOG) Slog.v(TAG, "newState = "+newState+", headsetState = "+headsetState+","
+            + "mHeadsetState = "+mHeadsetState);
+        if (mHeadsetState == headsetState || ((h2w_headset & (h2w_headset - 1)) != 0)) {
+            Log.e(TAG, "unsetting h2w flag");
+            h2wStateChange = false;
+        }
+        // - c: 0 usb headset to 1 usb headset
+        // - d: 1 usb headset to 0 usb headset
+        if ((usb_headset_anlg >> 2) == 1 && (usb_headset_dgtl >> 3) == 1) {
+            Log.e(TAG, "unsetting usb flag");
+            usbStateChange = false;
+        }
+        if (!h2wStateChange && !usbStateChange) {
+            Log.e(TAG, "invalid transition, returning ...");
+            return;
         }
 
-        public String getSwitchStatePath() {
-            return String.format("/sys/class/switch/%s/state", mDevName);
+        mHeadsetName = newName;
+        mPrevHeadsetState = mHeadsetState;
+        mHeadsetState = headsetState;
+
+        mWakeLock.acquire();
+
+        Message msg = mHandler.obtainMessage(0, mHeadsetState, mPrevHeadsetState, mHeadsetName);
+        mHandler.sendMessage(msg);
+    }
+
+    private void setDevicesState(
+            int headsetState, int prevHeadsetState, String headsetName) {
+        synchronized (mLock) {
+            int allHeadsets = SUPPORTED_HEADSETS;
+            for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) {
+                if ((curHeadset & allHeadsets) != 0) {
+                    setDeviceStateLocked(curHeadset, headsetState, prevHeadsetState, headsetName);
+                    allHeadsets &= ~curHeadset;
+                }
+            }
         }
+    }
 
-        public boolean checkSwitchExists() {
-            File f = new File(getSwitchStatePath());
-            return ((null != f) && f.exists());
-        }
+    private void setDeviceStateLocked(int headset,
+            int headsetState, int prevHeadsetState, String headsetName) {
+        if ((headsetState & headset) != (prevHeadsetState & headset)) {
+            int device;
+            int state;
 
-        public int computeNewHeadsetState(int headsetState, int switchState) {
-            int preserveMask = ~(mState1Bits | mState2Bits);
-            int setBits = ((switchState == 1) ? mState1Bits :
-                          ((switchState == 2) ? mState2Bits : 0));
+            if ((headsetState & headset) != 0) {
+                state = 1;
+            } else {
+                state = 0;
+            }
 
-            return ((headsetState & preserveMask) | setBits);
+            if (headset == BIT_HEADSET) {
+                device = AudioManager.DEVICE_OUT_WIRED_HEADSET;
+            } else if (headset == BIT_HEADSET_NO_MIC){
+                device = AudioManager.DEVICE_OUT_WIRED_HEADPHONE;
+            } else if (headset == BIT_USB_HEADSET_ANLG) {
+                device = AudioManager.DEVICE_OUT_ANLG_DOCK_HEADSET;
+            } else if (headset == BIT_USB_HEADSET_DGTL) {
+                device = AudioManager.DEVICE_OUT_DGTL_DOCK_HEADSET;
+            } else if (headset == BIT_HDMI_AUDIO) {
+                device = AudioManager.DEVICE_OUT_AUX_DIGITAL;
+            } else {
+                Slog.e(TAG, "setDeviceState() invalid headset type: "+headset);
+                return;
+            }
+
+            if (LOG)
+                Slog.v(TAG, "device "+headsetName+((state == 1) ? " connected" : " disconnected"));
+
+            mAudioManager.setWiredDeviceConnectionState(device, state, headsetName);
         }
     }
 
@@ -130,189 +267,53 @@
         return retVal;
     }
 
-    private static List<UEventInfo> uEventInfo = makeObservedUEventList();
-
-    private int mHeadsetState;
-    private int mPrevHeadsetState;
-    private String mHeadsetName;
-
-    private final Context mContext;
-    private final WakeLock mWakeLock;  // held while there is a pending route change
-
-    private final AudioManager mAudioManager;
-
-    public WiredAccessoryObserver(Context context) {
-        mContext = context;
-        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WiredAccessoryObserver");
-        mWakeLock.setReferenceCounted(false);
-        mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
-
-        context.registerReceiver(new BootCompletedReceiver(),
-            new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
-    }
-
-    private final class BootCompletedReceiver extends BroadcastReceiver {
-      @Override
-      public void onReceive(Context context, Intent intent) {
-        // At any given time accessories could be inserted
-        // one on the board, one on the dock and one on HDMI:
-        // observe three UEVENTs
-        init();  // set initial status
-        for (int i = 0; i < uEventInfo.size(); ++i) {
-            UEventInfo uei = uEventInfo.get(i);
-            startObserving("DEVPATH="+uei.getDevPath());
-        }
-      }
-    }
-
-    @Override
-    public void onUEvent(UEventObserver.UEvent event) {
-        if (LOG) Slog.v(TAG, "Headset UEVENT: " + event.toString());
-
-        try {
-            String devPath = event.get("DEVPATH");
-            String name = event.get("SWITCH_NAME");
-            int state = Integer.parseInt(event.get("SWITCH_STATE"));
-            updateState(devPath, name, state);
-        } catch (NumberFormatException e) {
-            Slog.e(TAG, "Could not parse switch state from event " + event);
-        }
-    }
-
-    private synchronized final void updateState(String devPath, String name, int state)
-    {
-        for (int i = 0; i < uEventInfo.size(); ++i) {
-            UEventInfo uei = uEventInfo.get(i);
-            if (devPath.equals(uei.getDevPath())) {
-                update(name, uei.computeNewHeadsetState(mHeadsetState, state));
-                return;
-            }
-        }
-    }
-
-    private synchronized final void init() {
-        char[] buffer = new char[1024];
-        mPrevHeadsetState = mHeadsetState;
-
-        if (LOG) Slog.v(TAG, "init()");
-
-        for (int i = 0; i < uEventInfo.size(); ++i) {
-            UEventInfo uei = uEventInfo.get(i);
-            try {
-                int curState;
-                FileReader file = new FileReader(uei.getSwitchStatePath());
-                int len = file.read(buffer, 0, 1024);
-                file.close();
-                curState = Integer.valueOf((new String(buffer, 0, len)).trim());
-
-                if (curState > 0) {
-                    updateState(uei.getDevPath(), uei.getDevName(), curState);
-                }
-
-            } catch (FileNotFoundException e) {
-                Slog.w(TAG, uei.getSwitchStatePath() +
-                        " not found while attempting to determine initial switch state");
-            } catch (Exception e) {
-                Slog.e(TAG, "" , e);
-            }
-        }
-    }
-
-    private synchronized final void update(String newName, int newState) {
-        // Retain only relevant bits
-        int headsetState = newState & SUPPORTED_HEADSETS;
-        int newOrOld = headsetState | mHeadsetState;
-        int delay = 0;
-        int usb_headset_anlg = headsetState & BIT_USB_HEADSET_ANLG;
-        int usb_headset_dgtl = headsetState & BIT_USB_HEADSET_DGTL;
-        int h2w_headset = headsetState & (BIT_HEADSET | BIT_HEADSET_NO_MIC);
-        boolean h2wStateChange = true;
-        boolean usbStateChange = true;
-        // reject all suspect transitions: only accept state changes from:
-        // - a: 0 heaset to 1 headset
-        // - b: 1 headset to 0 headset
-        if (LOG) Slog.v(TAG, "newState = "+newState+", headsetState = "+headsetState+","
-            + "mHeadsetState = "+mHeadsetState);
-        if (mHeadsetState == headsetState || ((h2w_headset & (h2w_headset - 1)) != 0)) {
-            Log.e(TAG, "unsetting h2w flag");
-            h2wStateChange = false;
-        }
-        // - c: 0 usb headset to 1 usb headset
-        // - d: 1 usb headset to 0 usb headset
-        if ((usb_headset_anlg >> 2) == 1 && (usb_headset_dgtl >> 3) == 1) {
-            Log.e(TAG, "unsetting usb flag");
-            usbStateChange = false;
-        }
-        if (!h2wStateChange && !usbStateChange) {
-            Log.e(TAG, "invalid transition, returning ...");
-            return;
-        }
-
-        mHeadsetName = newName;
-        mPrevHeadsetState = mHeadsetState;
-        mHeadsetState = headsetState;
-
-        mWakeLock.acquire();
-        mHandler.sendMessage(mHandler.obtainMessage(0,
-                                                    mHeadsetState,
-                                                    mPrevHeadsetState,
-                                                    mHeadsetName));
-    }
-
-    private synchronized final void setDevicesState(int headsetState,
-                                                    int prevHeadsetState,
-                                                    String headsetName) {
-        int allHeadsets = SUPPORTED_HEADSETS;
-        for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) {
-            if ((curHeadset & allHeadsets) != 0) {
-                setDeviceState(curHeadset, headsetState, prevHeadsetState, headsetName);
-                allHeadsets &= ~curHeadset;
-            }
-        }
-    }
-
-    private final void setDeviceState(int headset,
-                                      int headsetState,
-                                      int prevHeadsetState,
-                                      String headsetName) {
-        if ((headsetState & headset) != (prevHeadsetState & headset)) {
-            int device;
-            int state;
-
-            if ((headsetState & headset) != 0) {
-                state = 1;
-            } else {
-                state = 0;
-            }
-
-            if (headset == BIT_HEADSET) {
-                device = AudioManager.DEVICE_OUT_WIRED_HEADSET;
-            } else if (headset == BIT_HEADSET_NO_MIC){
-                device = AudioManager.DEVICE_OUT_WIRED_HEADPHONE;
-            } else if (headset == BIT_USB_HEADSET_ANLG) {
-                device = AudioManager.DEVICE_OUT_ANLG_DOCK_HEADSET;
-            } else if (headset == BIT_USB_HEADSET_DGTL) {
-                device = AudioManager.DEVICE_OUT_DGTL_DOCK_HEADSET;
-            } else if (headset == BIT_HDMI_AUDIO) {
-                device = AudioManager.DEVICE_OUT_AUX_DIGITAL;
-            } else {
-                Slog.e(TAG, "setDeviceState() invalid headset type: "+headset);
-                return;
-            }
-
-            if (LOG)
-                Slog.v(TAG, "device "+headsetName+((state == 1) ? " connected" : " disconnected"));
-
-            mAudioManager.setWiredDeviceConnectionState(device, state, headsetName);
-        }
-    }
-
-    private final Handler mHandler = new Handler() {
+    private final Handler mHandler = new Handler(Looper.myLooper(), null, true) {
         @Override
         public void handleMessage(Message msg) {
             setDevicesState(msg.arg1, msg.arg2, (String)msg.obj);
             mWakeLock.release();
         }
     };
+
+    private static final class UEventInfo {
+        private final String mDevName;
+        private final int mState1Bits;
+        private final int mState2Bits;
+
+        public UEventInfo(String devName, int state1Bits, int state2Bits) {
+            mDevName = devName;
+            mState1Bits = state1Bits;
+            mState2Bits = state2Bits;
+        }
+
+        public String getDevName() { return mDevName; }
+
+        public String getDevPath() {
+            return String.format("/devices/virtual/switch/%s", mDevName);
+        }
+
+        public String getSwitchStatePath() {
+            return String.format("/sys/class/switch/%s/state", mDevName);
+        }
+
+        public boolean checkSwitchExists() {
+            File f = new File(getSwitchStatePath());
+            return ((null != f) && f.exists());
+        }
+
+        public int computeNewHeadsetState(int headsetState, int switchState) {
+            int preserveMask = ~(mState1Bits | mState2Bits);
+            int setBits = ((switchState == 1) ? mState1Bits :
+                          ((switchState == 2) ? mState2Bits : 0));
+
+            return ((headsetState & preserveMask) | setBits);
+        }
+    }
+
+    private final class BootCompletedReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            bootCompleted();
+        }
+    }
 }
diff --git a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 8fa6722..f1a03de 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,104 @@
             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 motionEvent = (MotionEvent) event;
+        mEventHandler.onMotionEvent(motionEvent, policyFlags);
+    }
+
+    @Override
+    public void onMotionEvent(MotionEvent event, int policyFlags) {
+        sendInputEvent(event, 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..e7f3599 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -48,6 +48,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -58,9 +59,11 @@
 import android.util.Slog;
 import android.util.SparseArray;
 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 +77,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;
 
@@ -115,6 +117,8 @@
 
     private static final int MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER = 3;
 
+    private static final int MSG_SEND_UPDATE_INPUT_FILTER = 4;
+
     private static int sIdCounter = 0;
 
     private static int sNextWindowId;
@@ -157,20 +161,18 @@
 
     private boolean mIsTouchExplorationEnabled;
 
-    private final WindowManagerService mWindowManagerService;
+    private boolean mIsScreenMagnificationEnabled;
+
+    private final IWindowManager mWindowManager;
 
     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;
 
     /**
@@ -181,10 +183,9 @@
     public AccessibilityManagerService(Context context) {
         mContext = context;
         mPackageManager = mContext.getPackageManager();
-        mWindowManagerService = (WindowManagerService) ServiceManager.getService(
-                Context.WINDOW_SERVICE);
+        mWindowManager = (IWindowManager) ServiceManager.getService(Context.WINDOW_SERVICE);
         mSecurityPolicy = new SecurityPolicy();
-        mMainHandler = new MainHanler();
+        mMainHandler = new MainHandler(mContext.getMainLooper());
         registerPackageChangeAndBootCompletedBroadcastReceiver();
         registerSettingsContentObservers();
     }
@@ -202,7 +203,7 @@
                 synchronized (mLock) {
                     // We will update when the automation service dies.
                     if (mUiAutomationService == null) {
-                        populateAccessibilityServiceListLocked();
+                        populateInstalledAccessibilityServiceLocked();
                         manageServicesLocked();
                     }
                 }
@@ -263,18 +264,11 @@
                     synchronized (mLock) {
                         // We will update when the automation service dies.
                         if (mUiAutomationService == null) {
-                            populateAccessibilityServiceListLocked();
-                            populateEnabledAccessibilityServicesLocked();
-                            populateTouchExplorationGrantedAccessibilityServicesLocked();
-                            handleAccessibilityEnabledSettingChangedLocked();
-                            handleTouchExplorationEnabledSettingChangedLocked();
-                            updateInputFilterLocked();
-                            sendStateToClientsLocked();
+                            updateInternalStateLocked();
                         }
                     }
                     return;
                 }
-
                 super.onReceive(context, intent);
             }
         };
@@ -330,6 +324,24 @@
                     }
                 });
 
+        Uri accessibilityScreenMagnificationEnabledUri = Settings.Secure.getUriFor(
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED);
+        contentResolver.registerContentObserver(accessibilityScreenMagnificationEnabledUri, 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) {
+                            handleScreenMagnificationEnabledSettingChangedLocked();
+                            updateInputFilterLocked();
+                            sendStateToClientsLocked();
+                        }
+                    }
+                }
+            });
+
         Uri accessibilityServicesUri =
             Settings.Secure.getUriFor(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
         contentResolver.registerContentObserver(accessibilityServicesUri, false,
@@ -358,8 +370,7 @@
                         // We will update when the automation service dies.
                         if (mUiAutomationService == null) {
                             populateTouchExplorationGrantedAccessibilityServicesLocked();
-                            unbindAllServicesLocked();
-                            manageServicesLocked();
+                            handleTouchExplorationGrantedAccessibilityServicesChangedLocked();
                         }
                     }
                 }
@@ -385,18 +396,6 @@
     }
 
     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);
-        }
-
         synchronized (mLock) {
             if (mSecurityPolicy.canDispatchAccessibilityEvent(event)) {
                 mSecurityPolicy.updateActiveWindowAndEventSourceLocked(event);
@@ -406,22 +405,10 @@
             if (mHasInputFilter && mInputFilter != null) {
                 mMainHandler.obtainMessage(MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER,
                         AccessibilityEvent.obtain(event)).sendToTarget();
-
             }
             event.recycle();
             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());
     }
 
@@ -584,15 +571,24 @@
      *
      * @param outBounds The output to which to write the bounds.
      */
-    void getActiveWindowBounds(Rect outBounds) {
+    boolean getActiveWindowBounds(Rect outBounds) {
         synchronized (mLock) {
             final int windowId = mSecurityPolicy.mActiveWindowId;
             IBinder token = mWindowIdToWindowTokenMap.get(windowId);
-            mWindowManagerService.getWindowFrame(token, outBounds);
+            try {
+                WindowInfo info = mWindowManager.getWindowInfo(token);
+                if (info != null) {
+                    outBounds.set(info.frame);
+                    return true;
+                }
+            } catch (RemoteException re) {
+                /* ignore */
+            }
+            return false;
         }
     }
 
-    int getActiveWindowId() {
+    public int getActiveWindowId() {
         return mSecurityPolicy.mActiveWindowId;
     }
 
@@ -604,14 +600,6 @@
         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
@@ -624,7 +612,7 @@
         //       enabled accessibility services.
         for (int i = mServices.size() - 1; i >= 0; i--) {
             Service service = mServices.get(i);
-            if (service.mReqeustTouchExplorationMode && service.mIsDefault == isDefault) {
+            if (service.mRequestTouchExplorationMode && service.mIsDefault == isDefault) {
                 service.notifyGesture(gestureId);
                 return true;
             }
@@ -648,7 +636,7 @@
     /**
      * Populates the cached list of installed {@link AccessibilityService}s.
      */
-    private void populateAccessibilityServiceListLocked() {
+    private void populateInstalledAccessibilityServiceLocked() {
         mInstalledServices.clear();
 
         List<ResolveInfo> installedServices = mPackageManager.queryIntentServices(
@@ -658,11 +646,7 @@
         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(
-                    serviceInfo.permission)) {
+            if (!android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE.equals(serviceInfo.permission)) {
                 Slog.w(LOG_TAG, "Skipping accessibilty service " + new ComponentName(
                         serviceInfo.packageName, serviceInfo.name).flattenToShortString()
                         + ": it does not require the permission "
@@ -958,23 +942,26 @@
     }
 
     /**
-     * Updates the touch exploration state.
+     * Updates the state of the input filter.
      */
     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);
-        }
+         mMainHandler.obtainMessage(MSG_SEND_UPDATE_INPUT_FILTER).sendToTarget();
+    }
+
+    /**
+     * Updated the internal state of this service to match the current settings.
+     */
+    private void updateInternalStateLocked() {
+        populateInstalledAccessibilityServiceLocked();
+        populateEnabledAccessibilityServicesLocked();
+        populateTouchExplorationGrantedAccessibilityServicesLocked();
+
+        handleTouchExplorationEnabledSettingChangedLocked();
+        handleScreenMagnificationEnabledSettingChangedLocked();
+        handleAccessibilityEnabledSettingChangedLocked();
+
+        updateInputFilterLocked();
+        sendStateToClientsLocked();
     }
 
     /**
@@ -1000,6 +987,31 @@
                 Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0) == 1;
     }
 
+    /**
+     * Updates the state based on the screen magnification enabled setting.
+     */
+    private void handleScreenMagnificationEnabledSettingChangedLocked() {
+        mIsScreenMagnificationEnabled = Settings.Secure.getInt(
+                mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 0) == 1;
+    }
+
+    private void handleTouchExplorationGrantedAccessibilityServicesChangedLocked() {
+        final int serviceCount = mServices.size();
+        for (int i = 0; i < serviceCount; i++) {
+            Service service = mServices.get(i);
+            if (service.mRequestTouchExplorationMode
+                    && mTouchExplorationGrantedServices.contains(service.mComponentName)) {
+                tryEnableTouchExplorationLocked(service);
+                return;
+            }
+        }
+        if (mIsTouchExplorationEnabled) {
+            mMainHandler.obtainMessage(MSG_TOGGLE_TOUCH_EXPLORATION, 0,
+                    0).sendToTarget();
+        }
+    }
+
     private void tryEnableTouchExplorationLocked(final Service service) {
         if (!mIsTouchExplorationEnabled && service.mRequestTouchExplorationMode) {
             final boolean canToggleTouchExploration = mTouchExplorationGrantedServices.contains(
@@ -1055,7 +1067,12 @@
         }
     }
 
-    private class MainHanler extends Handler {
+    private class MainHandler extends Handler {
+
+        public MainHandler(Looper looper) {
+            super(looper);
+        }
+
         @Override
         public void handleMessage(Message msg) {
             final int type = msg.what;
@@ -1112,10 +1129,50 @@
                 case MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER: {
                     AccessibilityEvent event = (AccessibilityEvent) msg.obj;
                     if (mHasInputFilter && mInputFilter != null) {
-                        mInputFilter.onAccessibilityEvent(event);
+                        mInputFilter.notifyAccessibilityEvent(event);
                     }
                     event.recycle();
                 } break;
+                case MSG_SEND_UPDATE_INPUT_FILTER: {
+                    boolean setInputFilter = false;
+                    AccessibilityInputFilter inputFilter = null;
+                    synchronized (mLock) {
+                        if ((mIsAccessibilityEnabled && mIsTouchExplorationEnabled)
+                                || mIsScreenMagnificationEnabled) {
+                            if (!mHasInputFilter) {
+                                mHasInputFilter = true;
+                                if (mInputFilter == null) {
+                                    mInputFilter = new AccessibilityInputFilter(mContext,
+                                            AccessibilityManagerService.this);
+                                }
+                                inputFilter = mInputFilter;
+                                setInputFilter = true;
+                            }
+                            int flags = 0;
+                            if (mIsScreenMagnificationEnabled) {
+                                flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER;
+                            }
+                            if (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 {
+                            mWindowManager.setInputFilter(inputFilter);
+                        } catch (RemoteException re) {
+                            /* ignore */
+                        }
+                    }
+                } break;
             }
         }
     }
@@ -1163,8 +1220,6 @@
 
         boolean mCanRetrieveScreenContent;
 
-        boolean mReqeustTouchExplorationMode;
-
         boolean mIsAutomation;
 
         final Rect mTempBounds = new Rect();
@@ -1204,7 +1259,7 @@
             mIsAutomation = isAutomation;
             if (!isAutomation) {
                 mCanRetrieveScreenContent = accessibilityServiceInfo.getCanRetrieveWindowContent();
-                mReqeustTouchExplorationMode =
+                mRequestTouchExplorationMode =
                     (accessibilityServiceInfo.flags
                             & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0;
                 mIntent = new Intent().setComponent(mComponentName);
@@ -1334,8 +1389,6 @@
                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
                 throws RemoteException {
             final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
-            final int windowLeft;
-            final int windowTop;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
@@ -1348,10 +1401,6 @@
                         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 +1408,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 +1417,7 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return getCompatibilityScale(resolvedWindowId);
+            return 0;
         }
 
         @Override
@@ -1377,8 +1426,6 @@
                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
                 throws RemoteException {
             final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
-            final int windowLeft;
-            final int windowTop;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
@@ -1392,19 +1439,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 +1456,7 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return getCompatibilityScale(resolvedWindowId);
+            return 0;
         }
 
         @Override
@@ -1421,8 +1465,6 @@
                 IAccessibilityInteractionConnectionCallback callback, int flags,
                 long interrogatingTid) throws RemoteException {
             final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
-            final int windowLeft;
-            final int windowTop;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
@@ -1436,10 +1478,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 +1485,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 +1494,7 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return getCompatibilityScale(resolvedWindowId);
+            return 0;
         }
 
         @Override
@@ -1465,8 +1503,6 @@
                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
                 throws RemoteException {
             final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
-            final int windowLeft;
-            final int windowTop;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
@@ -1480,18 +1516,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 +1532,7 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return getCompatibilityScale(resolvedWindowId);
+            return 0;
         }
 
         @Override
@@ -1508,8 +1541,6 @@
                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
                 throws RemoteException {
             final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
-            final int windowLeft;
-            final int windowTop;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
@@ -1523,18 +1554,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,7 +1570,7 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return getCompatibilityScale(resolvedWindowId);
+            return 0;
         }
 
         @Override
@@ -1630,18 +1658,7 @@
                 // the state based on values in the settings database.
                 if (mIsAutomation) {
                     mUiAutomationService = null;
-
-                    populateEnabledAccessibilityServicesLocked();
-                    populateTouchExplorationGrantedAccessibilityServicesLocked();
-
-                    handleAccessibilityEnabledSettingChangedLocked();
-                    sendStateToClientsLocked();
-
-                    handleTouchExplorationEnabledSettingChangedLocked();
-                    updateInputFilterLocked();
-
-                    populateAccessibilityServiceListLocked();
-                    manageServicesLocked();
+                    updateInternalStateLocked();
                 }
             }
         }
@@ -1820,7 +1837,12 @@
 
         private float getCompatibilityScale(int windowId) {
             IBinder windowToken = mWindowIdToWindowTokenMap.get(windowId);
-            return mWindowManagerService.getWindowCompatibilityScale(windowToken);
+            try {
+                return mWindowManager.getWindowCompatibilityScale(windowToken);
+            } catch (RemoteException re) {
+                /* ignore */
+            }
+            return 1.0f;
         }
     }
 
@@ -1939,18 +1961,25 @@
         }
 
         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);
+            final long identity = Binder.clearCallingIdentity();
+            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 = mWindowManager.getFocusedWindowToken();
+                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);
+                        }
                     }
                 }
+            } catch (RemoteException re) {
+                /* ignore */
+            } finally {
+                Binder.restoreCallingIdentity(identity);
             }
             return -1;
         }
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..b715570
--- /dev/null
+++ b/services/java/com/android/server/accessibility/EventStreamTransformation.java
@@ -0,0 +1,90 @@
+/*
+ ** 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 a motion event.
+     *
+     * @param event The motion event.
+     * @param policyFlags Policy flags for the event.
+     */
+    public void onMotionEvent(MotionEvent event, 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..48781ac
--- /dev/null
+++ b/services/java/com/android/server/accessibility/ScreenMagnifier.java
@@ -0,0 +1,1798 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.provider.Settings;
+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;
+
+/**
+ * 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;
+
+    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.System.getFloat(context.getContentResolver(),
+                Settings.System.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, int policyFlags) {
+        mMagnifiedContentInteractonStateHandler.onMotionEvent(event);
+        switch (mCurrentState) {
+            case STATE_DELEGATING: {
+                handleMotionEventStateDelegating(event, policyFlags);
+            } break;
+            case STATE_DETECTING: {
+                mDetectingStateHandler.onMotionEvent(event, 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, int policyFlags) {
+        if (event.getActionMasked() == MotionEvent.ACTION_UP) {
+            if (mDetectingStateHandler.mDelayedEventQueue == null) {
+                transitionToState(STATE_DETECTING);
+            }
+        }
+        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());
+            }
+            mNext.onMotionEvent(event, 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 = mMagnificationController.getScale();
+                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, int policyFlags) {
+            cacheDelayedMotionEvent(event, 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, int policyFlags) {
+            MotionEventInfo info = MotionEventInfo.obtain(event, 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;
+                ScreenMagnifier.this.onMotionEvent(info.mEvent, info.mPolicyFlags);
+                info.recycle();
+            }
+        }
+
+        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 int mPolicyFlags;
+
+        public static MotionEventInfo obtain(MotionEvent event, 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, policyFlags);
+                return info;
+            }
+        }
+
+        private void initialize(MotionEvent event, int policyFlags) {
+            mEvent = MotionEvent.obtain(event);
+            mPolicyFlags = policyFlags;
+        }
+
+        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;
+            mPolicyFlags = 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_RECOMPUTE_VIEWPORT_BOUNDS = 2;
+        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 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();
+                }
+            };
+
+            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;
+                    }
+                } else {
+                    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_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: {
+                                    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()) {
+                scrollX = rectangle.left - magnifiedRegionBounds.left;
+            } 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_RECOMPUTE_VIEWPORT_BOUNDS: {
+                        final boolean animate = message.arg1 == 1;
+                        mViewport.recomputeBounds(animate);
+                    } 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;
+                    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);
+
+            Rect notMagnifiedFrame = mTempRect2;
+            notMagnifiedFrame.set(0, 0, 0, 0);
+
+            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;
+                    }
+                    if (isWindowMagnified(info.type)) {
+                        Rect clippedFrame = mTempRect3;
+                        clippedFrame.set(info.touchableRegion);
+                        subtract(clippedFrame, notMagnifiedFrame);
+                        magnifiedFrame.union(clippedFrame);
+                    } else {
+                        Rect clippedFrame = mTempRect3;
+                        clippedFrame.set(info.touchableRegion);
+                        subtract(clippedFrame, magnifiedFrame);
+                        notMagnifiedFrame.union(clippedFrame);
+                    }
+                    if (magnifiedFrame.bottom >= notMagnifiedFrame.top) {
+                        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..cb6b31a 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -25,6 +25,7 @@
 import android.gesture.GestureStroke;
 import android.gesture.Prediction;
 import android.graphics.Rect;
+import android.os.Build;
 import android.os.Handler;
 import android.os.SystemClock;
 import android.util.Slog;
@@ -35,9 +36,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 +65,7 @@
  *
  * @hide
  */
-public class TouchExplorer {
+class TouchExplorer implements EventStreamTransformation {
 
     private static final boolean DEBUG = false;
 
@@ -120,10 +121,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;
 
@@ -155,6 +152,9 @@
     // 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;
 
@@ -170,6 +170,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;
 
@@ -200,20 +203,25 @@
     // The id of the last touch explored window.
     private int mLastTouchedWindowId;
 
+    // Whether touch exploration gesture has ended.
+    private boolean mTouchExplorationGestureEnded;
+
+    // Whether touch interaction has ended.
+    private boolean mTouchInteractionEnded;
+
     /**
      * 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();
@@ -242,7 +250,11 @@
         }
     }
 
-    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.
@@ -278,8 +290,17 @@
         mLongPressingPointerDeltaX = 0;
         mLongPressingPointerDeltaY = 0;
         mCurrentState = STATE_TOUCH_EXPLORING;
+        if (mNext != null) {
+            mNext.clear();
+        }
     }
 
+    @Override
+    public void setNext(EventStreamTransformation next) {
+        mNext = next;
+    }
+
+    @Override
     public void onMotionEvent(MotionEvent event, int policyFlags) {
         if (DEBUG) {
             Slog.d(LOG_TAG, "Received event: " + event + ", policyFlags=0x"
@@ -308,9 +329,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 (mTouchExplorationGestureEnded
+                && eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
+            mTouchExplorationGestureEnded = false;
+            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 (mTouchInteractionEnded
+                && eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
+            mTouchInteractionEnded = false;
+            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,6 +363,9 @@
                 mLastTouchedWindowId = event.getWindowId();
             } break;
         }
+        if (mNext != null) {
+            mNext.onAccessibilityEvent(event);
+        }
     }
 
     /**
@@ -346,6 +387,15 @@
 
         switch (event.getActionMasked()) {
             case MotionEvent.ACTION_DOWN:
+                // The delayed enter not delivered implies that we have delivered
+                // TYPE_TOUCH_INTERACTION_START and not TYPE_TOUCH_INTERACTION_END,
+                // therefore we need to deliver the interaction end event here.
+                if (mSendHoverEnterDelayed.isPending()) {
+                    sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
+                }
+                // Announce the start of a new touch interaction.
+                sendAccessibilityEvent(
+                        AccessibilityEvent.TYPE_TOUCH_INTERACTION_START);
                 // 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
@@ -384,7 +434,7 @@
                         // to detect what the user is trying to do.
                         final int pointerId = receivedTracker.getPrimaryActivePointerId();
                         final int pointerIdBits = (1 << pointerId);
-                        mSendHoverEnterDelayed.post(event, pointerIdBits, policyFlags);
+                        mSendHoverEnterDelayed.post(event, true, pointerIdBits, policyFlags);
                     } break;
                     default: {
                         /* do nothing - let the code for ACTION_MOVE decide what to do */
@@ -431,6 +481,10 @@
                                     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.
@@ -539,7 +593,8 @@
 
                         // If we have not delivered the enter schedule exit.
                         if (mSendHoverEnterDelayed.isPending()) {
-                            mSendHoverExitDelayed.post(event, pointerIdBits, policyFlags);
+                            mSendHoverEnterDelayed.mTouchExplorationInProgress = false;
+                            mSendHoverExitDelayed.post(event, false, pointerIdBits, policyFlags);
                         } else {
                             // The user is touch exploring so we send events for end.
                             sendExitEventsIfNeeded(policyFlags);
@@ -644,6 +699,9 @@
                 }
              } break;
             case MotionEvent.ACTION_UP: {
+                // Announce the end of a new touch interaction.
+                sendAccessibilityEvent(
+                        AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
                 mCurrentState = STATE_TOUCH_EXPLORING;
             } break;
             case MotionEvent.ACTION_CANCEL: {
@@ -675,6 +733,10 @@
                 }
             } 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: {
                 mLongPressingPointerId = -1;
                 mLongPressingPointerDeltaX = 0;
@@ -713,6 +775,13 @@
                 }
             } break;
             case MotionEvent.ACTION_UP: {
+                // 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 +817,19 @@
     }
 
     /**
+     * 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);
+        }
+    }
+
+    /**
      * 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.
      *
@@ -795,7 +877,8 @@
         MotionEvent event = mInjectedPointerTracker.getLastInjectedHoverEvent();
         if (event != null && event.getActionMasked() != MotionEvent.ACTION_HOVER_EXIT) {
             final int pointerIdBits = event.getPointerIdBits();
-            mAms.touchExplorationGestureEnded();
+            mTouchExplorationGestureEnded = true;
+            mTouchInteractionEnded = true;
             sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIdBits, policyFlags);
         }
     }
@@ -810,7 +893,6 @@
         MotionEvent event = mInjectedPointerTracker.getLastInjectedHoverEvent();
         if (event != null && event.getActionMasked() == MotionEvent.ACTION_HOVER_EXIT) {
             final int pointerIdBits = event.getPointerIdBits();
-            mAms.touchExplorationGestureStarted();
             sendMotionEvent(event, MotionEvent.ACTION_HOVER_ENTER, pointerIdBits, policyFlags);
         }
     }
@@ -958,7 +1040,9 @@
 
         // Make sure that the user will see the event.
         policyFlags |= WindowManagerPolicy.FLAG_PASS_TO_USER;
-        mInputFilter.sendInputEvent(event, policyFlags);
+        if (mNext != null) {
+            mNext.onMotionEvent(event, policyFlags);
+        }
 
         mInjectedPointerTracker.onMotionEvent(event);
 
@@ -1008,11 +1092,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 +1108,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;
@@ -1062,16 +1150,24 @@
                 return;
             }
 
+            if (Build.IS_DEBUGGABLE) {
+                if (mSendHoverEnterDelayed.isPending()) {
+                    throw new IllegalStateException("mSendHoverEnterDelayed must not be pending.");
+                }
+                if (mSendHoverExitDelayed.isPending()) {
+                    throw new IllegalStateException("mSendHoverExitDelayed must not be pending.");
+                }
+                if (!mPerformLongPressDelayed.isPending()) {
+                    throw new IllegalStateException(
+                            "mPerformLongPressDelayed must not be pending.");
+                }
+            }
+
             // Remove pending event deliveries.
-            mSendHoverEnterDelayed.remove();
-            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);
+            // The touch interaction has ended since we will send a click.
+            sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
 
             int clickLocationX;
             int clickLocationY;
@@ -1140,42 +1236,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 +1261,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);
     }
 
     /**
@@ -1308,13 +1335,13 @@
         }
 
         public void remove() {
-            if (isPenidng()) {
+            if (isPending()) {
                 mHandler.removeCallbacks(this);
                 clear();
             }
         }
 
-        private boolean isPenidng() {
+        public boolean isPending() {
             return (mEvent != null);
         }
 
@@ -1377,7 +1404,7 @@
         }
 
         private void clear() {
-            if (!isPenidng()) {
+            if (!isPending()) {
                 return;
             }
             mEvent.recycle();
@@ -1398,15 +1425,18 @@
         private MotionEvent mPrototype;
         private int mPointerIdBits;
         private int mPolicyFlags;
+        private boolean mTouchExplorationInProgress;
 
         public SendHoverDelayed(int hoverAction, boolean gestureStarted) {
             mHoverAction = hoverAction;
             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);
+            mTouchExplorationInProgress = touchExplorationInProgress;
             mPointerIdBits = pointerIdBits;
             mPolicyFlags = policyFlags;
             mHandler.postDelayed(this, mDetermineUserIntentTimeout);
@@ -1443,6 +1473,7 @@
             mPrototype = null;
             mPointerIdBits = -1;
             mPolicyFlags = 0;
+            mTouchExplorationInProgress = false;
         }
 
         public void forceSendAndRemove() {
@@ -1459,10 +1490,17 @@
                 Slog.d(LOG_TAG_SEND_HOVER_DELAYED, mGestureStarted ?
                         "touchExplorationGestureStarted" : "touchExplorationGestureEnded");
             }
-            if (mGestureStarted) {
-                mAms.touchExplorationGestureStarted();
+            if (mTouchExplorationInProgress) {
+                if (mGestureStarted) {
+                    sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START);
+                } else {
+                    mTouchExplorationGestureEnded = true;
+                    mTouchInteractionEnded = true;
+                }
             } else {
-                mAms.touchExplorationGestureEnded();
+                if (!mGestureStarted) {
+                    mTouchInteractionEnded = true;
+                }
             }
             sendMotionEvent(mPrototype, mHoverAction, mPointerIdBits, mPolicyFlags);
             clear();
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..aefc264
--- /dev/null
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -0,0 +1,2158 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.content.pm.UserInfo;
+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();
+        }
+        if (!bringUpServiceLocked(r, service.getFlags(), false)) {
+            return new ComponentName("!", "Service process is bad");
+        }
+        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, true);
+                            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)) {
+                    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.handleIncomingUserLocked(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.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.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 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);
+
+        // 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) {
+            Slog.w(TAG, "Unable to launch app "
+                    + r.appInfo.packageName + "/"
+                    + r.appInfo.uid + " for service "
+                    + r.intent.getIntent() + ": user " + r.userId + " is stopped");
+            bringDownServiceLocked(r, true);
+            return false;
+        }
+
+        // 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 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=mAm.startProcessLocked(procName, 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 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, 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,
+                    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,
+                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.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, 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..ce5424b 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -27,6 +27,7 @@
 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 +47,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 +78,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 +101,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 +115,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 +124,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 +147,6 @@
 import java.io.StringWriter;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
@@ -153,7 +155,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;
@@ -242,37 +243,16 @@
     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;
+
     static final int MY_PID = Process.myPid();
     
     static final String[] EMPTY_STRING_ARRAY = new String[0];
@@ -454,6 +434,27 @@
     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>();
+
+    /**
+     * 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 +515,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 +564,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 +722,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 +828,9 @@
     static ActivityManagerService mSelf;
     static ActivityThread mSystemThread;
 
+    private int mCurrentUserId;
+    private UserManagerService mUserManager;
+
     private final class AppDeathRecipient implements IBinder.DeathRecipient {
         final ProcessRecord mApp;
         final int mPid;
@@ -876,6 +880,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;
@@ -1010,10 +1017,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 +1118,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 +1154,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 +1178,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 +1293,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 +1313,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;
+            }
             }
         }
     };
@@ -1521,6 +1543,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 +1561,16 @@
                 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));
+
         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();
         
@@ -1764,7 +1794,7 @@
     }
 
     private final void updateLruProcessInternalLocked(ProcessRecord app,
-            boolean oomAdj, boolean updateActivityTime, int bestPos) {
+            boolean updateActivityTime, 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);
@@ -1796,7 +1826,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,7 +1851,7 @@
                 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,
+                    updateLruProcessInternalLocked(cr.binding.service.app,
                             updateActivityTime, i+1);
                 }
             }
@@ -1829,21 +1859,21 @@
         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,
+                updateLruProcessInternalLocked(cpr.proc,
                         updateActivityTime, i+1);
             }
         }
-        
-        //Slog.i(TAG, "Putting proc to front: " + app.processName);
-        if (oomAdj) {
-            updateOomAdjLocked();
-        }
     }
 
     final void updateLruProcessLocked(ProcessRecord app,
             boolean oomAdj, boolean updateActivityTime) {
         mLruSeq++;
-        updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
+        updateLruProcessInternalLocked(app, updateActivityTime, 0);
+
+        //Slog.i(TAG, "Putting proc to front: " + app.processName);
+        if (oomAdj) {
+            updateOomAdjLocked();
+        }
     }
 
     final ProcessRecord getProcessRecordLocked(
@@ -1857,7 +1887,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);
@@ -1992,7 +2022,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 +2038,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 +2107,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();
@@ -2095,7 +2149,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 +2161,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 +2197,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 +2217,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.
      */
@@ -2223,7 +2299,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 +2427,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 = handleIncomingUserLocked(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 +2446,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 = handleIncomingUserLocked(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 = handleIncomingUserLocked(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 +2531,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 +2597,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 = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+                false, true, "startActivityInPackage", null);
 
         int ret = mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
                 resultTo, resultWho, requestCode, startFlags,
@@ -2545,23 +2614,18 @@
             Intent[] intents, String[] resolvedTypes, IBinder resultTo, Bundle options) {
         enforceNotIsolatedCaller("startActivities");
         int ret = mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo,
-                options, Binder.getOrigCallingUser());
+                options, UserHandle.getCallingUserId());
         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 = handleIncomingUserLocked(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 +2724,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 +2754,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);
         }
     }
     
@@ -3379,10 +3444,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 = handleIncomingUserLocked(pid, uid,
+                userId, false, true, "clearApplicationUserData", null);
         long callingId = Binder.clearCallingIdentity();
         try {
             IPackageManager pm = AppGlobals.getPackageManager();
@@ -3424,7 +3491,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 +3503,23 @@
             Slog.w(TAG, msg);
             throw new SecurityException(msg);
         }
-        
-        int userId = UserId.getCallingUserId();
+
+        userId = handleIncomingUserLocked(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 +3569,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 +3579,34 @@
             Slog.w(TAG, msg);
             throw new SecurityException(msg);
         }
-        final int userId = UserId.getCallingUserId();
+        userId = handleIncomingUserLocked(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)) {
+                        forceStopPackageLocked(packageName, pkgUid);
+                    }
                 }
             }
         } finally {
@@ -3540,16 +3615,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 +3631,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 +3644,50 @@
     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);
         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,7 +3738,8 @@
     }
 
     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) {
@@ -3657,18 +3749,29 @@
         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.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 +3784,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 +3829,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 +3920,79 @@
             }
         }
 
-        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 (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 +4018,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) {
@@ -3878,24 +4066,14 @@
             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);
-                }
-            }
+            mServices.processStartTimedOutLocked(app);
             EventLog.writeEvent(EventLogTags.AM_KILL, pid,
                     app.processName, app.setAdj, "start timeout");
             Process.killProcessQuiet(pid);
@@ -4095,24 +4273,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 +4399,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 +4420,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 +4455,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 +4548,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 +4582,13 @@
         
         synchronized(this) {
             int callingUid = Binder.getCallingUid();
+            userId = handleIncomingUserLocked(Binder.getCallingPid(), callingUid, userId,
+                    false, true, "getIntentSender", null);
             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 +4598,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 +4608,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 +4633,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 +4681,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 +4901,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 +4911,7 @@
     int checkCallingPermission(String permission) {
         return checkPermission(permission,
                 Binder.getCallingPid(),
-                UserId.getAppId(Binder.getCallingUid()));
+                UserHandle.getAppId(Binder.getCallingUid()));
     }
 
     /**
@@ -4875,7 +5042,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 +5087,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 +5106,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 +5398,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 +5734,28 @@
     }
 
     public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
-            int flags) {
+            int flags, int userId) {
         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);
+        if (userId != UserHandle.getCallingUserId()) {
+            // Check if the caller is holding permissions for cross-user requests.
+            if (checkComponentPermission(
+                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                    Binder.getCallingPid(), callingUid, -1, true)
+                    != PackageManager.PERMISSION_GRANTED) {
+                String msg = "Permission Denial: "
+                        + "Request to get recent tasks for user " + userId
+                        + " but is calling from user " + UserHandle.getUserId(callingUid)
+                        + "; this requires "
+                        + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+                Slog.w(TAG, msg);
+                throw new SecurityException(msg);
+            } else {
+                if (userId == UserHandle.USER_CURRENT) {
+                    userId = mCurrentUserId;
+                }
+            }
+        }
+
         synchronized (this) {
             enforceCallingPermission(android.Manifest.permission.GET_TASKS,
                     "getRecentTasks()");
@@ -5582,7 +5764,7 @@
                     == PackageManager.PERMISSION_GRANTED;
 
             IPackageManager pm = AppGlobals.getPackageManager();
-            
+
             final int N = mRecentTasks.size();
             ArrayList<ActivityManager.RecentTaskInfo> res
                     = new ArrayList<ActivityManager.RecentTaskInfo>(
@@ -5590,7 +5772,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 +5800,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;
                                 }
                             }
@@ -5689,29 +5871,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.
@@ -6055,15 +6215,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 +6374,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;
@@ -6218,10 +6389,13 @@
                           + " (pid=" + Binder.getCallingPid()
                           + ") when getting content provider " + name);
                 }
+                if (r.userId != userId) {
+                    throw new SecurityException("Calling requested user " + userId
+                            + " but app is user " + r.userId);
+                }
             }
 
             // 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) {
@@ -6296,6 +6470,7 @@
                 Binder.restoreCallingIdentity(origId);
             }
 
+            boolean singleton;
             if (!providerRunning) {
                 try {
                     cpi = AppGlobals.getPackageManager().
@@ -6306,7 +6481,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 +6502,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 +6528,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.
                     }
@@ -6463,17 +6650,19 @@
             throw new SecurityException(msg);
         }
 
-        return getContentProviderImpl(caller, name, null, stable);
+        return getContentProviderImpl(caller, name, null, stable,
+                UserHandle.getCallingUserId());
     }
 
     public ContentProviderHolder getContentProviderExternal(String name, IBinder token) {
         enforceCallingPermission(android.Manifest.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY,
             "Do not have permission in call getContentProviderExternal()");
-        return getContentProviderExternalUnchecked(name, token);
+        return getContentProviderExternalUnchecked(name, token, UserHandle.getCallingUserId());
     }
 
-    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 +6693,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 +6707,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 +6918,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 = handleIncomingUserLocked(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 +6936,7 @@
             return null;
         } finally {
             if (holder != null) {
-                removeContentProviderExternalUnchecked(name, null);
+                removeContentProviderExternalUnchecked(name, null, userId);
             }
             Binder.restoreCallingIdentity(ident);
         }
@@ -6766,7 +6955,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 +6963,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.
@@ -6812,7 +7001,7 @@
         // 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 +7032,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 +7040,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 +7064,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 + "'");
         }
@@ -7085,7 +7275,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);
             }
         }
@@ -7219,7 +7410,7 @@
         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;
@@ -7504,42 +7695,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 +7855,19 @@
             } catch (RemoteException e) {
             }
 
+            long ident = Binder.clearCallingIdentity();
+            try {
+                Intent intent = new Intent(Intent.ACTION_USER_STARTED);
+                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+                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);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
             mMainStack.resumeTopActivityLocked(null);
+            sendUserSwitchBroadcastsLocked(-1, mCurrentUserId);
         }
     }
 
@@ -7760,7 +7966,8 @@
                 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) {
@@ -7795,7 +8002,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 +8016,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);
                         }
                     }
                 }
@@ -8150,7 +8357,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) {
@@ -8423,11 +8630,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 +8706,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 +8719,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 +8775,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);
                     }
@@ -8723,7 +8948,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 +8969,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 +9008,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 +9283,18 @@
         }
 
         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("  mUserLru: [");
+        for (int i=0; i<mUserLru.size(); i++) {
+            if (i > 0) pw.print(", ");
+            pw.print(mUserLru.get(i));
+        }
+        pw.println("]");
         pw.println("  mHomeProcess: " + mHomeProcess);
         pw.println("  mPreviousProcess: " + mPreviousProcess);
         if (dumpAll) {
@@ -9134,7 +9371,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 +9453,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 +9652,15 @@
     boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
             int opti, boolean dumpAll, String dumpPackage) {
         boolean needSep = false;
-        
+        boolean onlyHistory = false;
+
+        if ("history".equals(dumpPackage)) {
+            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 +9693,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 +9741,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 +10046,7 @@
                 pw.print("    ");
                 pw.print("oom: max="); pw.print(r.maxAdj);
                 pw.print(" hidden="); pw.print(r.hiddenAdj);
+                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 +10535,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 +10544,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));
             }
         }
 
@@ -10810,7 +10632,7 @@
         app.hasShownUi = false;
         app.hasAboveClient = false;
 
-        killServicesLocked(app, allowRestart);
+        mServices.killServicesLocked(app, allowRestart);
 
         boolean restart = false;
 
@@ -10909,8 +10731,9 @@
             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.
@@ -10974,806 +10797,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 +10825,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 +10868,111 @@
         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) {
+        synchronized(this) {
+            return handleIncomingUserLocked(callingPid, callingUid, userId, allowAll,
+                    requireFull, name, callerPackage);
+        }        
+    }
+
+    int handleIncomingUserLocked(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) {
+                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 +10986,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 +11008,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 +11019,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 +11028,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);
         }
     }
     
@@ -12515,7 +11054,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 "
@@ -12633,9 +11172,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 +11217,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 +11236,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.handleIncomingUserLocked(callingPid, callingUid, userId,
+                    true, true, "registerReceiver", callerPackage);
+
             List allSticky = null;
 
             // Look for any matching sticky broadcasts...
@@ -12702,10 +11254,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 +11280,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 +11293,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 +11326,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 +11389,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 +11400,67 @@
             }
         }
     }
-    
+
+    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 (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 +11478,45 @@
         if ((resultTo != null) && !ordered) {
             Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
         }
-        
+
+        userId = handleIncomingUserLocked(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.
+         */
+        if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
+            || callingUid == Process.SHELL_UID || callingUid == 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 +11541,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 +11550,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 +11563,7 @@
                             }
                             if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
                                 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
-                                        new String[] {ssp});
+                                        new String[] {ssp}, userId);
                             }
                         }
                     }
@@ -12939,29 +11607,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 +11627,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 +11674,29 @@
             }
         }
 
+        int[] users;
+        if (userId == UserHandle.USER_ALL) {
+            // Caller wants broadcast to go to all started users.
+            users = new int[mStartedUsers.size()];
+            for (int i=0; i<mStartedUsers.size(); i++) {
+                users[i] = mStartedUsers.keyAt(i);
+            }
+        } 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 +11714,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 +11804,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 +11889,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 = handleIncomingUserLocked(Binder.getCallingPid(),
+                Binder.getCallingUid(), userId, true, false, "removeStickyBroadcast", null);
+
         synchronized(this) {
             if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
                     != PackageManager.PERMISSION_GRANTED) {
@@ -13241,15 +11908,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 +11981,10 @@
 
     public boolean startInstrumentation(ComponentName className,
             String profileFile, int flags, Bundle arguments,
-            IInstrumentationWatcher watcher) {
+            IInstrumentationWatcher watcher, int userId) {
         enforceNotIsolatedCaller("startInstrumentation");
+        userId = handleIncomingUserLocked(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 +11996,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 +12026,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 +12083,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");
@@ -13580,12 +12258,12 @@
                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
                         | Intent.FLAG_RECEIVER_REPLACE_PENDING);
                 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),
                             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 +12384,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 +12401,7 @@
                 } else {
                     try {
                         ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
-                                destIntent.getComponent(), 0, UserId.getCallingUserId());
+                                destIntent.getComponent(), 0, UserHandle.getCallingUserId());
                         int res = mMainStack.startActivityLocked(srec.app.thread, destIntent,
                                 null, aInfo, parent.appToken, null,
                                 0, -1, parent.launchedFromUid, 0, null, true, null);
@@ -13732,7 +12410,7 @@
                         foundParentInTask = false;
                     }
                     mMainStack.requestFinishActivityLocked(parent.appToken, resultCode,
-                            resultData, "navigate-up");
+                            resultData, "navigate-up", true);
                 }
             }
             Binder.restoreCallingIdentity(origId);
@@ -13775,14 +12453,15 @@
     }
 
     private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
-            ProcessRecord TOP_APP, boolean recursed, boolean doingAll) {
+            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;
+                app.curAdj = app.curRawAdj = app.nonStoppingAdj =
+                        app.hasActivities ? hiddenAdj : emptyAdj;
             }
             return app.curRawAdj;
         }
@@ -13790,7 +12469,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;
@@ -13807,6 +12486,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 +12497,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 +12514,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 +12530,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 +12552,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.
+        } else {
+            // 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.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.
-            adj = hiddenAdj;
-            schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
-            app.hidden = true;
-            app.empty = true;
-            app.adjType = "bg-empty";
         }
 
         boolean hasStoppingActivities = false;
@@ -13898,6 +12575,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,9 +12593,20 @@
                     foregroundActivities = true;
                     hasStoppingActivities = true;
                 }
+                if (r.app == app) {
+                    app.hasActivities = true;
+                }
             }
         }
 
+        if (adj == hiddenAdj && !app.hasActivities) {
+            // Whoops, this process is completely empty as far as we know
+            // at this point.
+            adj = emptyAdj;
+            app.empty = true;
+            app.adjType = "bg-empty";
+        }
+
         if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
             if (app.foregroundServices) {
                 // The user is aware of this app, so make it visible.
@@ -14005,7 +12694,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 +12740,16 @@
                                         myHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
                                     }
                                 }
-                                clientAdj = computeOomAdjLocked(
-                                    client, myHiddenAdj, TOP_APP, true, doingAll);
+                                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,
+                                        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 +12765,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
@@ -14190,8 +12888,16 @@
                             myHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
                         }
                     }
-                    int clientAdj = computeOomAdjLocked(
-                        client, myHiddenAdj, TOP_APP, true, doingAll);
+                    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,
+                            myEmptyAdj, TOP_APP, true, doingAll);
                     if (adj > clientAdj) {
                         if (app.hasShownUi && app != mHomeProcess
                                 && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
@@ -14604,9 +13310,10 @@
         }
     }
 
-    private final boolean updateOomAdjLocked(
-            ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP, boolean doingAll) {
+    private final boolean updateOomAdjLocked(ProcessRecord app, int hiddenAdj,
+            int emptyAdj, ProcessRecord TOP_APP, boolean doingAll) {
         app.hiddenAdj = hiddenAdj;
+        app.emptyAdj = emptyAdj;
 
         if (app.thread == null) {
             return false;
@@ -14616,7 +13323,7 @@
 
         boolean success = true;
 
-        computeOomAdjLocked(app, hiddenAdj, TOP_APP, false, doingAll);
+        computeOomAdjLocked(app, hiddenAdj, emptyAdj, TOP_APP, false, doingAll);
 
         if (app.curRawAdj != app.setRawAdj) {
             if (wasKeeping && !app.keeping) {
@@ -14694,7 +13401,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 +13410,8 @@
 
         mAdjSeq++;
 
-        boolean success = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP, false);
+        boolean success = updateOomAdjLocked(app, app.hiddenAdj, 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) {
@@ -14731,34 +13439,53 @@
         // 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 emptyFactor = (mLruProcesses.size()-mNumNonHiddenProcs-mNumHiddenProcs)/numSlots;
+        if (emptyFactor < 1) emptyFactor = 1;
+        int hiddenFactor = (mNumHiddenProcs > 0 ? mNumHiddenProcs : 1)/numSlots;
+        if (hiddenFactor < 1) hiddenFactor = 1;
+        int stepHidden = 0;
+        int stepEmpty = 0;
+        final int emptyProcessLimit = mProcessLimit > 1 ? mProcessLimit / 2 : mProcessLimit;
+        final int hiddenProcessLimit = mProcessLimit > 1 ? mProcessLimit / 2 : mProcessLimit;
         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;
         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, 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;
+                            }
+                        }
+                    }
                     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,
@@ -14766,8 +13493,37 @@
                         app.killedBackground = true;
                         Process.killProcessQuiet(app.pid);
                     }
+                } 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) {
+                        numEmpty++;
+                        if (numEmpty > emptyProcessLimit) {
+                            Slog.i(TAG, "No longer want " + app.processName
+                                    + " (pid " + app.pid + "): empty #" + numEmpty);
+                            EventLog.writeEvent(EventLogTags.AM_KILL, 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
@@ -14797,18 +13553,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.MAX_HIDDEN_APPS/4)
+                && numEmpty <= (ProcessList.MAX_HIDDEN_APPS/4)) {
+            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.MAX_HIDDEN_APPS/5)) {
                 fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
-            } else if (numHidden <= (ProcessList.MAX_HIDDEN_APPS/3)) {
+            } else if (numHiddenAndEmpty <= (ProcessList.MAX_HIDDEN_APPS/3)) {
                 fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
             } else {
                 fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
@@ -15007,7 +13765,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 +13784,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 +13828,40 @@
         }
     }
 
-    public boolean dumpHeap(String process, boolean managed,
+    private ProcessRecord findProcessLocked(String process, int userId, String callName) {
+        userId = handleIncomingUserLocked(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 +13878,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 +13926,392 @@
 
     // 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);
 
+                // 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));
+                }
+
+                mCurrentUserId = userId;
+                final Integer userIdInt = Integer.valueOf(userId);
+                mUserLru.remove(userIdInt);
+                mUserLru.add(userIdInt);
+
+                final UserStartedState uss = mStartedUsers.get(userId);
+
+                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);
+                Intent intent = new Intent(Intent.ACTION_USER_STARTED);
+                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+                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 = new Intent(Intent.ACTION_USER_INITIALIZE);
+                        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) {
+                                        synchronized (ActivityManagerService.this) {
+                                            getUserManagerLocked().makeInitialized(userInfo.id);
+                                        }
+                                    }
+                                }, 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID,
+                                userId);
+                    } else {
+                        getUserManagerLocked().makeInitialized(userInfo.id);
+                    }
+                }
+
+                boolean haveActivities = mMainStack.switchUserLocked(userId, uss);
+                if (!haveActivities) {
+                    startHomeActivityLocked(userId);
+                }
+            
+                sendUserSwitchBroadcastsLocked(oldUserId, userId);
+            }
+        } 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.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.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.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) {
+                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 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) {
+            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);
+            }
+        }
+    }
+
+    @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) {
+            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_STOPPING;
+
+                long ident = Binder.clearCallingIdentity();
+                try {
+                    // Inform of user switch
+                    Intent intent = new Intent(Intent.ACTION_SHUTDOWN);
+                    final IIntentReceiver resultReceiver = new IIntentReceiver.Stub() {
+                        @Override
+                        public void performReceive(Intent intent, int resultCode, String data,
+                                Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
+                            finishUserStop(uss);
+                        }
+                    };
+                    broadcastIntentLocked(null, null, intent,
+                            null, resultReceiver, 0, null, null, null,
+                            true, false, MY_PID, Process.SYSTEM_UID, userId);
+                } 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 (uss.mState != UserStartedState.STATE_STOPPING
+                    || mStartedUsers.get(userId) != uss) {
+                stopped = false;
+            } else {
+                stopped = true;
+                // User can no longer run.
+                mStartedUsers.remove(userId);
+
+                // 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_FULL)
+                != PackageManager.PERMISSION_GRANTED) {
+            String msg = "Permission Denial: getCurrentUser() from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid()
+                    + " requires " + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+            Slog.w(TAG, msg);
+            throw new SecurityException(msg);
+        }
+        synchronized (this) {
+            return getUserManagerLocked().getUserInfo(mCurrentUserId);
+        }
+    }
+
+    @Override
+    public boolean isUserRunning(int userId) {
+        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);
+        }
+    }
+
+    boolean isUserRunningLocked(int userId) {
+        UserStartedState state = mStartedUsers.get(userId);
+        return state != null && state.mState != UserStartedState.STATE_STOPPING;
+    }
+
+    @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 +14322,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 +14330,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..009fb5d 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;
@@ -321,7 +321,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 +333,6 @@
         state = ActivityState.INITIALIZING;
         frontOfTask = false;
         launchFailed = false;
-        haveState = false;
         stopped = false;
         delayedResume = false;
         finishing = false;
@@ -347,6 +346,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
@@ -614,14 +618,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(),
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index b9e63b7..29ee0bc 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;
@@ -210,7 +210,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.
@@ -418,11 +421,10 @@
     }
     
     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 && r.userId == mCurrentUser) {
                 return r;
             }
             i--;
@@ -431,11 +433,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 && r.userId == mCurrentUser) {
                 return r;
             }
             i--;
@@ -453,12 +454,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)
+                    && r.userId == mCurrentUser) {
                 return r;
             }
             i--;
@@ -500,7 +501,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 +545,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 +574,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,
@@ -723,7 +723,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 +754,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 +900,7 @@
             mService.notifyAll();
         }
     }
-    
+
     public final Bitmap screenshotActivities(ActivityRecord who) {
         if (who.noDisplay) {
             return null;
@@ -919,7 +917,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;
     }
@@ -1008,7 +1007,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);
@@ -1089,7 +1102,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) {
@@ -1395,7 +1408,7 @@
             // Launcher...
             if (mMainStack) {
                 ActivityOptions.abort(options);
-                return mService.startHomeActivityLocked(0);
+                return mService.startHomeActivityLocked(mCurrentUser);
             }
         }
 
@@ -1425,7 +1438,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);
@@ -1477,6 +1499,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, true);
+            }
             startPausingLocked(userLeaving, false);
             return true;
         }
@@ -1492,7 +1523,7 @@
                     Slog.d(TAG, "no-history finish of " + last + " on new resume");
                 }
                 requestFinishActivityLocked(last.appToken, Activity.RESULT_CANCELED, null,
-                "no-history");
+                        "no-history", false);
             }
         }
 
@@ -1714,14 +1745,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 {
@@ -2068,7 +2094,7 @@
                                 continue;
                             }
                             if (finishActivityLocked(p, srcPos,
-                                    Activity.RESULT_CANCELED, null, "reset")) {
+                                    Activity.RESULT_CANCELED, null, "reset", false)) {
                                 replyChainEnd--;
                                 srcPos--;
                             }
@@ -2131,7 +2157,7 @@
                             continue;
                         }
                         if (finishActivityLocked(p, srcPos,
-                                Activity.RESULT_CANCELED, null, "reset")) {
+                                Activity.RESULT_CANCELED, null, "reset", false)) {
                             taskTopI--;
                             lastReparentPos--;
                             replyChainEnd--;
@@ -2188,7 +2214,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--;
                                 }
@@ -2258,7 +2284,7 @@
                         continue;
                     }
                     if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
-                            null, "clear")) {
+                            null, "clear", false)) {
                         i--;
                     }
                 }
@@ -2272,7 +2298,7 @@
                         int index = indexOfTokenLocked(ret.appToken);
                         if (index >= 0) {
                             finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
-                                    null, "clear");
+                                    null, "clear", false);
                         }
                         return null;
                     }
@@ -2301,7 +2327,7 @@
                 continue;
             }
             if (!finishActivityLocked(r, i, Activity.RESULT_CANCELED,
-                    null, "clear")) {
+                    null, "clear", false)) {
                 i++;
             }
         }
@@ -2404,7 +2430,7 @@
         }
 
         if (err == ActivityManager.START_SUCCESS) {
-            final int userId = aInfo != null ? UserId.getUserId(aInfo.applicationInfo.uid) : 0;
+            final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
             Slog.i(TAG, "START {" + intent.toShortString(true, true, true, false)
                     + " u=" + userId + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
         }
@@ -3013,7 +3039,8 @@
         // 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)) {
+        if (aInfo != null && (aInfo.flags & ActivityInfo.FLAG_MULTIPROCESS) == 0
+                && mService.isSingleton(aInfo.processName, aInfo.applicationInfo, null, 0)) {
             userId = 0;
         }
         aInfo = mService.getActivityInfoForUser(aInfo, userId);
@@ -3062,7 +3089,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 +3333,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 +3439,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 +3521,10 @@
                 booting = mService.mBooting;
                 mService.mBooting = false;
             }
+            if (mStartingUsers.size() > 0) {
+                startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
+                mStartingUsers.clear();
+            }
         }
 
         int i;
@@ -3513,7 +3545,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 +3569,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 +3595,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 +3606,7 @@
         }
         ActivityRecord r = mHistory.get(index);
 
-        finishActivityLocked(r, index, resultCode, resultData, reason);
+        finishActivityLocked(r, index, resultCode, resultData, reason, oomAdj);
         return true;
     }
 
@@ -3587,10 +3623,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 +3650,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 +3689,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;
@@ -3704,7 +3742,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 +3766,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 +3779,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 +3808,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 +3830,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);
             }
@@ -3901,7 +3942,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;
         }
@@ -3982,9 +4023,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();
                 }
             }
 
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..07440b5 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) {
diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java
index 47b8c0a..b0af081 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;
 
@@ -219,7 +222,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 +252,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 +357,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 +386,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 +429,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 +580,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 +653,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 +668,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 +691,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 +740,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 +754,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 "
@@ -945,12 +965,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 +985,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
@@ -1003,7 +1024,8 @@
                 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) {
diff --git a/services/java/com/android/server/am/BroadcastRecord.java b/services/java/com/android/server/am/BroadcastRecord.java
index dd560fc..ca6d5f7 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,7 +80,7 @@
     void dump(PrintWriter pw, String prefix) {
         final long now = SystemClock.uptimeMillis();
 
-        pw.print(prefix); pw.println(this);
+        pw.print(prefix); pw.print(this); pw.print(" to user "); pw.println(userId);
         pw.print(prefix); pw.println(intent);
         if (sticky) {
             Bundle bundle = intent.getExtras();
@@ -140,14 +141,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 +169,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 +186,7 @@
         ordered = _serialized;
         sticky = _sticky;
         initialSticky = _initialSticky;
+        userId = _userId;
         nextReceiver = 0;
         state = IDLE;
     }
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..5b3ff8d 100644
--- a/services/java/com/android/server/am/ConnectionRecord.java
+++ b/services/java/com/android/server/am/ConnectionRecord.java
@@ -18,6 +18,7 @@
 
 import android.app.IServiceConnection;
 import android.app.PendingIntent;
+import android.content.Context;
 
 import java.io.PrintWriter;
 
@@ -62,6 +63,33 @@
         sb.append("ConnectionRecord{");
         sb.append(Integer.toHexString(System.identityHashCode(this)));
         sb.append(' ');
+        if ((flags&Context.BIND_AUTO_CREATE) != 0) {
+            sb.append("CR ");
+        }
+        if ((flags&Context.BIND_DEBUG_UNBIND) != 0) {
+            sb.append("DBG ");
+        }
+        if ((flags&Context.BIND_NOT_FOREGROUND) != 0) {
+            sb.append("NOTFG ");
+        }
+        if ((flags&Context.BIND_ABOVE_CLIENT) != 0) {
+            sb.append("ABCLT ");
+        }
+        if ((flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
+            sb.append("OOM ");
+        }
+        if ((flags&Context.BIND_WAIVE_PRIORITY) != 0) {
+            sb.append("WPRI ");
+        }
+        if ((flags&Context.BIND_IMPORTANT) != 0) {
+            sb.append("IMP ");
+        }
+        if ((flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
+            sb.append("ACT ");
+        }
+        if ((flags&Context.BIND_NOT_VISIBLE) != 0) {
+            sb.append("NOTVIS ");
+        }
         if (serviceDead) {
             sb.append("DEAD ");
         }
diff --git a/services/java/com/android/server/am/ContentProviderRecord.java b/services/java/com/android/server/am/ContentProviderRecord.java
index fb21b06..de306b5 100644
--- a/services/java/com/android/server/am/ContentProviderRecord.java
+++ b/services/java/com/android/server/am/ContentProviderRecord.java
@@ -38,6 +38,7 @@
     final int uid;
     final ApplicationInfo appInfo;
     final ComponentName name;
+    final boolean singleton;
     public IContentProvider provider;
     public boolean noReleaseNeeded;
     // All attached clients
@@ -54,12 +55,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 +71,7 @@
         uid = cpr.uid;
         appInfo = cpr.appInfo;
         name = cpr.name;
+        singleton = cpr.singleton;
         noReleaseNeeded = cpr.noReleaseNeeded;
     }
 
@@ -82,7 +85,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 +153,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) {
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..c61f13c 100644
--- a/services/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/java/com/android/server/am/PendingIntentRecord.java
@@ -25,7 +25,6 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.os.UserId;
 import android.util.Slog;
 
 import java.io.PrintWriter;
@@ -54,11 +53,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 +70,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 +104,9 @@
                 if (type != other.type) {
                     return false;
                 }
+                if (userId != other.userId){
+                    return false;
+                }
                 if (!packageName.equals(other.packageName)) {
                     return false;
                 }
@@ -156,7 +161,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() {
@@ -237,11 +242,10 @@
                                 allIntents[allIntents.length-1] = finalIntent;
                                 allResolvedTypes[allResolvedTypes.length-1] = resolvedType;
                                 owner.startActivitiesInPackage(uid, allIntents,
-                                        allResolvedTypes, resultTo, options);
+                                        allResolvedTypes, resultTo, options, key.userId);
                             } else {
-                                owner.startActivityInPackage(uid,
-                                        finalIntent, resolvedType,
-                                        resultTo, resultWho, requestCode, 0, options);
+                                owner.startActivityInPackage(uid, finalIntent, resolvedType,
+                                        resultTo, resultWho, requestCode, 0, options, key.userId);
                             }
                         } catch (RuntimeException e) {
                             Slog.w(ActivityManagerService.TAG,
@@ -259,8 +263,7 @@
                             owner.broadcastIntentInPackage(key.packageName, uid,
                                     finalIntent, resolvedType,
                                     finishedReceiver, code, null, null,
-                                requiredPermission, (finishedReceiver != null), false, UserId
-                                        .getUserId(uid));
+                                requiredPermission, (finishedReceiver != null), false, key.userId);
                             sendFinish = false;
                         } catch (RuntimeException e) {
                             Slog.w(ActivityManagerService.TAG,
@@ -270,7 +273,7 @@
                     case ActivityManager.INTENT_SENDER_SERVICE:
                         try {
                             owner.startServiceInPackage(uid,
-                                    finalIntent, resolvedType);
+                                    finalIntent, resolvedType, key.userId);
                         } catch (RuntimeException e) {
                             Slog.w(ActivityManagerService.TAG,
                                     "Unable to send startService intent", e);
@@ -281,7 +284,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..afc060e 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.
@@ -146,7 +147,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..d372422 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,7 @@
     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 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 +74,7 @@
     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 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.
@@ -199,6 +201,7 @@
                 pw.print(" empty="); pw.println(empty);
         pw.print(prefix); pw.print("oom: max="); pw.print(maxAdj);
                 pw.print(" hidden="); pw.print(hiddenAdj);
+                pw.print(" empty="); pw.print(emptyAdj);
                 pw.print(" curRaw="); pw.print(curRawAdj);
                 pw.print(" setRaw="); pw.print(setRawAdj);
                 pw.print(" nonStopping="); pw.print(nonStoppingAdj);
@@ -215,7 +218,9 @@
                 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(" removed="); pw.print(removed);
+                pw.print(" hasActivities="); pw.print(hasActivities);
+                pw.print(" foregroundActivities="); pw.println(foregroundActivities);
         pw.print(prefix); pw.print("adjSeq="); pw.print(adjSeq);
                 pw.print(" lruSeq="); pw.println(lruSeq);
         if (!keeping) {
@@ -308,12 +313,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 = emptyAdj = ProcessList.HIDDEN_APP_MIN_ADJ;
         curRawAdj = setRawAdj = -100;
         curAdj = setAdj = -100;
         persistent = false;
@@ -391,7 +396,7 @@
             sb.append(info.uid%Process.FIRST_APPLICATION_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..7055fdc 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);
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..7059674 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;
 
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..3f3ed85
--- /dev/null
+++ b/services/java/com/android/server/am/UserStartedState.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.am;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+import android.app.IStopUserCallback;
+import android.os.UserHandle;
+
+public class UserStartedState {
+    public final static int STATE_BOOTING = 0;
+    public final static int STATE_RUNNING = 1;
+    public final static int STATE_STOPPING = 2;
+
+    public final UserHandle mHandle;
+    public final ArrayList<IStopUserCallback> mStopCallbacks
+            = new ArrayList<IStopUserCallback>();
+
+    public int mState = STATE_BOOTING;
+
+    public UserStartedState(UserHandle handle, boolean initial) {
+        mHandle = handle;
+    }
+
+    void dump(String prefix, PrintWriter pw) {
+        pw.print(prefix); pw.print("mState="); pw.println(mState);
+    }
+}
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 682ecf8..79fb458 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());
@@ -501,8 +504,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);
+                }
             }
         }
     }
@@ -1135,7 +1143,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 +1173,7 @@
             mSetDnsForwardersErrorState = new SetDnsForwardersErrorState();
             addState(mSetDnsForwardersErrorState);
 
-            mNotifyList = new ArrayList();
+            mNotifyList = new ArrayList<TetherInterfaceSM>();
             setInitialState(mInitialState);
         }
 
@@ -1362,8 +1370,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 +1388,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 +1431,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 +1580,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..b3cbb84 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,116 @@
 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.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 +176,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 +203,7 @@
 
         Log.i(TAG, "Switched from " + mPackage + " to " + newPackage);
         mPackage = newPackage;
+        updateState(DetailedState.IDLE, "prepare");
         return true;
     }
 
@@ -144,7 +212,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 +276,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 +297,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 +308,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 +399,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,15 +417,18 @@
                     .setLargeIcon(icon)
                     .setContentTitle(title)
                     .setContentText(text)
-                    .setContentIntent(VpnConfig.getIntentForStatusPanel(mContext, config))
+                    .setContentIntent(mStatusIntent)
                     .setDefaults(0)
                     .setOngoing(true)
-                    .getNotification();
+                    .build();
             nm.notify(R.drawable.vpn_connected, notification);
         }
     }
 
     private void hideNotification() {
+        if (!mEnableNotif) return;
+        mStatusIntent = null;
+
         NotificationManager nm = (NotificationManager)
                 mContext.getSystemService(Context.NOTIFICATION_SERVICE);
 
@@ -366,31 +445,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;
+        }
     }
 
     /**
@@ -407,8 +627,6 @@
         private final String[] mDaemons;
         private final String[][] mArguments;
         private final LocalSocket[] mSockets;
-        private final String mOuterInterface;
-        private final LegacyVpnInfo mInfo;
 
         private long mTimer = -1;
 
@@ -416,20 +634,13 @@
             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.
-            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) {
-            if (interfaze.equals(mOuterInterface)) {
+            if (interfaze.equals(mConfig.interfaze)) {
                 Log.i(TAG, "Legacy VPN is going down with " + interfaze);
                 exit();
             }
@@ -439,21 +650,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 +662,7 @@
             synchronized (TAG) {
                 Log.v(TAG, "Executing");
                 execute();
+                monitorDaemons();
             }
         }
 
@@ -474,22 +674,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 +700,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 +708,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 +722,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 +781,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 +838,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..abc1d32
--- /dev/null
+++ b/services/java/com/android/server/display/DisplayAdapter.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.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;
+
+    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..f5aa3d4
--- /dev/null
+++ b/services/java/com/android/server/display/DisplayDevice.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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() {
+    }
+
+    /**
+     * 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..f0cd0f5
--- /dev/null
+++ b/services/java/com/android/server/display/DisplayDeviceInfo.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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 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 this display device can rotate to show contents in a
+     * different orientation.  Otherwise the rotation is assumed to be fixed in the
+     * natural orientation and the display manager should transform the content to fit.
+     */
+    public static final int FLAG_SUPPORTS_ROTATION = 1 << 1;
+
+    /**
+     * Flag: Indicates that this display device can show secure surfaces.
+     */
+    public static final int FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT = 1 << 2;
+
+    /**
+     * 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;
+
+    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;
+    }
+
+    @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;
+    }
+
+    // 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) + "}";
+    }
+
+    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_SUPPORTS_ROTATION) != 0) {
+            msg.append(", FLAG_SUPPORTS_ROTATION");
+        }
+        if ((flags & FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT) != 0) {
+            msg.append(", FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT");
+        }
+        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..39f2418
--- /dev/null
+++ b/services/java/com/android/server/display/DisplayManagerService.java
@@ -0,0 +1,888 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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;
+
+    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 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;
+
+    // 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 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();
+
+    // 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();
+
+        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();
+        }
+    }
+
+    /**
+     * Called during initialization to associate the display manager with the
+     * input manager.
+     */
+    public void setInputManager(InputManagerFuncs inputManagerFuncs) {
+        synchronized (mSyncRoot) {
+            mInputManagerFuncs = inputManagerFuncs;
+            scheduleTraversalLocked();
+        }
+    }
+
+    /**
+     * 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();
+                }
+            }
+        }
+    }
+
+    /**
+     * 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();
+        }
+    }
+
+    /**
+     * 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() {
+        if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission");
+        }
+
+        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 (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission");
+        }
+        if (address == null) {
+            throw new IllegalArgumentException("address must not be null");
+        }
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mSyncRoot) {
+                if (mWifiDisplayAdapter != null) {
+                    mWifiDisplayAdapter.requestConnectLocked(address);
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    @Override // Binder call
+    public void disconnectWifiDisplay() {
+        if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission");
+        }
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mSyncRoot) {
+                if (mWifiDisplayAdapter != null) {
+                    mWifiDisplayAdapter.requestDisconnectLocked();
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    @Override // Binder call
+    public WifiDisplayStatus getWifiDisplayStatus() {
+        if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission");
+        }
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mSyncRoot) {
+                if (mWifiDisplayAdapter != null) {
+                    return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
+                } else {
+                    return new WifiDisplayStatus();
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    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()) {
+                registerDisplayAdapterLocked(new OverlayDisplayAdapter(
+                        mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler));
+                mWifiDisplayAdapter = new WifiDisplayAdapter(
+                        mSyncRoot, mContext, mHandler, mDisplayAdapterListener);
+                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;
+            }
+
+            mDisplayDevices.add(device);
+            addLogicalDisplayLocked(device);
+            scheduleTraversalLocked();
+        }
+    }
+
+    private void handleDisplayDeviceChanged(DisplayDevice device) {
+        synchronized (mSyncRoot) {
+            if (!mDisplayDevices.contains(device)) {
+                Slog.w(TAG, "Attempted to change non-existent display device: "
+                        + device.getDisplayDeviceInfoLocked());
+                return;
+            }
+
+            device.applyPendingDisplayDeviceInfoChangesLocked();
+            if (updateLogicalDisplaysLocked()) {
+                scheduleTraversalLocked();
+            }
+        }
+    }
+
+    private void handleDisplayDeviceRemoved(DisplayDevice device) {
+        synchronized (mSyncRoot) {
+            if (!mDisplayDevices.remove(device)) {
+                Slog.w(TAG, "Attempted to remove non-existent display device: "
+                        + device.getDisplayDeviceInfoLocked());
+                return;
+            }
+
+            mRemovedDisplayDevices.add(device);
+            updateLogicalDisplaysLocked();
+            scheduleTraversalLocked();
+        }
+    }
+
+    // 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;
+        }
+
+        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.
+     */
+    public void setDisplayHasContent(int displayId, boolean hasContent) {
+        synchronized (mSyncRoot) {
+            LogicalDisplay display = mLogicalDisplays.get(displayId);
+            if (display != null && display.hasContentLocked() != hasContent) {
+                display.setHasContentLocked(hasContent);
+                scheduleTraversalLocked();
+            }
+        }
+    }
+
+    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 {
+            display.configureDisplayInTransactionLocked(device);
+        }
+
+        // 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() {
+        if (!mPendingTraversal && mWindowManagerFuncs != null) {
+            mPendingTraversal = true;
+            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)");
+        pw.println("  mHeadless=" + mHeadless);
+
+        synchronized (mSyncRoot) {
+            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);
+            }
+
+            pw.println();
+            pw.println("Default viewport: " + mDefaultViewport);
+            pw.println("External touch viewport: " + mExternalTouchViewport);
+        }
+    }
+
+    /**
+     * 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();
+            }
+        }
+    }
+
+    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..f3bec1d
--- /dev/null
+++ b/services/java/com/android/server/display/HeadlessDisplayAdapter.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.server.display;
+
+import android.content.Context;
+import android.os.Handler;
+import android.util.DisplayMetrics;
+
+/**
+ * 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";
+
+    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_SUPPORTS_SECURE_VIDEO_OUTPUT;
+                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..eab4c9a
--- /dev/null
+++ b/services/java/com/android/server/display/LocalDisplayAdapter.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.display;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.IBinder;
+import android.util.SparseArray;
+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 final PhysicalDisplayInfo mTempPhys = new PhysicalDisplayInfo();
+
+    public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
+            Context context, Handler handler, Listener listener) {
+        super(syncRoot, context, handler, listener, TAG);
+    }
+
+    @Override
+    public void registerLocked() {
+        // TODO: listen for notifications from Surface Flinger about
+        // built-in displays being added or removed and rescan as needed.
+        super.registerLocked();
+        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;
+
+        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;
+                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_SUPPORTS_SECURE_VIDEO_OUTPUT
+                            | DisplayDeviceInfo.FLAG_SUPPORTS_ROTATION;
+                    mInfo.densityDpi = (int)(mPhys.density * 160 + 0.5f);
+                    mInfo.xDpi = mPhys.xDpi;
+                    mInfo.yDpi = mPhys.yDpi;
+                    mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;
+                } else {
+                    mInfo.name = getContext().getResources().getString(
+                            com.android.internal.R.string.display_manager_hdmi_display_name);
+                    mInfo.flags = DisplayDeviceInfo.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT;
+                    mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
+                    mInfo.setAssumedDensityForExternalDisplay(mPhys.width, mPhys.height);
+                }
+            }
+            return mInfo;
+        }
+
+        @Override
+        public void dumpLocked(PrintWriter pw) {
+            super.dumpLocked(pw);
+            pw.println("mBuiltInDisplayId=" + mBuiltInDisplayId);
+            pw.println("mPhys=" + mPhys);
+        }
+    }
+}
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..3607de15
--- /dev/null
+++ b/services/java/com/android/server/display/LogicalDisplay.java
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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();
+
+    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_SECURE_VIDEO_OUTPUT) != 0) {
+                mBaseDisplayInfo.flags |= Display.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT;
+            }
+            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.
+     */
+    public void configureDisplayInTransactionLocked(DisplayDevice device) {
+        final DisplayInfo displayInfo = getDisplayInfoLocked();
+        final DisplayDeviceInfo displayDeviceInfo = device.getDisplayDeviceInfoLocked();
+
+        // Set the layer stack.
+        device.setLayerStackInTransactionLocked(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_SUPPORTS_ROTATION) != 0) {
+            orientation = displayInfo.rotation;
+        }
+
+        // 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("mLayerStack=" + mLayerStack);
+        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..75ddd24
--- /dev/null
+++ b/services/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.os.Handler;
+import android.os.IBinder;
+import android.provider.Settings;
+import android.util.DisplayMetrics;
+import android.util.Slog;
+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 = "";
+
+    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.System.getUriFor(Settings.Secure.OVERLAY_DISPLAY_DEVICES),
+                        true, new SettingsObserver(getHandler()));
+
+                synchronized (getSyncRoot()) {
+                    updateOverlayDisplayDevicesLocked();
+                }
+            }
+        });
+    }
+
+    private void updateOverlayDisplayDevicesLocked() {
+        String value = Settings.System.getString(getContext().getContentResolver(),
+                Settings.Secure.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 SettingsObserver extends ContentObserver {
+        public SettingsObserver(Handler handler) {
+            super(handler);
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            synchronized (getSyncRoot()) {
+                updateOverlayDisplayDevicesLocked();
+            }
+        }
+    }
+
+    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 DisplayDeviceInfo mInfo;
+
+        public OverlayDisplayDevice(IBinder displayToken, String name,
+                int width, int height, float refreshRate, int densityDpi,
+                Surface surface) {
+            super(OverlayDisplayAdapter.this, displayToken);
+            mName = name;
+            mWidth = width;
+            mHeight = height;
+            mRefreshRate = refreshRate;
+            mDensityDpi = densityDpi;
+            mSurface = surface;
+        }
+
+        public void clearSurfaceLocked() {
+            mSurface = null;
+            sendTraversalRequestLocked();
+        }
+
+        @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.densityDpi = mDensityDpi;
+                mInfo.xDpi = mDensityDpi;
+                mInfo.yDpi = mDensityDpi;
+                mInfo.flags = DisplayDeviceInfo.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT;
+                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(Surface surface, float refreshRate) {
+            synchronized (getSyncRoot()) {
+                IBinder displayToken = Surface.createDisplay(mName);
+                mDevice = new OverlayDisplayDevice(displayToken, mName,
+                        mWidth, mHeight, refreshRate, mDensityDpi, surface);
+
+                sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_ADDED);
+            }
+        }
+
+        // Called on the UI thread.
+        @Override
+        public void onWindowDestroyed() {
+            synchronized (getSyncRoot()) {
+                if (mDevice != null) {
+                    mDevice.clearSurfaceLocked();
+                    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..d08f65f
--- /dev/null
+++ b/services/java/com/android/server/display/OverlayDisplayWindow.java
@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.Surface;
+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);
+        }
+    }
+
+    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(new Surface(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(Surface surface, float refreshRate);
+        public void onWindowDestroyed();
+    }
+}
\ 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..b57d3dc
--- /dev/null
+++ b/services/java/com/android/server/display/WifiDisplayAdapter.java
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.content.Intent;
+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.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 WifiDisplayController mDisplayController;
+    private WifiDisplayDevice mDisplayDevice;
+
+    private WifiDisplayStatus mCurrentStatus;
+    private boolean mEnabled;
+    private int mScanState;
+    private int mActiveDisplayState;
+    private WifiDisplay mActiveDisplay;
+    private WifiDisplay[] mKnownDisplays = WifiDisplay.EMPTY_ARRAY;
+
+    private boolean mPendingStatusChangeBroadcast;
+
+    public WifiDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
+            Context context, Handler handler, Listener listener) {
+        super(syncRoot, context, handler, listener, TAG);
+    }
+
+    @Override
+    public void dumpLocked(PrintWriter pw) {
+        super.dumpLocked(pw);
+
+        pw.println("mCurrentStatus=" + getWifiDisplayStatusLocked());
+        pw.println("mEnabled=" + mEnabled);
+        pw.println("mScanState=" + mScanState);
+        pw.println("mActiveDisplayState=" + mActiveDisplayState);
+        pw.println("mActiveDisplay=" + mActiveDisplay);
+        pw.println("mKnownDisplays=" + Arrays.toString(mKnownDisplays));
+        pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast);
+
+        // 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();
+
+        getHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                mDisplayController = new WifiDisplayController(
+                        getContext(), getHandler(), mWifiDisplayListener);
+            }
+        });
+    }
+
+    public void requestScanLocked() {
+        getHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                if (mDisplayController != null) {
+                    mDisplayController.requestScan();
+                }
+            }
+        });
+    }
+
+    public void requestConnectLocked(final String address) {
+        getHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                if (mDisplayController != null) {
+                    mDisplayController.requestConnect(address);
+                }
+            }
+        });
+    }
+
+    public void requestDisconnectLocked() {
+        getHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                if (mDisplayController != null) {
+                    mDisplayController.requestDisconnect();
+                }
+            }
+        });
+    }
+
+    public WifiDisplayStatus getWifiDisplayStatusLocked() {
+        if (mCurrentStatus == null) {
+            mCurrentStatus = new WifiDisplayStatus(mEnabled, mScanState, mActiveDisplayState,
+                    mActiveDisplay, mKnownDisplays);
+        }
+        return mCurrentStatus;
+    }
+
+    private void handleConnectLocked(WifiDisplay display,
+            Surface surface, int width, int height, int flags) {
+        handleDisconnectLocked();
+
+        int deviceFlags = 0;
+        if ((flags & RemoteDisplay.DISPLAY_FLAG_SECURE) != 0) {
+            deviceFlags |= DisplayDeviceInfo.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT;
+        }
+
+        float refreshRate = 60.0f; // TODO: get this for real
+
+        String name = display.getDeviceName();
+        IBinder displayToken = Surface.createDisplay(name);
+        mDisplayDevice = new WifiDisplayDevice(displayToken, name, width, height,
+                refreshRate, deviceFlags, surface);
+        sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_ADDED);
+    }
+
+    private void handleDisconnectLocked() {
+        if (mDisplayDevice != null) {
+            mDisplayDevice.clearSurfaceLocked();
+            sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED);
+            mDisplayDevice = null;
+        }
+    }
+
+    private void scheduleStatusChangedBroadcastLocked() {
+        if (!mPendingStatusChangeBroadcast) {
+            mPendingStatusChangeBroadcast = true;
+            getHandler().post(mStatusChangeBroadcast);
+        }
+    }
+
+    private final Runnable mStatusChangeBroadcast = new Runnable() {
+        @Override
+        public void run() {
+            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 receivers that
+            // have the required permission.
+            getContext().sendBroadcast(intent,
+                    android.Manifest.permission.CONFIGURE_WIFI_DISPLAY);
+        }
+    };
+
+    private final WifiDisplayController.Listener mWifiDisplayListener =
+            new WifiDisplayController.Listener() {
+        @Override
+        public void onEnablementChanged(boolean enabled) {
+            synchronized (getSyncRoot()) {
+                if (mEnabled != enabled) {
+                    mCurrentStatus = null;
+                    mEnabled = enabled;
+                    scheduleStatusChangedBroadcastLocked();
+                }
+            }
+        }
+
+        @Override
+        public void onScanStarted() {
+            synchronized (getSyncRoot()) {
+                if (mScanState != WifiDisplayStatus.SCAN_STATE_SCANNING) {
+                    mCurrentStatus = null;
+                    mScanState = WifiDisplayStatus.SCAN_STATE_SCANNING;
+                    scheduleStatusChangedBroadcastLocked();
+                }
+            }
+        }
+
+        public void onScanFinished(WifiDisplay[] knownDisplays) {
+            synchronized (getSyncRoot()) {
+                if (mScanState != WifiDisplayStatus.SCAN_STATE_NOT_SCANNING
+                        || !Arrays.equals(mKnownDisplays, knownDisplays)) {
+                    mCurrentStatus = null;
+                    mScanState = WifiDisplayStatus.SCAN_STATE_NOT_SCANNING;
+                    mKnownDisplays = knownDisplays;
+                    scheduleStatusChangedBroadcastLocked();
+                }
+            }
+        }
+
+        @Override
+        public void onDisplayConnecting(WifiDisplay display) {
+            synchronized (getSyncRoot()) {
+                if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTING
+                        || mActiveDisplay == null
+                        || !mActiveDisplay.equals(display)) {
+                    mCurrentStatus = null;
+                    mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTING;
+                    mActiveDisplay = display;
+                    scheduleStatusChangedBroadcastLocked();
+                }
+            }
+        }
+
+        @Override
+        public void onDisplayConnectionFailed() {
+            synchronized (getSyncRoot()) {
+                if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED
+                        || mActiveDisplay != null) {
+                    mCurrentStatus = 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()) {
+                handleConnectLocked(display, surface, width, height, flags);
+
+                if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTED
+                        || mActiveDisplay == null
+                        || !mActiveDisplay.equals(display)) {
+                    mCurrentStatus = null;
+                    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) {
+                    mCurrentStatus = null;
+                    mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED;
+                    mActiveDisplay = null;
+                    scheduleStatusChangedBroadcastLocked();
+                }
+            }
+        }
+    };
+
+    private final class WifiDisplayDevice extends DisplayDevice {
+        private final String mName;
+        private final int mWidth;
+        private final int mHeight;
+        private final float mRefreshRate;
+        private final int mFlags;
+
+        private Surface mSurface;
+        private DisplayDeviceInfo mInfo;
+
+        public WifiDisplayDevice(IBinder displayToken, String name,
+                int width, int height, float refreshRate, int flags,
+                Surface surface) {
+            super(WifiDisplayAdapter.this, displayToken);
+            mName = name;
+            mWidth = width;
+            mHeight = height;
+            mRefreshRate = refreshRate;
+            mFlags = flags;
+            mSurface = surface;
+        }
+
+        public void clearSurfaceLocked() {
+            mSurface = null;
+            sendTraversalRequestLocked();
+        }
+
+        @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.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
+                mInfo.setAssumedDensityForExternalDisplay(mWidth, mHeight);
+            }
+            return mInfo;
+        }
+    }
+}
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..87e11e6
--- /dev/null
+++ b/services/java/com/android/server/display/WifiDisplayController.java
@@ -0,0 +1,820 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.display.WifiDisplay;
+import android.media.AudioManager;
+import android.media.RemoteDisplay;
+import android.net.NetworkInfo;
+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.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;
+
+/**
+ * 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 = 30;
+    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> mKnownWifiDisplayPeers =
+            new ArrayList<WifiP2pDevice>();
+
+    // 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;
+
+    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);
+    }
+
+    public void dump(PrintWriter pw) {
+        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("mKnownWifiDisplayPeers: size=" + mKnownWifiDisplayPeers.size());
+        for (WifiP2pDevice device : mKnownWifiDisplayPeers) {
+            pw.println("  " + describeWifiP2pDevice(device));
+        }
+    }
+
+    public void requestScan() {
+        discoverPeers();
+    }
+
+    public void requestConnect(String address) {
+        for (WifiP2pDevice device : mKnownWifiDisplayPeers) {
+            if (device.deviceAddress.equals(address)) {
+                connect(device);
+            }
+        }
+    }
+
+    public void requestDisconnect() {
+        disconnect();
+    }
+
+    private void enableWfd() {
+        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;
+                        setWfdEnabled(true);
+                    }
+                }
+
+                @Override
+                public void onFailure(int reason) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Failed to set WFD info with reason " + reason + ".");
+                    }
+                    mWfdEnabling = false;
+                }
+            });
+        }
+    }
+
+    private void setWfdEnabled(final boolean enabled) {
+        if (mWfdEnabled != enabled) {
+            mWfdEnabled = enabled;
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mListener.onEnablementChanged(enabled);
+                }
+            });
+        }
+    }
+
+    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.");
+                }
+
+                mKnownWifiDisplayPeers.clear();
+                for (WifiP2pDevice device : peers.getDeviceList()) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "  " + describeWifiP2pDevice(device));
+                    }
+
+                    if (isWifiDisplay(device)) {
+                        mKnownWifiDisplayPeers.add(device);
+                    }
+                }
+
+                handleScanFinished();
+            }
+        });
+    }
+
+    private void handleScanStarted() {
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mListener.onScanStarted();
+            }
+        });
+    }
+
+    private void handleScanFinished() {
+        final int count = mKnownWifiDisplayPeers.size();
+        final WifiDisplay[] displays = WifiDisplay.CREATOR.newArray(count);
+        for (int i = 0; i < count; i++) {
+            displays[i] = createWifiDisplay(mKnownWifiDisplayPeers.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() {
+        if (mDesiredDevice != null && mConnectedDevice != mDesiredDevice
+                && mConnectionRetriesLeft > 0) {
+            mConnectionRetriesLeft -= 1;
+            Slog.i(TAG, "Retrying Wifi display connection.  Retries left: "
+                    + mConnectionRetriesLeft);
+
+            // 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);
+
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mListener.onDisplayDisconnected();
+                }
+            });
+
+            // 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);
+
+            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);
+
+            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) {
+            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;
+
+            final WifiDisplay display = createWifiDisplay(mConnectingDevice);
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mListener.onDisplayConnecting(display);
+                }
+            });
+
+            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(final Surface surface,
+                        final int width, final int height, final 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);
+                        mHandler.post(new Runnable() {
+                            @Override
+                            public void run() {
+                                mListener.onDisplayConnected(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) {
+        if (mWifiP2pEnabled != enabled) {
+            mWifiP2pEnabled = enabled;
+            if (enabled) {
+                if (!mWfdEnabled) {
+                    enableWfd();
+                }
+            } else {
+                setWfdEnabled(false);
+                disconnect();
+            }
+        }
+    }
+
+    private void handlePeersChanged() {
+        if (mWifiP2pEnabled) {
+            if (mWfdEnabled) {
+                requestPeers();
+            } else {
+                enableWfd();
+            }
+        }
+    }
+
+    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);
+                            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!");
+
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mListener.onDisplayConnectionFailed();
+            }
+        });
+
+        if (mDesiredDevice != null) {
+            if (mConnectionRetriesLeft > 0) {
+                mHandler.postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        retryConnection();
+                    }
+                }, timeoutOccurred ? 0 : CONNECT_RETRY_DELAY_MILLIS);
+            } else {
+                disconnect();
+            }
+        }
+    }
+
+    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);
+    }
+
+    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)) {
+                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 onEnablementChanged(boolean enabled);
+
+        void onScanStarted();
+        void onScanFinished(WifiDisplay[] knownDisplays);
+
+        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/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..805818a 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;
@@ -57,11 +59,12 @@
 import android.os.RemoteException;
 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;
@@ -89,7 +92,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;
 
@@ -108,7 +112,6 @@
     private final Callbacks mCallbacks;
     private final InputManagerHandler mHandler;
     private boolean mSystemReady;
-    private BluetoothService mBluetoothService;
     private NotificationManager mNotificationManager;
 
     // Persistent data store.  Must be locked each time during use.
@@ -137,17 +140,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,
@@ -236,11 +240,11 @@
         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 +286,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);
     }
 
     /**
@@ -425,9 +428,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 +439,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);
@@ -1210,8 +1221,12 @@
     }
 
     // Native callback.
-    private void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
-        mCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
+    private void notifySwitch(long whenNanos, int switchCode, int switchValue) {
+        switch (switchCode) {
+            case SW_LID:
+                mCallbacks.notifyLidSwitchChanged(whenNanos, switchValue == 0);
+                break;
+        }
     }
 
     // Native callback.
@@ -1229,7 +1244,11 @@
     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;
             }
         }
@@ -1384,9 +1403,9 @@
 
     // 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;
     }
@@ -1422,6 +1441,10 @@
      * Private handler for the input manager.
      */
     private final class InputManagerHandler extends Handler {
+        public InputManagerHandler() {
+            super(true /*async*/);
+        }
+
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
@@ -1447,7 +1470,7 @@
     /**
      * 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() {
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..7d030e9 100644
--- a/services/java/com/android/server/location/GeocoderProxy.java
+++ b/services/java/com/android/server/location/GeocoderProxy.java
@@ -16,92 +16,64 @@
 
 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.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) {
+        GeocoderProxy proxy = new GeocoderProxy(context, initialPackageNames);
+        if (proxy.bind()) {
+            return proxy;
+        } else {
+            return null;
+        }
+    }
+
+    public GeocoderProxy(Context context, List<String> initialPackageNames) {
         mContext = context;
-        mIntent = new Intent(SERVICE_ACTION);
-        reconnect(packageName);
+
+        mServiceWatcher = new ServiceWatcher(mContext, TAG, SERVICE_ACTION, initialPackageNames,
+                null, null);
     }
 
-    /** 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 +83,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..26d9c15
--- /dev/null
+++ b/services/java/com/android/server/location/GeofenceManager.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 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.
+ */
+
+package com.android.server.location;
+
+import java.io.PrintWriter;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import android.Manifest.permission;
+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.Looper;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.util.Log;
+
+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;
+
+    /**
+     * 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)
+
+    private final Context mContext;
+    private final LocationManager mLocationManager;
+    private final PowerManager.WakeLock mWakeLock;
+    private final Looper mLooper;  // looper thread to take location updates on
+    private final LocationBlacklist mBlacklist;
+
+    private Object mLock = new Object();
+
+    // access to members below is synchronized on mLock
+    private Location mLastLocation;
+    private List<GeofenceState> mFences = new LinkedList<GeofenceState>();
+
+    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);
+        mLooper = Looper.myLooper();
+        mBlacklist = blacklist;
+
+        LocationRequest request = new LocationRequest()
+                .setQuality(LocationRequest.POWER_NONE)
+                .setFastestInterval(0);
+        mLocationManager.requestLocationUpdates(request, this, Looper.myLooper());
+    }
+
+    public void addFence(LocationRequest request, Geofence geofence, PendingIntent intent, int uid,
+            String packageName) {
+        GeofenceState state = new GeofenceState(geofence, mLastLocation,
+                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);
+            updateProviderRequirementsLocked();
+        }
+    }
+
+    public void removeFence(Geofence fence, PendingIntent intent) {
+        synchronized (mLock) {
+            Iterator<GeofenceState> iter = mFences.iterator();
+            while (iter.hasNext()) {
+                GeofenceState state = iter.next();
+                if (state.mIntent.equals(intent)) {
+
+                    if (fence == null) {
+                        // alwaus remove
+                        iter.remove();
+                    } else {
+                        // just remove matching fences
+                        if (fence.equals(state.mFence)) {
+                            iter.remove();
+                        }
+                    }
+                }
+            }
+            updateProviderRequirementsLocked();
+        }
+    }
+
+    public void removeFence(String packageName) {
+        synchronized (mLock) {
+            Iterator<GeofenceState> iter = mFences.iterator();
+            while (iter.hasNext()) {
+                GeofenceState state = iter.next();
+                if (state.mPackageName.equals(packageName)) {
+                    iter.remove();
+                }
+            }
+            updateProviderRequirementsLocked();
+        }
+    }
+
+    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 processLocation(Location location) {
+        List<PendingIntent> enterIntents = new LinkedList<PendingIntent>();
+        List<PendingIntent> exitIntents = new LinkedList<PendingIntent>();
+
+        synchronized (mLock) {
+            mLastLocation = location;
+
+            removeExpiredFencesLocked();
+
+            for (GeofenceState state : mFences) {
+                if (mBlacklist.isBlacklisted(state.mPackageName)) {
+                    if (D) Log.d(TAG, "skipping geofence processing for blacklisted app: " +
+                            state.mPackageName);
+                    continue;
+                }
+
+                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);
+                }
+            }
+            updateProviderRequirementsLocked();
+        }
+
+        // release lock before sending intents
+        for (PendingIntent intent : exitIntents) {
+            sendIntentExit(intent);
+        }
+        for (PendingIntent intent : enterIntents) {
+            sendIntentEnter(intent);
+        }
+    }
+
+    private void sendIntentEnter(PendingIntent pendingIntent) {
+        Intent intent = new Intent();
+        intent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, true);
+        sendIntent(pendingIntent, intent);
+    }
+
+    private void sendIntentExit(PendingIntent pendingIntent) {
+        Intent intent = new Intent();
+        intent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, false);
+        sendIntent(pendingIntent, intent);
+    }
+
+    private void sendIntent(PendingIntent pendingIntent, Intent intent) {
+        try {
+            mWakeLock.acquire();
+            pendingIntent.send(mContext, 0, intent, this, null, permission.ACCESS_FINE_LOCATION);
+        } catch (PendingIntent.CanceledException e) {
+            removeFence(null, pendingIntent);
+            mWakeLock.release();
+        }
+    }
+
+    private void updateProviderRequirementsLocked() {
+        double minDistance = Double.MAX_VALUE;
+        for (GeofenceState state : mFences) {
+            if (state.getDistance() < minDistance) {
+                minDistance = state.getDistance();
+            }
+        }
+
+        if (minDistance == Double.MAX_VALUE) {
+            disableLocationLocked();
+        } else {
+            int intervalMs = (int)(minDistance * 1000) / MAX_SPEED_M_S;
+            requestLocationLocked(intervalMs);
+        }
+    }
+
+    private void requestLocationLocked(int intervalMs) {
+        mLocationManager.requestLocationUpdates(new LocationRequest().setInterval(intervalMs), this,
+                mLooper);
+    }
+
+    private void disableLocationLocked() {
+        mLocationManager.removeUpdates(this);
+    }
+
+    @Override
+    public void onLocationChanged(Location location) {
+        processLocation(location);
+    }
+
+    @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");
+        }
+    }
+}
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..1fd737f
--- /dev/null
+++ b/services/java/com/android/server/location/GeofenceState.java
@@ -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.
+ */
+
+
+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 mDistance;  // current distance to center of fence
+
+    public GeofenceState(Geofence fence, Location prevLocation, long expireAt,
+            String packageName, PendingIntent intent) {
+        mState = STATE_UNKNOWN;
+
+        mFence = fence;
+        mExpireAt = expireAt;
+        mPackageName = packageName;
+        mIntent = intent;
+
+        mLocation = new Location("");
+        mLocation.setLatitude(fence.getLatitude());
+        mLocation.setLongitude(fence.getLongitude());
+
+        if (prevLocation != null) {
+            processLocation(prevLocation);
+        }
+    }
+
+    /**
+     * Process a new location.
+     * @return FLAG_ENTER or FLAG_EXIT if the fence was crossed, 0 otherwise
+     */
+    public int processLocation(Location location) {
+        mDistance = mLocation.distanceTo(location);
+
+        int prevState = mState;
+        //TODO: inside/outside detection could be made more rigorous
+        boolean inside = mDistance <= Math.max(mFence.getRadius(), location.getAccuracy());
+        if (inside) {
+            mState = STATE_INSIDE;
+        } else {
+            mState = STATE_OUTSIDE;
+        }
+
+        if (prevState != 0 && mState != prevState) {
+            if (mState == STATE_INSIDE) return FLAG_ENTER;
+            if (mState == STATE_OUTSIDE) return FLAG_EXIT;
+        }
+        return 0;
+    }
+
+    public double getDistance() {
+        return mDistance;
+    }
+
+    @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(), mDistance, state);
+    }
+}
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index 4ad6140..bb11fe7 100755
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -29,11 +29,13 @@
 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;
@@ -45,6 +47,7 @@
 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,17 +57,19 @@
 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;
@@ -81,8 +86,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 +159,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 +189,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 +220,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 +251,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 +267,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,7 +282,7 @@
 
     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>();
@@ -267,17 +298,11 @@
     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 +312,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 +340,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 +375,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 +383,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 +420,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,7 +431,7 @@
         // 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);
@@ -467,22 +505,21 @@
         IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(ALARM_WAKEUP);
         intentFilter.addAction(ALARM_TIMEOUT);
+        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
         mContext.registerReceiver(mBroadcastReciever, intentFilter);
     }
 
     /**
      * 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) {
@@ -516,7 +553,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 +578,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 +693,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 +721,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 +733,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 +778,69 @@
         }
     }
 
+    @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);
+    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 (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.setElapsedRealtimeNano(SystemClock.elapsedRealtimeNano());
             }
             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,25 +1519,19 @@
                         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();
             }
         }
     };
@@ -1617,17 +1542,39 @@
             super("GpsLocationProvider");
         }
 
+        @Override
         public void run() {
             Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
             initialize();
             Looper.prepare();
+
+            LocationManager locManager =
+                    (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
             mHandler = new ProviderHandler();
             // signal when we are initialized and ready to go
             mInitializedLatch.countDown();
+            locManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER,
+                    0, 0, new NetworkLocationListener(), Looper.myLooper());
             Looper.loop();
         }
     }
 
+    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);
+            }
+        }
+        @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() {
         Uri uri = Uri.parse("content://telephony/carriers/preferapn");
         String apn = null;
@@ -1647,6 +1594,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..38871d7 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.getElapsedRealtimeNano() <
+                        lastKnownLocation.getElapsedRealtimeNano()) {
                     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..71fa9f9
--- /dev/null
+++ b/services/java/com/android/server/location/LocationBlacklist.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.server.location;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.Handler;
+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];
+    
+    public LocationBlacklist(Context context, Handler handler) {
+        super(handler);
+        mContext = context;
+    }
+
+    public void init() {
+        mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
+                BLACKLIST_CONFIG_NAME), false, this);
+//        mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
+//                WHITELIST_CONFIG_NAME), false, this);
+        reloadBlacklist();
+    }
+
+    private void reloadBlacklist() {
+        String blacklist[] = getStringArray(BLACKLIST_CONFIG_NAME);
+        String whitelist[] = getStringArray(WHITELIST_CONFIG_NAME);
+        synchronized (mLock) {
+            mWhitelist = whitelist;
+            Slog.i(TAG, "whitelist: " + Arrays.toString(mWhitelist));
+            mBlacklist = blacklist;
+            Slog.i(TAG, "blacklist: " + Arrays.toString(mBlacklist));
+        }
+    }
+
+    /**
+     * 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();
+    }
+
+    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()]);
+    }
+
+    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..84fd255
--- /dev/null
+++ b/services/java/com/android/server/location/LocationFudger.java
@@ -0,0 +1,397 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.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";
+
+    private static final String EXTRA_COARSE_LOCATION = "coarseLocation";
+
+    /**
+     * 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) {
+            Bundle extras = location.getExtras();
+            if (extras == null) {
+                return addCoarseLocationExtraLocked(location);
+            }
+            Parcelable parcel = extras.getParcelable(EXTRA_COARSE_LOCATION);
+            if (parcel == null) {
+                return addCoarseLocationExtraLocked(location);
+            }
+            if (!(parcel instanceof Location)) {
+                return addCoarseLocationExtraLocked(location);
+            }
+            Location coarse = (Location) parcel;
+            if (coarse.getAccuracy() < mAccuracyInMeters) {
+                return addCoarseLocationExtraLocked(location);
+            }
+            return coarse;
+        }
+    }
+
+    private Location addCoarseLocationExtraLocked(Location location) {
+        Bundle extras = location.getExtras();
+        if (extras == null) extras = new Bundle();
+        Location coarse = createCoarseLocked(location);
+        extras.putParcelable(EXTRA_COARSE_LOCATION, coarse);
+        location.setExtras(extras);
+        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..6f09232 100644
--- a/services/java/com/android/server/location/LocationProviderInterface.java
+++ b/services/java/com/android/server/location/LocationProviderInterface.java
@@ -16,42 +16,33 @@
 
 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 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..7faf72c 100644
--- a/services/java/com/android/server/location/LocationProviderProxy.java
+++ b/services/java/com/android/server/location/LocationProviderProxy.java
@@ -16,458 +16,272 @@
 
 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.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) {
+        LocationProviderProxy proxy = new LocationProviderProxy(context, name, action,
+                initialPackageNames, handler);
+        if (proxy.bind()) {
+            return proxy;
+        } else {
+            return null;
+        }
+    }
+
+    private LocationProviderProxy(Context context, String name, String action,
+            List<String> initialPackageNames, Handler handler) {
         mContext = context;
         mName = name;
-        mIntent = new Intent(SERVICE_ACTION);
-        mHandler = handler;
-        reconnect(packageName);
+        mServiceWatcher = new ServiceWatcher(mContext, TAG, action, initialPackageNames,
+                mNewServiceWork, handler);
     }
 
-    /** 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 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..36c43ff 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,12 @@
         pw.println(prefix + "mStatusUpdateTime=" + mStatusUpdateTime);
         pw.println(prefix + "mExtras=" + mExtras);
     }
+
+    @Override
+    public void setRequest(ProviderRequest request, WorkSource source) { }
+
+    @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..0ce21b7 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,63 @@
  * {@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;
-    }
-
-    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 setRequest(ProviderRequest request, WorkSource source) {
+        mReportLocation = request.reportLocation;
     }
 
     public void updateLocation(Location location) {
-        if (mTracking) {
+        if (mReportLocation) {
             try {
                 // pass the location back to the location manager
                 mLocationManager.reportLocation(location, true);
@@ -141,13 +107,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("mReportLocaiton=" + 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..f2d6745
--- /dev/null
+++ b/services/java/com/android/server/net/LockdownVpnTracker.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.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) {
+        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..60666b4 100644
--- a/services/java/com/android/server/net/NetworkStatsCollection.java
+++ b/services/java/com/android/server/net/NetworkStatsCollection.java
@@ -29,8 +29,8 @@
 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.FileRotator;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Objects;
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index ba122ec..3a593e4 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -38,23 +38,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;
@@ -99,6 +99,7 @@
 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.telephony.PhoneStateListener;
@@ -763,7 +764,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 +990,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);
     }
 
     /**
@@ -1216,39 +1218,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 +1258,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 +1278,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..ad85c0d 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;
@@ -324,26 +324,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 +359,20 @@
         return execute("movefiles");
     }
 
+    /**
+     * 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) {
         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;
         }
 
@@ -387,16 +383,4 @@
 
         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);
-
-        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..536c612 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;
@@ -64,10 +69,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 +84,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 +108,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 +153,7 @@
 import libcore.io.ErrnoException;
 import libcore.io.IoUtils;
 import libcore.io.Libcore;
+import libcore.io.OsConstants;
 import libcore.io.StructStat;
 
 /**
@@ -165,6 +175,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 +186,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 +215,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 +283,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 +293,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;
@@ -388,6 +413,7 @@
     // package uri's from external media onto secure containers
     // or internal storage.
     private IMediaContainerService mContainerService = null;
+    private int mContainerServiceUserId;
 
     static final int SEND_PENDING_BROADCAST = 1;
     static final int MCS_BOUND = 3;
@@ -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>();
@@ -456,8 +482,15 @@
                     " DefaultContainerService");
             Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
             Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
+            mContainerServiceUserId = 0;
+            if (mPendingInstalls.size() > 0) {
+                mContainerServiceUserId = mPendingInstalls.get(0).getUser().getIdentifier();
+                if (mContainerServiceUserId == UserHandle.USER_ALL) {
+                    mContainerServiceUserId = 0;
+                }
+            }
             if (mContext.bindService(service, mDefContainerConn,
-                    Context.BIND_AUTO_CREATE)) {
+                    Context.BIND_AUTO_CREATE, mContainerServiceUserId)) {
                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                 mBound = true;
                 return true;
@@ -534,6 +567,15 @@
                     } else if (mPendingInstalls.size() > 0) {
                         HandlerParams params = mPendingInstalls.get(0);
                         if (params != null) {
+                            // Check if we're connected to the correct service, if it's an install
+                            // request.
+                            final int installFor = params.getUser().getIdentifier();
+                            if (installFor != mContainerServiceUserId
+                                    && (installFor == UserHandle.USER_ALL
+                                            && mContainerServiceUserId != 0)) {
+                                mHandler.sendEmptyMessage(MCS_RECONNECT);
+                                return;
+                            }
                             if (params.startCopy()) {
                                 // We are done...  look for more work or to
                                 // go idle.
@@ -650,15 +692,21 @@
                     break;
                 }
                 case START_CLEANING_PACKAGE: {
-                    String packageName = (String)msg.obj;
                     Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
+                    PackageCleanItem item = new PackageCleanItem((String)msg.obj,
+                            msg.arg2 != 0);
                     synchronized (mPackages) {
-                        if (!mSettings.mPackagesToBeCleaned.contains(packageName)) {
-                            mSettings.mPackagesToBeCleaned.add(packageName);
+                        if (msg.arg1 == UserHandle.USER_ALL) {
+                            int[] users = sUserManager.getUserIds();
+                            for (int user : users) {
+                                mSettings.addPackageToCleanLPw(user, item);
+                            }
+                        } else {
+                            mSettings.addPackageToCleanLPw(msg.arg1, item);
                         }
                     }
                     Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
-                    startCleaningPackages();
+                    startCleaningPackages(-1);
                 } break;
                 case POST_INSTALL: {
                     if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);
@@ -674,26 +722,65 @@
                             res.removedInfo.sendBroadcast(false, true);
                             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 +851,33 @@
                     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);
+                            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);
+                        }
+
+                        processPendingInstall(args, ret);
                         mHandler.sendEmptyMessage(MCS_UNBIND);
                     }
-
                     break;
                 }
                 case PACKAGE_VERIFIED: {
@@ -798,6 +901,8 @@
                         int ret;
                         if (state.isInstallAllowed()) {
                             ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+                            broadcastPackageVerified(verificationId, args.packageURI,
+                                    response.code);
                             try {
                                 ret = args.copyApk(mContainerService, true);
                             } catch (RemoteException e) {
@@ -832,9 +937,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 +967,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 +981,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 +1006,7 @@
             mSeparateProcesses = null;
         }
 
-        mInstaller = new Installer();
+        mInstaller = installer;
 
         WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
         Display d = wm.getDefaultDisplay();
@@ -916,11 +1024,12 @@
             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());
             long startTime = SystemClock.uptimeMillis();
 
             EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
@@ -1099,7 +1208,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 +1219,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()) {
@@ -1122,6 +1230,7 @@
             }
 
             mAppInstallDir = new File(dataDir, "app");
+            mAppLibInstallDir = new File(dataDir, "app-lib");
             //look for any incomplete package installations
             ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
             //clean up list
@@ -1160,9 +1269,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 "
@@ -1297,13 +1404,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 +1634,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 +1655,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,18 +1698,19 @@
     @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;
         }
     }
 
@@ -1712,14 +1813,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 +1831,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 +1855,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 +1866,12 @@
                 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));
             }
             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 +1887,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 +1912,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 +1935,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 +1943,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 +1956,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 +1964,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 +1974,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 +1982,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 +1992,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 +2000,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 +2046,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
@@ -1962,7 +2075,7 @@
 
     public int checkUidPermission(String permName, int uid) {
         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)) {
@@ -1981,6 +2094,34 @@
         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 +2137,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 +2340,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 +2399,7 @@
     }
 
     public String[] getPackagesForUid(int uid) {
-        uid = UserId.getAppId(uid);
+        uid = UserHandle.getAppId(uid);
         // reader
         synchronized (mPackages) {
             Object obj = mSettings.getUserIdLPr(uid);
@@ -2283,7 +2424,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 +2454,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);
     }
@@ -2394,6 +2536,9 @@
                 final int M = prefs.size();
                 for (int i=0; i<M; i++) {
                     final PreferredActivity pa = prefs.get(i);
+                    if (pa.mUserId != userId) {
+                        continue;
+                    }
                     if (pa.mPref.mMatch != match) {
                         continue;
                     }
@@ -2451,6 +2596,7 @@
     public List<ResolveInfo> queryIntentActivities(Intent intent,
             String resolvedType, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "query intent activities");
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -2490,6 +2636,8 @@
             Intent[] specifics, String[] specificTypes, Intent intent,
             String resolvedType, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        enforceCrossUserPermission(Binder.getCallingUid(), userId, false,
+                "query intent activity options");
         final String resultsAction = intent.getAction();
 
         List<ResolveInfo> results = queryIntentActivities(intent, resolvedType, flags
@@ -2759,11 +2907,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 +2989,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 +3013,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 +3043,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 +3062,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 +3090,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 +3141,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 +3172,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 +3240,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 +3306,7 @@
 
                     InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
                             ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString);
-                    synchronized (mInstaller) {
+                    synchronized (mInstallLock) {
                         args.cleanUpResourcesLI();
                     }
                     synchronized (mPackages) {
@@ -3183,7 +3340,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 +3362,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 +3393,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 +3535,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 +3596,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) {
@@ -3632,7 +3826,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 +3985,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 +3999,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 +4008,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 +4045,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 +4071,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 +4093,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 +4108,43 @@
                         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);
                     }
 
-                    /*
-                     * If this is an internal application or our
-                     * nativeLibraryPath points to our data directory, unpack
-                     * the libraries if necessary.
-                     */
-                    NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, 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 (mInstaller.linkNativeLibraryDirectory(dataPathString,
+                            pkg.applicationInfo.nativeLibraryDir) == -1) {
+                        Slog.e(TAG, "Unable to link native library directory");
+                        mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+                        return null;
+                    }
                 } else {
                     Slog.i(TAG, "Linking native library dir for " + path);
-                    mInstaller.linkNativeLibraryDirectory(dataPathString,
+                    int ret = mInstaller.linkNativeLibraryDirectory(dataPathString,
                             pkg.applicationInfo.nativeLibraryDir);
+                    if (ret < 0) {
+                        Slog.w(TAG, "Failed linking native library dir for " + path);
+                        mLastScanError = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
+                        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,7 +4181,9 @@
             // 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);
+            for (int i=0; i<mSettings.mPackagesToBeCleaned.size(); i++) {
+                mSettings.mPackagesToBeCleaned.valueAt(i).remove(pkgName);
+            }
             
             // Take care of first install / last update times.
             if (currentTime != 0) {
@@ -4268,20 +4459,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 +4539,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 +4657,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 +4965,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 +5043,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 +5057,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 +5081,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 +5167,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 +5240,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 +5254,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 +5279,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 +5380,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 = sUserManager.getUserIds();
+                }
                 for (int id : userIds) {
                     final Intent intent = new Intent(action,
                             pkg != null ? Uri.fromParts("package", pkg, null) : null);
@@ -5122,11 +5399,18 @@
                     }
                     // 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.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,8 +5428,9 @@
         return mMediaMounted || Environment.isExternalStorageEmulated();
     }
 
-    public String nextPackageToClean(String lastPackage) {
+    public PackageCleanItem nextPackageToClean(PackageCleanItem lastPackage) {
         // writer
+        final int userId = UserHandle.getCallingUserId();
         synchronized (mPackages) {
             if (!isExternalMediaAvailable()) {
                 // If the external storage is no longer mounted at this point,
@@ -5153,34 +5438,66 @@
                 // packages files and can not delete any more.  Bail.
                 return null;
             }
-            if (lastPackage != null) {
-                mSettings.mPackagesToBeCleaned.remove(lastPackage);
+            ArrayList<PackageCleanItem> pkgs = mSettings.mPackagesToBeCleaned.get(userId);
+            if (pkgs != null) {
+                if (lastPackage != null) {
+                    pkgs.remove(lastPackage);
+                }
+                if (pkgs.size() > 0) {
+                    return pkgs.get(0);
+                }
             }
-            return mSettings.mPackagesToBeCleaned.size() > 0
-                    ? mSettings.mPackagesToBeCleaned.get(0) : null;
+            mSettings.mPackagesToBeCleaned.remove(userId);
         }
+        // Move on to the next user to clean.
+        long ident = Binder.clearCallingIdentity();
+        try {
+            startCleaningPackages(userId);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+        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() {
+    void startCleaningPackages(int lastUser) {
         // reader
+        int nextUser = -1;
         synchronized (mPackages) {
             if (!isExternalMediaAvailable()) {
                 return;
             }
-            if (mSettings.mPackagesToBeCleaned.size() <= 0) {
+            final int N = mSettings.mPackagesToBeCleaned.size();
+            if (N <= 0) {
                 return;
             }
+            for (int i=0; i<N; i++) {
+                int user = mSettings.mPackagesToBeCleaned.keyAt(i);
+                if (user > lastUser) {
+                    nextUser = user;
+                    break;
+                }
+            }
+            if (nextUser < 0) {
+                nextUser = mSettings.mPackagesToBeCleaned.keyAt(0);
+            }
         }
         Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE);
         intent.setComponent(DEFAULT_CONTAINER_COMPONENT);
         IActivityManager am = ActivityManagerNative.getDefault();
         if (am != null) {
             try {
-                am.startService(null, intent, null);
+                am.startService(null, intent, null, nextUser);
             } catch (RemoteException e) {
             }
         }
@@ -5195,9 +5512,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 +5542,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 +5572,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 +5585,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 +5598,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 +5633,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,
+                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 +5664,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 +5727,49 @@
         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) {
+        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.sendBroadcast(intent, android.Manifest.permission.PACKAGE_VERIFICATION_AGENT);
+    }
+
     private ComponentName matchComponentForVerifier(String packageName,
             List<ResolveInfo> receivers) {
         ActivityInfo targetReceiver = null;
@@ -5447,20 +5882,45 @@
      * @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() {
+        if (!DEFAULT_VERIFY_ENABLE) {
+            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.Secure.getInt(mContext.getContentResolver(),
-                android.provider.Settings.Secure.PACKAGE_VERIFIER_ENABLE,
-                DEFAULT_VERIFY_ENABLE ? 1 : 0) == 1 ? true : false;
+                android.provider.Settings.Secure.INSTALL_NON_MARKET_APPS,
+                -1);
     }
 
     public void setInstallerPackageName(String targetPackage, String installerPackageName) {
@@ -5615,6 +6075,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 +6127,7 @@
         private final IPackageStatsObserver mObserver;
 
         public MeasureParams(PackageStats stats, IPackageStatsObserver observer) {
+            super(new UserHandle(stats.userHandle));
             mObserver = observer;
             mStats = stats;
         }
@@ -5663,7 +6135,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 +6143,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 +6166,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 +6202,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 +6210,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 +6237,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 +6339,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;
@@ -5884,6 +6374,8 @@
                     ret = PackageManager.INSTALL_FAILED_INVALID_URI;
                 } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
                     ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
+                } else if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {
+                    ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
                 } else {
                     // Override with defaults if needed.
                     loc = installLocationPolicy(pkgLite, flags);
@@ -5919,8 +6411,9 @@
                     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 +6430,29 @@
 
                     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.getInstallerUid() >= 0) {
+                            verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID,
+                                  verificationParams.getInstallerUid());
+                        }
                     }
 
                     final PackageVerificationState verificationState = new PackageVerificationState(
@@ -6018,12 +6531,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 +6577,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 +6731,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();
@@ -6275,11 +6792,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 +6806,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 +6848,7 @@
             installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
             codeFileName = createTempPackageFile(installDir).getPath();
             resourceFileName = getResourcePathFromCodePath();
+            libraryPath = getLibraryPathFromCodePath();
             created = true;
         }
 
@@ -6384,6 +6903,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 +6937,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 +6952,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 +7016,15 @@
             }
         }
 
+        private String getLibraryPathFromCodePath() {
+            return new File(mAppLibInstallDir, getApkName(getCodePath())).getPath();
+        }
+
         @Override
         String getNativeLibraryPath() {
+            if (libraryPath == null) {
+                libraryPath = getLibraryPathFromCodePath();
+            }
             return libraryPath;
         }
 
@@ -6493,6 +7050,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 +7128,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 +7147,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 +7305,7 @@
                 final int groupOwner;
                 final String protectedFile;
                 if (isFwdLocked()) {
-                    groupOwner = uid;
+                    groupOwner = UserHandle.getSharedAppGid(uid);
                     protectedFile = RES_FILE_NAME;
                 } else {
                     groupOwner = -1;
@@ -6817,7 +7387,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 +7481,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 +7494,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 +7522,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 +7539,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 +7564,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 +7588,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 +7597,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 +7618,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 +7634,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 +7652,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 +7682,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 +7701,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 +7721,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 +7880,7 @@
                     systemApp = (ps.pkg.applicationInfo.flags &
                             ApplicationInfo.FLAG_SYSTEM) != 0;
                 }
+                res.origUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
             }
         }
 
@@ -7327,11 +7899,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 +7958,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 +8007,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,8 +8037,7 @@
      *  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;
 
@@ -7468,27 +8052,30 @@
         }
         
         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);
         }
 
-        if (res && sendBroadCast) {
+        if (res) {
             boolean systemUpdate = info.isRemovedPackageSystemUpdate;
-            info.sendBroadcast(deleteCodeAndResources, systemUpdate);
+            info.sendBroadcast(true, systemUpdate);
 
             // If the removed package was a system update, the old system packaged
             // 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 +8084,7 @@
         // other processes clean up before deleting resources.
         if (info.args != null) {
             synchronized (mInstallLock) {
-                info.args.doPostDeleteLI(deleteCodeAndResources);
+                info.args.doPostDeleteLI(true);
             }
         }
 
@@ -7507,29 +8094,30 @@
     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) {
             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);
             }
             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 +8128,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 +8162,7 @@
                             mSettings.updateSharedUserPermsLPw(deletedPs, mGlobalGids);
                         }
                     }
-                    clearPackagePreferredActivitiesLPw(deletedPs.name);
+                    clearPackagePreferredActivitiesLPw(deletedPs.name, UserHandle.USER_ALL);
                 }
             }
             // can downgrade to reader
@@ -7593,38 +8176,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 +8209,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 +8235,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);
+            outInfo.args = createInstallArgs(packageFlagsToInstallFlags(ps), ps.codePathString,
+                    ps.resourcePathString, ps.nativeLibraryPathString);
         }
         return true;
     }
@@ -7686,54 +8256,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 +8349,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,44 +8365,54 @@
         }
 
         final Intent containerIntent = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
-        ClearStorageConnection conn = new ClearStorageConnection();
-        if (mContext.bindService(containerIntent, conn, Context.BIND_AUTO_CREATE)) {
-            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) {
+        int[] users;
+        if (userId == UserHandle.USER_ALL) {
+            users = sUserManager.getUserIds();
+        } else {
+            users = new int[] { userId };
+        }
+        for (int curUser : users) {
+            ClearStorageConnection conn = new ClearStorageConnection();
+            if (mContext.bindService(containerIntent, conn, Context.BIND_AUTO_CREATE, curUser)) {
+                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) {
+                            }
                         }
                     }
-                }
-                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 {
+                    mContext.unbindService(conn);
                 }
-            } finally {
-                mContext.unbindService(conn);
             }
         }
     }
@@ -7818,7 +8422,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 +8431,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 +8497,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 +8505,7 @@
                 synchronized (mInstallLock) {
                     succeded = deleteApplicationCacheFilesLI(packageName, userId);
                 }
-                clearExternalStorageDataSync(packageName, false);
+                clearExternalStorageDataSync(packageName, userId, false);
                 if(observer != null) {
                     try {
                         observer.onRemoveCompleted(packageName, succeded);
@@ -7941,12 +8545,12 @@
         return true;
     }
 
-    public void getPackageSizeInfo(final String packageName,
+    public void getPackageSizeInfo(final String packageName, int userHandle,
             final IPackageStatsObserver observer) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.GET_PACKAGE_SIZE, null);
 
-        PackageStats stats = new PackageStats(packageName);
+        PackageStats stats = new PackageStats(packageName, userHandle);
 
         /*
          * Queue up an async operation since the package measurement may take a
@@ -7957,7 +8561,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 +8599,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,26 +8651,28 @@
     }
     
     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(
-                    new PreferredActivity(filter, match, set, activity));
+                    new PreferredActivity(filter, match, set, activity, userId));
             scheduleWriteSettingsLocked();            
         }
     }
@@ -8101,13 +8708,15 @@
                 mContext.enforceCallingOrSelfPermission(
                         android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
             }
-            
+
+            final int callingUserId = UserHandle.getCallingUserId();
             ArrayList<PreferredActivity> removed = null;
             Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
             String action = filter.getAction(0);
             String category = filter.getCategory(0);
             while (it.hasNext()) {
                 PreferredActivity pa = it.next();
+                if (pa.mUserId != callingUserId) continue;
                 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
                     if (removed == null) {
                         removed = new ArrayList<PreferredActivity>();
@@ -8123,7 +8732,7 @@
                     mSettings.mPreferredActivities.removeFilter(pa);
                 }
             }
-            addPreferredActivity(filter, match, set, activity);
+            addPreferredActivity(filter, match, set, activity, callingUserId);
         }
     }
 
@@ -8147,17 +8756,21 @@
                 }
             }
 
-            if (clearPackagePreferredActivitiesLPw(packageName)) {
+            if (clearPackagePreferredActivitiesLPw(packageName, UserHandle.getCallingUserId())) {
                 scheduleWriteSettingsLocked();            
             }
         }
     }
 
-    boolean clearPackagePreferredActivitiesLPw(String packageName) {
+    /** This method takes a specific user id as well as UserHandle.USER_ALL. */
+    boolean clearPackagePreferredActivitiesLPw(String packageName, int userId) {
         ArrayList<PreferredActivity> removed = null;
         Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
         while (it.hasNext()) {
             PreferredActivity pa = it.next();
+            if (userId != UserHandle.USER_ALL && pa.mUserId != userId) {
+                continue;
+            }
             if (pa.mPref.mComponent.getPackageName().equals(packageName)) {
                 if (removed == null) {
                     removed = new ArrayList<PreferredActivity>();
@@ -8179,11 +8792,15 @@
             List<ComponentName> outActivities, String packageName) {
 
         int num = 0;
+        final int userId = UserHandle.getCallingUserId();
         // reader
         synchronized (mPackages) {
             final Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
             while (it.hasNext()) {
                 final PreferredActivity pa = it.next();
+                if (pa.mUserId != userId) {
+                    continue;
+                }
                 if (packageName == null
                         || pa.mPref.mComponent.getPackageName().equals(packageName)) {
                     if (outFilters != null) {
@@ -8227,7 +8844,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 +8865,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 +8914,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 +8963,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 +8972,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 +8993,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 +9004,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);
@@ -8951,7 +9568,7 @@
             if (DEBUG_SD_INSTALL)
                 Log.i(TAG, "Loading packages");
             loadMediaPackages(processCids, uidArr, removeCids);
-            startCleaningPackages();
+            startCleaningPackages(-1);
         } else {
             if (DEBUG_SD_INSTALL)
                 Log.i(TAG, "Unloading packages");
@@ -8972,7 +9589,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 +9634,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 +9743,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 +9768,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 +9782,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 +9838,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,31 +9910,26 @@
                                     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 (!isForwardLocked(pkg) && !isExternal(pkg)) {
+                                        synchronized (mInstallLock) {
                                             if (mInstaller.linkNativeLibraryDirectory(
                                                     pkg.applicationInfo.dataDir, newNativePath) < 0) {
                                                 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
                                             }
                                         }
-                                    } catch (IOException e) {
-                                        returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
+                                        NativeLibraryHelper.copyNativeBinariesIfNeededLI(new File(
+                                                newCodePath), newNativeDir);
+                                    } else {
+                                        synchronized (mInstallLock) {
+                                            if (mInstaller.linkNativeLibraryDirectory(
+                                                    pkg.applicationInfo.dataDir, newNativePath) < 0) {
+                                                returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
+                                            }
+                                        }
                                     }
 
-
                                     if (returnCode == PackageManager.MOVE_SUCCEEDED) {
                                         pkg.mPath = newCodePath;
                                         // Move dex files around
@@ -9415,48 +10032,37 @@
                 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);
-        }
-        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) {
+    /** Called by UserManagerService */
+    void cleanUpUserLILPw(int userHandle) {
         // 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);
+        Set<Entry<String, PackageSetting>> entries = mSettings.mPackages.entrySet();
+        for (Entry<String, PackageSetting> entry : entries) {
+            entry.getValue().removeUser(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);
+        }
+    }
+
+    /** Called by UserManagerService */
+    void createNewUserLILPw(int userHandle, File path) {
+        if (mInstaller != null) {
+            path.mkdir();
+            FileUtils.setPermissions(path.toString(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
+                    | FileUtils.S_IXOTH, -1, -1);
+            for (PackageSetting ps : mSettings.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.
+                mInstaller.createUserData(ps.name,
+                        UserHandle.getUid(userHandle, ps.appId), userHandle);
             }
-            if (mDirtyUsers.remove(userId));
-            mSettings.removeUserLPr(userId);
+            mSettings.writePackageRestrictionsLPr(userHandle);
         }
     }
 
@@ -9472,24 +10078,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)) {
diff --git a/services/java/com/android/server/pm/PackageSettingBase.java b/services/java/com/android/server/pm/PackageSettingBase.java
index 56f2166..d8f7345 100644
--- a/services/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/java/com/android/server/pm/PackageSettingBase.java
@@ -20,11 +20,13 @@
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
 
+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 +64,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 +109,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 +164,174 @@
         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);
+        return state != null ? state : 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 +339,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..5539e84 100644
--- a/services/java/com/android/server/pm/PreferredActivity.java
+++ b/services/java/com/android/server/pm/PreferredActivity.java
@@ -33,22 +33,38 @@
     private static final String TAG = "PreferredActivity";
 
     private static final boolean DEBUG_FILTERS = false;
+    static final String ATTR_USER_ID = "userId";
 
     final PreferredComponent mPref;
+    final int mUserId;
 
     PreferredActivity(IntentFilter filter, int match, ComponentName[] set, ComponentName activity) {
+        this(filter, match, set, activity, 0);
+    }
+
+    PreferredActivity(IntentFilter filter, int match, ComponentName[] set, ComponentName activity,
+            int userId) {
         super(filter);
+        mUserId = userId;
         mPref = new PreferredComponent(this, match, set, activity);
     }
 
     PreferredActivity(XmlPullParser parser) throws XmlPullParserException, IOException {
+        String userIdString = parser.getAttributeValue(null, ATTR_USER_ID);
+        if (userIdString != null && userIdString.length() > 0) {
+            mUserId = Integer.parseInt(userIdString);
+        } else {
+            // Old format with no userId specified - assume primary user
+            mUserId = 0;
+        }
         mPref = new PreferredComponent(this, parser);
     }
 
     public void writeToXml(XmlSerializer serializer) throws IOException {
+        serializer.attribute(null, ATTR_USER_ID, Integer.toString(mUserId));
         mPref.writeToXml(serializer);
         serializer.startTag(null, "filter");
-        super.writeToXml(serializer);
+            super.writeToXml(serializer);
         serializer.endTag(null, "filter");
     }
 
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 120b650..b075da3 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;
@@ -79,6 +80,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 +92,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;
@@ -121,6 +126,10 @@
     final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
                 new IntentResolver<PreferredActivity, PreferredActivity>() {
         @Override
+        protected PreferredActivity[] newArray(int size) {
+            return new PreferredActivity[size];
+        }
+        @Override
         protected String packageForFilter(PreferredActivity filter) {
             return filter.mPref.mComponent.getPackageName();
         }
@@ -150,7 +159,8 @@
 
     // Packages that have been uninstalled and still need their external
     // storage data deleted.
-    final ArrayList<String> mPackagesToBeCleaned = new ArrayList<String>();
+    final SparseArray<ArrayList<PackageCleanItem>> mPackagesToBeCleaned
+            = new SparseArray<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 +179,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 +204,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);
         return p;
     }
 
@@ -355,7 +369,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) {
         PackageSetting p = mPackages.get(name);
         if (p != null) {
             if (!p.codePath.equals(codePath)) {
@@ -398,11 +413,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,
@@ -436,8 +446,20 @@
                     List<UserInfo> users = getAllUsers();
                     if (users != null) {
                         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 +485,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 +509,25 @@
                 // user preferences
                 addPackageSettingLPw(p, name, sharedUser);
             }
+        } else {
+            if (installUser != null) {
+                // 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 +566,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) {
@@ -704,13 +747,12 @@
     }
 
     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() {
@@ -735,6 +777,9 @@
     }
 
     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 +811,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 +860,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 +886,14 @@
                         }
                         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 {
                     Slog.w(PackageManagerService.TAG, "Unknown element under <stopped-packages>: "
                           + parser.getName());
@@ -864,7 +918,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 +933,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);
                 }
             }
@@ -887,6 +944,9 @@
     }
 
     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 +981,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);
@@ -1194,9 +1258,17 @@
 
             if (mPackagesToBeCleaned.size() > 0) {
                 for (int i=0; i<mPackagesToBeCleaned.size(); i++) {
-                    serializer.startTag(null, "cleaning-package");
-                    serializer.attribute(null, ATTR_NAME, mPackagesToBeCleaned.get(i));
-                    serializer.endTag(null, "cleaning-package");
+                    final int userId = mPackagesToBeCleaned.keyAt(i);
+                    final String userStr = Integer.toString(userId);
+                    final ArrayList<PackageCleanItem> pkgs = mPackagesToBeCleaned.valueAt(i);
+                    for (int j=0; j<pkgs.size(); j++) {
+                        serializer.startTag(null, "cleaning-package");
+                        PackageCleanItem item = pkgs.get(j);
+                        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");
+                    }
                 }
             }
             
@@ -1452,6 +1524,17 @@
         return ret;
     }
 
+    void addPackageToCleanLPw(int userId, PackageCleanItem pkg) {
+        ArrayList<PackageCleanItem> pkgs = mPackagesToBeCleaned.get(userId);
+        if (pkgs == null) {
+            pkgs = new ArrayList<PackageCleanItem>();
+            mPackagesToBeCleaned.put(userId, pkgs);
+        }
+        if (!pkgs.contains(pkg)) {
+            pkgs.add(pkg);
+        }
+    }
+
     boolean readLPw(List<UserInfo> users) {
         FileInputStream str = null;
         if (mBackupSettingsFilename.exists()) {
@@ -1529,8 +1612,21 @@
                     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 user = 0;
+                        boolean andCode = true;
+                        try {
+                            if (userStr != null) {
+                                user = Integer.parseInt(userStr);
+                            }
+                        } catch (NumberFormatException e) {
+                        }
+                        if (codeStr != null) {
+                            andCode = Boolean.parseBoolean(codeStr);
+                        }
+                        addPackageToCleanLPw(user, new PackageCleanItem(name, andCode));
                     }
                 } else if (tagName.equals("renamed-package")) {
                     String nname = parser.getAttributeValue(null, "new");
@@ -1580,7 +1676,24 @@
             mReadMessages.append("Error reading: " + e.toString());
             PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
             Log.wtf(PackageManagerService.TAG, "Error reading package manager settings", e);
+        }
 
+        if (mBackupStoppedPackagesFilename.exists()
+                || mStoppedPackagesFilename.exists()) {
+            // Read old file
+            readStoppedLPw();
+            mBackupStoppedPackagesFilename.delete();
+            mStoppedPackagesFilename.delete();
+            // Migrate to new file format
+            writePackageRestrictionsLPr(0);
+        } else {
+            if (users == null) {
+                readPackageRestrictionsLPr(0);
+            } else {
+                for (UserInfo user : users) {
+                    readPackageRestrictionsLPr(user.id);
+                }
+            }
         }
 
         final int N = mPendingPackages.size();
@@ -1590,7 +1703,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,
+                        UserHandle.ALL, true);
                 if (p == null) {
                     PackageManagerService.reportSettingsProblem(Log.WARN,
                             "Unable to create application package for " + pp.name);
@@ -1624,23 +1738,6 @@
             }
         }
 
-        if (mBackupStoppedPackagesFilename.exists()
-                || mStoppedPackagesFilename.exists()) {
-            // Read old file
-            readStoppedLPw();
-            mBackupStoppedPackagesFilename.delete();
-            mStoppedPackagesFilename.delete();
-            // Migrate to new file format
-            writePackageRestrictionsLPr(0);
-        } else {
-            if (users == null) {
-                readPackageRestrictionsLPr(0);
-            } else {
-                for (UserInfo user : users) {
-                    readPackageRestrictionsLPr(user.id);
-                }
-            }
-        }
         mReadMessages.append("Read completed successfully: " + mPackages.size() + " packages, "
                 + mSharedUsers.size() + " shared uids\n");
 
@@ -2276,6 +2373,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 +2387,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 +2440,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 +2465,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 +2477,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();
         } catch (NullPointerException npe) {
             // packagemanager not yet initialized
         } finally {
@@ -2413,7 +2514,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 +2605,8 @@
                     first = false;
                     pw.print("anyDensity");
                 }
+                pw.println("]");
             }
-            pw.println("]");
             pw.print("    timeStamp=");
                 date.setTime(ps.timeStamp);
                 pw.println(sdf.format(date));
@@ -2520,25 +2620,31 @@
                 pw.print("    installerPackageName="); pw.println(ps.installerPackageName);
             }
             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("    permissionsFixed="); pw.println(ps.permissionsFixed);
+            pw.print("    haveGids="); pw.println(ps.haveGids);
+            pw.print("    pkgFlags="); printFlags(pw, ps.pkgFlags, FLAG_DUMP_SPEC);
+            pw.print("    installStatus="); pw.println(ps.installStatus);
             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..be86628
--- /dev/null
+++ b/services/java/com/android/server/pm/UserManagerService.java
@@ -0,0 +1,723 @@
+/*
+ * 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 static android.os.ParcelFileDescriptor.MODE_CREATE;
+import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
+
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.FastXmlSerializer;
+
+import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
+import android.app.IStopUserCallback;
+import android.content.Context;
+import android.content.Intent;
+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.ParcelFileDescriptor;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.AtomicFile;
+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.FileNotFoundException;
+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 UserManagerService extends IUserManager.Stub {
+
+    private static final String LOG_TAG = "UserManagerService";
+
+    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_SERIAL_NO = "serialNumber";
+    private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber";
+    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 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 final int mUserLimit;
+
+    private int[] mUserIds;
+    private boolean mGuestEnabled;
+    private int mNextSerialNumber;
+
+    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) {
+        synchronized (UserManagerService.class) {
+            mContext = context;
+            mPm = pm;
+            mInstallLock = installLock;
+            mPackagesLock = packagesLock;
+            mUserLimit = mContext.getResources().getInteger(
+                    com.android.internal.R.integer.config_multiuserMaximumUsers);
+            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();
+            sInstance = this;
+        }
+    }
+
+    @Override
+    public List<UserInfo> getUsers() {
+        checkManageUsersPermission("query users");
+        synchronized (mPackagesLock) {
+            ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
+            for (int i = 0; i < mUsers.size(); i++) {
+                users.add(mUsers.valueAt(i));
+            }
+            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) {
+        return mUsers.get(userId);
+    }
+
+    public boolean exists(int userId) {
+        synchronized (mPackagesLock) {
+            return ArrayUtils.contains(mUserIds, userId);
+        }
+    }
+
+    @Override
+    public void setUserName(int userId, String name) {
+        checkManageUsersPermission("rename users");
+        synchronized (mPackagesLock) {
+            UserInfo info = mUsers.get(userId);
+            if (name != null && !name.equals(info.name)) {
+                info.name = name;
+                writeUserLocked(info);
+            }
+        }
+        sendUserInfoChangedBroadcast(userId);
+    }
+
+    @Override
+    public void setUserIcon(int userId, Bitmap bitmap) {
+        checkManageUsersPermission("update users");
+        synchronized (mPackagesLock) {
+            UserInfo info = mUsers.get(userId);
+            if (info == null) 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.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.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.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 >= mUserLimit;
+    }
+
+    /**
+     * 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);
+                }
+            }
+
+            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();
+        } 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", null,
+                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;
+        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));
+            if (userInfo.iconPath != null) {
+                serializer.attribute(null,  ATTR_ICON_PATH, userInfo.iconPath);
+            }
+
+            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));
+
+            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;
+
+        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)) {
+                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 serialNumberValue = parser.getAttributeValue(null, ATTR_SERIAL_NO);
+                if (serialNumberValue != null) {
+                    serialNumber = Integer.parseInt(serialNumberValue);
+                }
+                String flagString = parser.getAttributeValue(null, ATTR_FLAGS);
+                flags = Integer.parseInt(flagString);
+                iconPath = parser.getAttributeValue(null, ATTR_ICON_PATH);
+
+                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;
+            return userInfo;
+
+        } catch (IOException ioe) {
+        } catch (XmlPullParserException pe) {
+        } finally {
+            if (fis != null) {
+                try {
+                    fis.close();
+                } catch (IOException e) {
+                }
+            }
+        }
+        return null;
+    }
+
+    @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++;
+                    mUsers.put(userId, userInfo);
+                    writeUserListLocked();
+                    writeUserLocked(userInfo);
+                    updateUserIdsLocked();
+                    mPm.createNewUserLILPw(userId, userPath);
+                }
+            }
+            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;
+            }
+        }
+
+        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(int userHandle) {
+        synchronized (mInstallLock) {
+            synchronized (mPackagesLock) {
+                // Cleanup package manager settings
+                mPm.cleanUpUserLILPw(userHandle);
+
+                // Remove this user from the list
+                mUsers.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));
+            }
+        }
+
+        // Let other services shutdown any activity
+        long ident = Binder.clearCallingIdentity();
+        try {
+            Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED);
+            addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userHandle);
+            mContext.sendBroadcastAsUser(addedIntent, UserHandle.ALL,
+                    android.Manifest.permission.MANAGE_USERS);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    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[] newUsers = new int[mUsers.size()];
+        for (int i = 0; i < mUsers.size(); i++) {
+            newUsers[i] = mUsers.keyAt(i);
+        }
+        mUserIds = newUsers;
+    }
+
+    /**
+     * 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 = 10;
+            while (i < Integer.MAX_VALUE) {
+                if (mUsers.indexOfKey(i) < 0) {
+                    break;
+                }
+                i++;
+            }
+            return i;
+        }
+    }
+}
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..5f4a786
--- /dev/null
+++ b/services/java/com/android/server/power/DisplayPowerController.java
@@ -0,0 +1,1160 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.AsyncTask;
+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;
+import java.io.StringWriter;
+import java.util.concurrent.Executor;
+
+/**
+ * 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;
+
+    // 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 = true;
+
+    // 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 = 450;
+
+    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.
+    private static final int PROXIMITY_SENSOR_DEBOUNCE_DELAY = 250;
+
+    // Trigger proximity if distance is less than 5 cm.
+    private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;
+
+    // Light sensor event rate in microseconds.
+    private static final int LIGHT_SENSOR_RATE = 1000000;
+
+    // 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;
+
+    // Filter time constant in milliseconds for computing a moving
+    // average of light samples.  Different constants are used
+    // to calculate the average light level when adapting to brighter or
+    // dimmer environments.
+    // This parameter only controls the filtering of light samples.
+    private static final long BRIGHTENING_LIGHT_TIME_CONSTANT = 600;
+    private static final long DIMMING_LIGHT_TIME_CONSTANT = 4000;
+
+    // Stability requirements in milliseconds for accepting a new brightness
+    // level.  This is used for debouncing the light sensor.  Different constants
+    // are used to debounce the light sensor when adapting to brighter or dimmer
+    // environments.
+    // This parameter controls how quickly brightness changes occur in response to
+    // an observed change in light level.
+    private static final long BRIGHTENING_LIGHT_DEBOUNCE = 2500;
+    private static final long DIMMING_LIGHT_DEBOUNCE = 10000;
+
+    private final Object mLock = new Object();
+
+    // Notifier for sending asynchronous notifications.
+    private final Notifier mNotifier;
+
+    // A suspend blocker.
+    private final SuspendBlocker mSuspendBlocker;
+
+    // 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;
+
+    // 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;
+
+    // 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;
+
+    // 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 average light sensor value.
+    private float mLightMeasurement;
+
+    // True if the light sensor measurement is valid.
+    private boolean mLightMeasurementValid;
+
+    // The number of light sensor samples that have been collected since the
+    // last time a light sensor reading was accepted.
+    private int mRecentLightSamples;
+
+    // The moving average of recent light sensor values.
+    private float mRecentLightAverage;
+
+    // True if recent light samples are getting brighter than the previous
+    // stable light measurement.
+    private boolean mRecentLightBrightening;
+
+    // The time constant to use for filtering based on whether the
+    // light appears to be brightening or dimming.
+    private long mRecentLightTimeConstant;
+
+    // The most recent light sample.
+    private float mLastLightSample;
+
+    // The time of the most light recent sample.
+    private long mLastLightSampleTime;
+
+    // The time when we accumulated the first recent light sample into mRecentLightSamples.
+    private long mFirstRecentLightSampleTime;
+
+    // The upcoming debounce light sensor time.
+    // This is only valid when mLightMeasurementValue && mRecentLightSamples >= 1.
+    private long mPendingLightSensorDebounceTime;
+
+    // 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, SuspendBlocker suspendBlocker,
+            Callbacks callbacks, Handler callbackHandler) {
+        mHandler = new DisplayControllerHandler(looper);
+        mNotifier = notifier;
+        mSuspendBlocker = suspendBlocker;
+        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 = resources.getInteger(
+                com.android.internal.R.integer.config_screenBrightnessDim);
+        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;
+            }
+
+            mLightSensorWarmUpTimeConfig = resources.getInteger(
+                    com.android.internal.R.integer.config_lightSensorWarmupTime);
+        }
+
+        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] = (float)brightness[0] / PowerManager.BRIGHTNESS_ON;
+            for (int i = 1; i < n; i++) {
+                x[i] = lux[i - 1];
+                y[i] = (float)brightness[i] / PowerManager.BRIGHTNESS_ON;
+            }
+
+            Spline spline = Spline.createMonotoneCubicSpline(x, y);
+            if (false) {
+                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() {
+        final Executor executor = AsyncTask.THREAD_POOL_EXECUTOR;
+        Display display = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
+        mPowerState = new DisplayPowerState(new ElectronBeam(display),
+                new PhotonicModulator(executor,
+                        mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT),
+                        mSuspendBlocker));
+
+        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;
+        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;
+                }
+                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;
+                    setScreenOn(false);
+                }
+            } else if (mWaitingForNegativeProximity
+                    && mScreenOffBecauseOfProximity
+                    && mProximity == PROXIMITY_POSITIVE
+                    && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
+                setProximitySensorEnabled(true);
+            } else {
+                setProximitySensorEnabled(false);
+                mWaitingForNegativeProximity = false;
+            }
+            if (mScreenOffBecauseOfProximity
+                    && mProximity != PROXIMITY_POSITIVE) {
+                mScreenOffBecauseOfProximity = false;
+                setScreenOn(true);
+                sendOnProximityNegative();
+            }
+        } else {
+            mWaitingForNegativeProximity = false;
+        }
+
+        // Turn on the light sensor if needed.
+        if (mLightSensor != null) {
+            setLightSensorEnabled(mPowerRequest.useAutoBrightness
+                    && wantScreenOn(mPowerRequest.screenState), updateAutoBrightness);
+        }
+
+        // Set the screen brightness.
+        if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM) {
+            // Screen is dimmed.  Overrides everything else.
+            animateScreenBrightness(
+                    clampScreenBrightness(mScreenBrightnessDimConfig),
+                    BRIGHTNESS_RAMP_RATE_FAST);
+            mUsingScreenAutoBrightness = false;
+        } else if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_BRIGHT) {
+            if (mScreenAutoBrightness >= 0 && mLightSensorEnabled) {
+                // Use current auto-brightness value.
+                animateScreenBrightness(
+                        clampScreenBrightness(mScreenAutoBrightness),
+                        mUsingScreenAutoBrightness ? BRIGHTNESS_RAMP_RATE_SLOW :
+                                BRIGHTNESS_RAMP_RATE_FAST);
+                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.
+                animateScreenBrightness(
+                        clampScreenBrightness(mPowerRequest.screenBrightness),
+                        BRIGHTNESS_RAMP_RATE_FAST);
+                mUsingScreenAutoBrightness = false;
+            }
+        } 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()) {
+                    setScreenOn(true);
+                    if (USE_ELECTRON_BEAM_ON_ANIMATION) {
+                        if (!mElectronBeamOnAnimator.isStarted()) {
+                            if (mPowerState.getElectronBeamLevel() == 1.0f) {
+                                mPowerState.dismissElectronBeam();
+                            } else if (mPowerState.prepareElectronBeam(true)) {
+                                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(false)
+                                && 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
+                && !mElectronBeamOnAnimator.isStarted()
+                && !mElectronBeamOffAnimator.isStarted()
+                && mPowerState.waitUntilClean(mCleanListener)) {
+            synchronized (mLock) {
+                if (!mPendingRequestChangedLocked) {
+                    mDisplayReadyLocked = true;
+                }
+            }
+            sendOnStateChanged();
+        }
+    }
+
+    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 Math.min(Math.max(Math.max(value, mScreenBrightnessDimConfig), 0), 255);
+    }
+
+    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);
+        mPendingProximity = positive ? PROXIMITY_POSITIVE : PROXIMITY_NEGATIVE;
+        mPendingProximityDebounceTime = time + PROXIMITY_SENSOR_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, mHandler);
+            }
+        } else {
+            if (mLightSensorEnabled) {
+                mLightSensorEnabled = false;
+                mLightMeasurementValid = false;
+                mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED);
+                mSensorManager.unregisterListener(mLightSensorListener);
+            }
+        }
+        if (updateAutoBrightness) {
+            updateAutoBrightness(false);
+        }
+    }
+
+    private void handleLightSensorEvent(long time, float lux) {
+        // Take the first few readings during the warm-up period and apply them
+        // immediately without debouncing.
+        if (!mLightMeasurementValid
+                || (time - mLightSensorEnableTime) < mLightSensorWarmUpTimeConfig) {
+            mLightMeasurement = lux;
+            mLightMeasurementValid = true;
+            mRecentLightSamples = 0;
+            updateAutoBrightness(true);
+        }
+
+        // Update our moving average.
+        if (lux != mLightMeasurement && (mRecentLightSamples == 0
+                || (lux < mLightMeasurement && mRecentLightBrightening)
+                || (lux > mLightMeasurement && !mRecentLightBrightening))) {
+            // If the newest light sample doesn't seem to be going in the
+            // same general direction as recent samples, then start over.
+            setRecentLight(time, lux, lux > mLightMeasurement);
+        } else if (mRecentLightSamples >= 1) {
+            // Add the newest light sample to the moving average.
+            accumulateRecentLight(time, lux);
+        }
+        if (DEBUG) {
+            Slog.d(TAG, "handleLightSensorEvent: lux=" + lux
+                    + ", mLightMeasurementValid=" + mLightMeasurementValid
+                    + ", mLightMeasurement=" + mLightMeasurement
+                    + ", mRecentLightSamples=" + mRecentLightSamples
+                    + ", mRecentLightAverage=" + mRecentLightAverage
+                    + ", mRecentLightBrightening=" + mRecentLightBrightening
+                    + ", mRecentLightTimeConstant=" + mRecentLightTimeConstant
+                    + ", mFirstRecentLightSampleTime="
+                            + TimeUtils.formatUptime(mFirstRecentLightSampleTime)
+                    + ", mPendingLightSensorDebounceTime="
+                            + TimeUtils.formatUptime(mPendingLightSensorDebounceTime));
+        }
+
+        // Debounce.
+        mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED);
+        debounceLightSensor();
+    }
+
+    private void setRecentLight(long time, float lux, boolean brightening) {
+        mRecentLightBrightening = brightening;
+        mRecentLightTimeConstant = brightening ?
+                BRIGHTENING_LIGHT_TIME_CONSTANT : DIMMING_LIGHT_TIME_CONSTANT;
+        mRecentLightSamples = 1;
+        mRecentLightAverage = lux;
+        mLastLightSample = lux;
+        mLastLightSampleTime = time;
+        mFirstRecentLightSampleTime = time;
+        mPendingLightSensorDebounceTime = time + (brightening ?
+                BRIGHTENING_LIGHT_DEBOUNCE : DIMMING_LIGHT_DEBOUNCE);
+    }
+
+    private void accumulateRecentLight(long time, float lux) {
+        final long timeDelta = time - mLastLightSampleTime;
+        mRecentLightSamples += 1;
+        mRecentLightAverage += (lux - mRecentLightAverage) *
+                timeDelta / (mRecentLightTimeConstant + timeDelta);
+        mLastLightSample = lux;
+        mLastLightSampleTime = time;
+    }
+
+    private void debounceLightSensor() {
+        if (mLightMeasurementValid && mRecentLightSamples >= 1) {
+            final long now = SystemClock.uptimeMillis();
+            if (mPendingLightSensorDebounceTime <= now) {
+                accumulateRecentLight(now, mLastLightSample);
+                mLightMeasurement = mRecentLightAverage;
+
+                if (DEBUG) {
+                    Slog.d(TAG, "debounceLightSensor: Accepted new measurement "
+                            + mLightMeasurement + " after "
+                            + (now - mFirstRecentLightSampleTime) + " ms based on "
+                            + mRecentLightSamples + " recent samples.");
+                }
+
+                updateAutoBrightness(true);
+
+                // Now that we have debounced the light sensor data, we have the
+                // option of either leaving the sensor in a debounced state or
+                // restarting the debounce cycle by setting mRecentLightSamples to 0.
+                //
+                // If we leave the sensor debounced, then new average light measurements
+                // may be accepted immediately as long as they are trending in the same
+                // direction as they were before.  If the measurements start
+                // jittering or trending in the opposite direction then the debounce
+                // cycle will automatically be restarted.  The benefit is that the
+                // auto-brightness control can be more responsive to changes over a
+                // broad range.
+                //
+                // For now, we choose to be more responsive and leave the following line
+                // commented out.
+                //
+                // mRecentLightSamples = 0;
+            } else {
+                Message msg = mHandler.obtainMessage(MSG_LIGHT_SENSOR_DEBOUNCED);
+                msg.setAsynchronous(true);
+                mHandler.sendMessageAtTime(msg, mPendingLightSensorDebounceTime);
+            }
+        }
+    }
+
+    private void updateAutoBrightness(boolean sendUpdate) {
+        if (!mLightMeasurementValid) {
+            return;
+        }
+
+        float value = mScreenAutoBrightnessSpline.interpolate(mLightMeasurement);
+        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(
+                (int)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 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("  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("  mLightMeasurement=" + mLightMeasurement);
+        pw.println("  mLightMeasurementValid=" + mLightMeasurementValid);
+        pw.println("  mLastLightSample=" + mLastLightSample);
+        pw.println("  mLastLightSampleTime="
+                + TimeUtils.formatUptime(mLastLightSampleTime));
+        pw.println("  mRecentLightSamples=" + mRecentLightSamples);
+        pw.println("  mRecentLightAverage=" + mRecentLightAverage);
+        pw.println("  mRecentLightBrightening=" + mRecentLightBrightening);
+        pw.println("  mRecentLightTimeConstant=" + mRecentLightTimeConstant);
+        pw.println("  mFirstRecentLightSampleTime="
+                + TimeUtils.formatUptime(mFirstRecentLightSampleTime));
+        pw.println("  mPendingLightSensorDebounceTime="
+                + TimeUtils.formatUptime(mPendingLightSensorDebounceTime));
+        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 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..2d74292
--- /dev/null
+++ b/services/java/com/android/server/power/DisplayPowerRequest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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;
+
+    public DisplayPowerRequest() {
+        screenState = SCREEN_STATE_BRIGHT;
+        useProximitySensor = false;
+        screenBrightness = PowerManager.BRIGHTNESS_ON;
+        screenAutoBrightnessAdjustment = 0.0f;
+        useAutoBrightness = 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;
+    }
+
+    @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;
+    }
+
+    @Override
+    public int hashCode() {
+        return 0; // don't care
+    }
+
+    @Override
+    public String toString() {
+        return "screenState=" + screenState
+                + ", useProximitySensor=" + useProximitySensor
+                + ", screenBrightness=" + screenBrightness
+                + ", screenAutoBrightnessAdjustment=" + screenAutoBrightnessAdjustment
+                + ", useAutoBrightness=" + useAutoBrightness;
+    }
+}
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..1bd7811
--- /dev/null
+++ b/services/java/com/android/server/power/DisplayPowerState.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.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;
+
+/**
+ * Represents the current display power state and realizes it.
+ *
+ * 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 the {@link Choreographer} to
+ * apply the changes.  This mechanism enables the display power state to be
+ * animated smoothly by the animation framework.
+ *
+ * This component must only be created or accessed by the {@link Looper} thread
+ * that belongs to the {@link DisplayPowerController}.
+ *
+ * We don't need to worry about holding a suspend blocker here because the
+ * {@link DisplayPowerController} does that for us whenever there is a pending invalidate.
+ */
+final class DisplayPowerState {
+    private static final String TAG = "DisplayPowerState";
+
+    private static boolean DEBUG = false;
+
+    private static final int DIRTY_SCREEN_ON = 1 << 0;
+    private static final int DIRTY_ELECTRON_BEAM = 1 << 1;
+    private static final int DIRTY_BRIGHTNESS = 1 << 2;
+
+    private final Choreographer mChoreographer;
+    private final ElectronBeam mElectronBeam;
+    private final PhotonicModulator mScreenBrightnessModulator;
+
+    private int mDirty;
+    private boolean mScreenOn;
+    private float mElectronBeamLevel;
+    private int mScreenBrightness;
+
+    private Runnable mCleanListener;
+
+    public DisplayPowerState(ElectronBeam electronBean,
+            PhotonicModulator screenBrightnessModulator) {
+        mChoreographer = Choreographer.getInstance();
+        mElectronBeam = electronBean;
+        mScreenBrightnessModulator = screenBrightnessModulator;
+
+        // 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;
+        mElectronBeamLevel = 1.0f;
+        mScreenBrightness = PowerManager.BRIGHTNESS_ON;
+        invalidate(DIRTY_BRIGHTNESS);
+    }
+
+    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;
+            invalidate(DIRTY_SCREEN_ON);
+        }
+    }
+
+    /**
+     * Returns true if the screen is on.
+     */
+    public boolean isScreenOn() {
+        return mScreenOn;
+    }
+
+    /**
+     * 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 warmUp True if the electron beam should start warming up.
+     * @return True if the electron beam was prepared.
+     */
+    public boolean prepareElectronBeam(boolean warmUp) {
+        boolean success = mElectronBeam.prepare(warmUp);
+        invalidate(DIRTY_ELECTRON_BEAM);
+        return success;
+    }
+
+    /**
+     * Dismisses the electron beam surface.
+     */
+    public void dismissElectronBeam() {
+        mElectronBeam.dismiss();
+    }
+
+    /**
+     * 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;
+            invalidate(DIRTY_ELECTRON_BEAM);
+        }
+    }
+
+    /**
+     * Gets the level of the electron beam steering current.
+     */
+    public float getElectronBeamLevel() {
+        return mElectronBeamLevel;
+    }
+
+    /**
+     * 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;
+            invalidate(DIRTY_BRIGHTNESS);
+        }
+    }
+
+    /**
+     * Gets the screen brightness.
+     */
+    public int getScreenBrightness() {
+        return mScreenBrightness;
+    }
+
+    /**
+     * 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 (mDirty != 0) {
+            mCleanListener = listener;
+            return false;
+        } else {
+            mCleanListener = null;
+            return true;
+        }
+    }
+
+    public void dump(PrintWriter pw) {
+        pw.println();
+        pw.println("Display Power State:");
+        pw.println("  mDirty=" + Integer.toHexString(mDirty));
+        pw.println("  mScreenOn=" + mScreenOn);
+        pw.println("  mScreenBrightness=" + mScreenBrightness);
+        pw.println("  mElectronBeamLevel=" + mElectronBeamLevel);
+
+        mElectronBeam.dump(pw);
+    }
+
+    private void invalidate(int dirty) {
+        if (mDirty == 0) {
+            mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL,
+                    mTraversalRunnable, null);
+        }
+
+        mDirty |= dirty;
+    }
+
+    private void apply() {
+        if (mDirty != 0) {
+            if ((mDirty & DIRTY_SCREEN_ON) != 0 && !mScreenOn) {
+                mScreenBrightnessModulator.setBrightness(0, true /*sync*/);
+                PowerManagerService.nativeSetScreenState(false);
+            }
+
+            if ((mDirty & DIRTY_ELECTRON_BEAM) != 0) {
+                mElectronBeam.draw(mElectronBeamLevel);
+            }
+
+            if ((mDirty & DIRTY_SCREEN_ON) != 0 && mScreenOn) {
+                PowerManagerService.nativeSetScreenState(true);
+            }
+
+            if ((mDirty & (DIRTY_BRIGHTNESS | DIRTY_SCREEN_ON | DIRTY_ELECTRON_BEAM)) != 0
+                    && mScreenOn) {
+                mScreenBrightnessModulator.setBrightness(
+                        (int)(mScreenBrightness * mElectronBeamLevel), false /*sync*/);
+            }
+
+            mDirty = 0;
+
+            if (mCleanListener != null) {
+                mCleanListener.run();
+            }
+        }
+    }
+
+    private final Runnable mTraversalRunnable = new Runnable() {
+        @Override
+        public void run() {
+            if (mDirty != 0) {
+                apply();
+            }
+        }
+    };
+}
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..0c68997
--- /dev/null
+++ b/services/java/com/android/server/power/ElectronBeam.java
@@ -0,0 +1,653 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.os.Process;
+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*
+ *
+ * Animates a screen transition from on to off or off to on by applying
+ * some GL transformations to a screenshot.
+ *
+ * This component must only be created or accessed by the {@link Looper} thread
+ * that belongs to the {@link DisplayPowerController}.
+ */
+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.4f;
+    private static final float VSTRETCH_DURATION = 1.0f - HSTRETCH_DURATION;
+
+    // Set to true when the animation context has been fully prepared.
+    private boolean mPrepared;
+    private boolean mWarmUp;
+
+    private final Display mDisplay;
+    private final DisplayInfo mDisplayInfo = new DisplayInfo();
+    private int mDisplayLayerStack; // layer stack associated with primary display
+    private int mDisplayRotation;
+    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;
+
+    // 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);
+
+    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 warmUp True if the electron beam is about to be turned on, false if
+     * it is about to be turned off.
+     * @return True if the electron beam is ready, false if it is uncontrollable.
+     */
+    public boolean prepare(boolean warmUp) {
+        if (DEBUG) {
+            Slog.d(TAG, "prepare: warmUp=" + warmUp);
+        }
+
+        mWarmUp = warmUp;
+
+        // 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 (!createEglContext()
+                || !createEglSurface()
+                || !captureScreenshotTextureAndSetViewport()) {
+            dismiss();
+            return false;
+        }
+
+        mPrepared = true;
+        return true;
+    }
+
+    /**
+     * 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();
+        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 (!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 showEglSurface();
+    }
+
+    /**
+     * 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,
+                mWarmUp ? 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 (!mWarmUp) {
+            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 createEglSurface() {
+        if (mSurfaceSession == null) {
+            mSurfaceSession = new SurfaceSession();
+        }
+
+        Surface.openTransaction();
+        try {
+            if (mSurface == null) {
+                try {
+                    mSurface = new Surface(mSurfaceSession,
+                            "ElectronBeam", mDisplayWidth, mDisplayHeight,
+                            PixelFormat.OPAQUE, Surface.OPAQUE | Surface.HIDDEN);
+                } 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();
+        }
+
+        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;
+        }
+
+        if (mSurface != null) {
+            Surface.openTransaction();
+            try {
+                mSurface.destroy();
+            } finally {
+                Surface.closeTransaction();
+            }
+            mSurface = null;
+            mSurfaceVisible = false;
+        }
+    }
+
+    private boolean showEglSurface() {
+        if (!mSurfaceVisible) {
+            Surface.openTransaction();
+            try {
+                mSurface.setLayer(ELECTRON_BEAM_LAYER);
+                mSurface.show();
+            } finally {
+                Surface.closeTransaction();
+            }
+            mSurfaceVisible = true;
+        }
+        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("  mWarmUp=" + mWarmUp);
+        pw.println("  mDisplayLayerStack=" + mDisplayLayerStack);
+        pw.println("  mDisplayRotation=" + mDisplayRotation);
+        pw.println("  mDisplayWidth=" + mDisplayWidth);
+        pw.println("  mDisplayHeight=" + mDisplayHeight);
+        pw.println("  mSurfaceVisible=" + mSurfaceVisible);
+    }
+}
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..ce1e147
--- /dev/null
+++ b/services/java/com/android/server/power/Notifier.java
@@ -0,0 +1,442 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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;
+import android.view.WindowManagerPolicy.ScreenOnListener;
+
+/**
+ * Sends broadcasts about important power state changes.
+ *
+ * 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.
+ *
+ * The notifier is designed to collapse unnecessary broadcasts when it is not
+ * possible for the system to have observed an intermediate state.
+ *
+ * For example, if the device wakes up, goes to sleep and wakes up again immediately
+ * before the go to sleep broadcast has been sent, then no broadcast will be
+ * sent about the system going to sleep and waking up.
+ */
+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 WindowManagerPolicy mPolicy;
+    private final ScreenOnListener mScreenOnListener;
+
+    private final NotifierHandler mHandler;
+    private final Intent mScreenOnIntent;
+    private final Intent mScreenOffIntent;
+
+    // The current power state.
+    private int mActualPowerState;
+    private int mLastGoToSleepReason;
+
+    // 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;
+
+    public Notifier(Looper looper, Context context, IBatteryStats batteryStats,
+            SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
+            ScreenOnListener screenOnListener) {
+        mContext = context;
+        mBatteryStats = batteryStats;
+        mSuspendBlocker = suspendBlocker;
+        mPolicy = policy;
+        mScreenOnListener = screenOnListener;
+
+        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;
+                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;
+                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
+                && mActualPowerState != mBroadcastedPowerState) {
+            mBroadcastInProgress = true;
+            mSuspendBlocker.acquire();
+            Message msg = mHandler.obtainMessage(MSG_BROADCAST);
+            msg.setAsynchronous(true);
+            mHandler.sendMessage(msg);
+        }
+    }
+
+    private void sendUserActivity() {
+        synchronized (mLock) {
+            if (!mUserActivityPending) {
+                return;
+            }
+            mUserActivityPending = false;
+        }
+
+        mPolicy.userActivity();
+    }
+
+    private void sendNextBroadcast() {
+        final int powerState;
+        final int goToSleepReason;
+        synchronized (mLock) {
+            if (mActualPowerState == POWER_STATE_UNKNOWN
+                    || mActualPowerState == mBroadcastedPowerState) {
+                mBroadcastInProgress = false;
+                mSuspendBlocker.release();
+                return;
+            }
+
+            powerState = mActualPowerState;
+            goToSleepReason = mLastGoToSleepReason;
+
+            mBroadcastedPowerState = powerState;
+            mBroadcastStartTime = SystemClock.uptimeMillis();
+        }
+
+        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 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/PhotonicModulator.java b/services/java/com/android/server/power/PhotonicModulator.java
new file mode 100644
index 0000000..c9b5d90
--- /dev/null
+++ b/services/java/com/android/server/power/PhotonicModulator.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.server.power;
+
+import com.android.server.LightsService;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Sets the value of a light asynchronously.
+ *
+ * This is done to avoid blocking the looper on devices for which
+ * setting the backlight brightness is especially slow.
+ */
+final class PhotonicModulator {
+    private static final int UNKNOWN_LIGHT_VALUE = -1;
+
+    private final Object mLock = new Object();
+
+    private final LightsService.Light mLight;
+    private final Executor mExecutor;
+    private final SuspendBlocker mSuspendBlocker;
+
+    private boolean mPendingChange;
+    private int mPendingLightValue;
+    private int mActualLightValue;
+
+    public PhotonicModulator(Executor executor, LightsService.Light light,
+            SuspendBlocker suspendBlocker) {
+        mExecutor = executor;
+        mLight = light;
+        mSuspendBlocker = suspendBlocker;
+        mPendingLightValue = UNKNOWN_LIGHT_VALUE;
+        mActualLightValue = UNKNOWN_LIGHT_VALUE;
+    }
+
+    /**
+     * Sets the backlight brightness, synchronously or asynchronously.
+     *
+     * @param lightValue The new light value, from 0 to 255.
+     * @param sync If true, waits for the brightness change to complete before returning.
+     */
+    public void setBrightness(int lightValue, boolean sync) {
+        synchronized (mLock) {
+            if (lightValue != mPendingLightValue) {
+                mPendingLightValue = lightValue;
+                if (!mPendingChange) {
+                    mPendingChange = true;
+                    mSuspendBlocker.acquire();
+                    mExecutor.execute(mTask);
+                }
+            }
+            if (sync) {
+                while (mPendingChange) {
+                    try {
+                        mLock.wait();
+                    } catch (InterruptedException ex) {
+                        // ignore it
+                    }
+                }
+            }
+        }
+    }
+
+    private final Runnable mTask = new Runnable() {
+        @Override
+        public void run() {
+            for (;;) {
+                final int newLightValue;
+                synchronized (mLock) {
+                    newLightValue = mPendingLightValue;
+                    if (newLightValue == mActualLightValue) {
+                        mSuspendBlocker.release();
+                        mPendingChange = false;
+                        mLock.notifyAll();
+                        return;
+                    }
+                    mActualLightValue = newLightValue;
+                }
+                mLight.setBrightness(newLightValue);
+            }
+        }
+    };
+}
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..fda619c
--- /dev/null
+++ b/services/java/com/android/server/power/PowerManagerService.java
@@ -0,0 +1,2122 @@
+/*
+ * 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 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.ServiceManager;
+import android.os.SystemClock;
+import android.os.WorkSource;
+import android.provider.Settings;
+import android.service.dreams.IDreamManager;
+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;
+
+    // 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;
+
+    // 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.
+    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;
+
+    // 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 seconds.
+    // 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;
+
+    private Context mContext;
+    private LightsService mLightsService;
+    private BatteryService mBatteryService;
+    private IBatteryStats mBatteryStats;
+    private HandlerThread mHandlerThread;
+    private PowerManagerHandler mHandler;
+    private WindowManagerPolicy mPolicy;
+    private Notifier mNotifier;
+    private DisplayPowerController mDisplayPowerController;
+    private SettingsObserver mSettingsObserver;
+    private IDreamManager 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;
+
+    // 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;
+
+    // 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;
+
+    // True if dreams are enabled by the user.
+    private boolean mDreamsEnabledSetting;
+
+    // True if dreams should be activated on sleep.
+    private boolean mDreamsActivateOnSleepSetting;
+
+    // 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;
+
+    // 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 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;
+
+    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);
+
+    static native void nativeSetScreenState(boolean on);
+
+    public PowerManagerService() {
+        synchronized (mLock) {
+            mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService");
+            mWakeLockSuspendBlocker.acquire();
+            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) {
+        // 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.
+        nativeSetScreenState(true);
+
+        mContext = context;
+        mLightsService = ls;
+        mBatteryService = bs;
+        mBatteryStats = bss;
+        mHandlerThread = new HandlerThread(TAG);
+        mHandlerThread.start();
+        mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
+
+        Watchdog.getInstance().addMonitor(this);
+    }
+
+    public void setPolicy(WindowManagerPolicy policy) {
+        synchronized (mLock) {
+            mPolicy = policy;
+        }
+    }
+
+    public void systemReady(TwilightService twilight) {
+        synchronized (mLock) {
+            mSystemReady = true;
+
+            PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
+            mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();
+            mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
+            mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();
+
+            mNotifier = new Notifier(mHandler.getLooper(), mContext, mBatteryStats,
+                    createSuspendBlockerLocked("PowerManagerService.Broadcasts"),
+                    mPolicy, mScreenOnListener);
+            mDisplayPowerController = new DisplayPowerController(mHandler.getLooper(),
+                    mContext, mNotifier, mLightsService, twilight,
+                    createSuspendBlockerLocked("PowerManagerService.Display"),
+                    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);
+
+            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);
+
+            // Register for settings changes.
+            final ContentResolver resolver = mContext.getContentResolver();
+            resolver.registerContentObserver(Settings.Secure.getUriFor(
+                    Settings.Secure.SCREENSAVER_ENABLED), false, mSettingsObserver);
+            resolver.registerContentObserver(Settings.Secure.getUriFor(
+                    Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP), false, mSettingsObserver);
+            resolver.registerContentObserver(Settings.System.getUriFor(
+                    Settings.System.SCREEN_OFF_TIMEOUT), false, mSettingsObserver);
+            resolver.registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Global.STAY_ON_WHILE_PLUGGED_IN), false, mSettingsObserver);
+            resolver.registerContentObserver(Settings.System.getUriFor(
+                    Settings.System.SCREEN_BRIGHTNESS), false, mSettingsObserver);
+            resolver.registerContentObserver(Settings.System.getUriFor(
+                    Settings.System.SCREEN_BRIGHTNESS_MODE), false, mSettingsObserver);
+
+            // 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_enableDreams);
+    }
+
+    private void updateSettingsLocked() {
+        final ContentResolver resolver = mContext.getContentResolver();
+
+        mDreamsEnabledSetting = (Settings.Secure.getInt(resolver,
+                Settings.Secure.SCREENSAVER_ENABLED, 0) != 0);
+        mDreamsActivateOnSleepSetting = (Settings.Secure.getInt(resolver,
+                Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 0) != 0);
+        mScreenOffTimeoutSetting = Settings.System.getInt(resolver,
+                Settings.System.SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT);
+        mStayOnWhilePluggedInSetting = Settings.Global.getInt(resolver,
+                Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
+                BatteryManager.BATTERY_PLUGGED_AC);
+
+        final int oldScreenBrightnessSetting = mScreenBrightnessSetting;
+        mScreenBrightnessSetting = Settings.System.getInt(resolver,
+                Settings.System.SCREEN_BRIGHTNESS, mScreenBrightnessSettingDefault);
+        if (oldScreenBrightnessSetting != mScreenBrightnessSetting) {
+            mTemporaryScreenBrightnessSettingOverride = -1;
+        }
+
+        final float oldScreenAutoBrightnessAdjustmentSetting =
+                mScreenAutoBrightnessAdjustmentSetting;
+        mScreenAutoBrightnessAdjustmentSetting = Settings.System.getFloat(resolver,
+                Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.0f);
+        if (oldScreenAutoBrightnessAdjustmentSetting != mScreenAutoBrightnessAdjustmentSetting) {
+            mTemporaryScreenAutoBrightnessAdjustmentSettingOverride = Float.NaN;
+        }
+
+        mScreenBrightnessModeSetting = Settings.System.getInt(resolver,
+                Settings.System.SCREEN_BRIGHTNESS_MODE,
+                Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
+
+        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) {
+        if (eventTime > SystemClock.uptimeMillis()) {
+            throw new IllegalArgumentException("event time must not be in the future");
+        }
+
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+
+        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...");
+                mNotifier.onWakeUpStarted();
+                mSendWakeUpFinishedNotificationWhenReady = true;
+                mSendGoToSleepFinishedNotificationWhenReady = false;
+                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;
+        }
+
+        mLastSleepTime = eventTime;
+        mDirty |= DIRTY_WAKEFULNESS;
+        mWakefulness = WAKEFULNESS_ASLEEP;
+        mNotifier.onGoToSleepStarted(reason);
+        mSendGoToSleepFinishedNotificationWhenReady = true;
+        mSendWakeUpFinishedNotificationWhenReady = false;
+
+        // 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;
+    }
+
+    /**
+     * 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.
+        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 (mDisplayReady) {
+            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) {
+            boolean wasPowered = mIsPowered;
+            mIsPowered = mBatteryService.isPowered();
+
+            if (wasPowered != mIsPowered) {
+                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 (mWakeUpWhenPluggedOrUnpluggedConfig) {
+                    wakeUpNoUpdateLocked(now);
+                }
+                userActivityNoUpdateLocked(
+                        now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
+            }
+        }
+    }
+
+    /**
+     * 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) {
+            if (mStayOnWhilePluggedInSetting != 0
+                    && !isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {
+                mStayOn = mBatteryService.isPowered(mStayOnWhilePluggedInSetting);
+            } else {
+                mStayOn = false;
+            }
+        }
+    }
+
+    /**
+     * 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;
+                        }
+                        break;
+                    case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
+                        if (mWakefulness != WAKEFULNESS_ASLEEP) {
+                            mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_BRIGHT;
+                        }
+                        break;
+                    case PowerManager.SCREEN_DIM_WAKE_LOCK:
+                        if (mWakefulness != WAKEFULNESS_ASLEEP) {
+                            mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_DIM;
+                        }
+                        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();
+
+                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);
+        }
+        return Math.max(timeout, MINIMUM_SCREEN_OFF_TIMEOUT);
+    }
+
+    private int getScreenDimDurationLocked() {
+        return SCREEN_DIM_DURATION;
+    }
+
+    /**
+     * 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)) != 0) {
+            if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) {
+                if (DEBUG_SPEW) {
+                    Slog.d(TAG, "updateWakefulnessLocked: Nap time...");
+                }
+                mWakefulness = WAKEFULNESS_NAPPING;
+                mDirty |= DIRTY_WAKEFULNESS;
+                changed = true;
+            }
+        }
+        return changed;
+    }
+
+    // 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 && !mStayOn
+                && (mWakeLockSummary
+                        & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM
+                                | WAKE_LOCK_PROXIMITY_SCREEN_OFF)) == 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_SETTINGS
+                | DIRTY_IS_POWERED | DIRTY_STAY_ON | 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) {
+                Log.d(TAG, "handleSandman: canDream=" + canDream
+                        + ", mWakefulness=" + wakefulnessToString(mWakefulness));
+            }
+
+            if (canDream && mWakefulness == WAKEFULNESS_NAPPING) {
+                startDreaming = true;
+            }
+        }
+
+        // Get the dream manager, if needed.
+        if (startDreaming && mDreamManager == null) {
+            mDreamManager = IDreamManager.Stub.asInterface(
+                    ServiceManager.checkService("dreams"));
+            if (mDreamManager == null) {
+                Slog.w(TAG, "Unable to find IDreamManager.");
+            }
+        }
+
+        // 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) {
+            try {
+                isDreaming = mDreamManager.isDreaming();
+                if (startDreaming && !isDreaming) {
+                    Slog.i(TAG, "Entering dreamland.");
+                    mDreamManager.dream();
+                    isDreaming = mDreamManager.isDreaming();
+                    if (!isDreaming) {
+                        Slog.i(TAG, "Could not enter dreamland.  Sleep will be dreamless.");
+                    }
+                }
+            } catch (RemoteException ex) {
+            }
+        }
+
+        // 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;
+                    updatePowerStateLocked();
+                    continueDreaming = true;
+                } else if (mWakefulness == WAKEFULNESS_DREAMING) {
+                    continueDreaming = true;
+                }
+            }
+            if (!continueDreaming) {
+                handleDreamFinishedLocked();
+            }
+
+            // Allow the sandman to detect when the dream has ended.
+            // FIXME: The DreamManagerService should tell us explicitly.
+            if (mWakefulness == WAKEFULNESS_DREAMING
+                    || mWakefulness == WAKEFULNESS_NAPPING) {
+                if (!mSandmanScheduled) {
+                    mSandmanScheduled = true;
+                    Message msg = mHandler.obtainMessage(MSG_SANDMAN);
+                    msg.setAsynchronous(true);
+                    mHandler.sendMessageDelayed(msg, 1000);
+                }
+            }
+        }
+
+        // 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) {
+            try {
+                if (!continueDreaming && isDreaming) {
+                    Slog.i(TAG, "Leaving dreamland.");
+                    mDreamManager.awaken();
+                }
+            } catch (RemoteException ex) {
+            }
+        }
+    }
+
+    /**
+     * Returns true if the device is allowed to dream in its current state,
+     * assuming there has been no recent user activity and no wake locks are held.
+     */
+    private boolean canDreamLocked() {
+        return mIsPowered
+                && mDreamsSupportedConfig
+                && mDreamsEnabledSetting
+                && mDreamsActivateOnSleepSetting
+                && !mBatteryService.isBatteryLow();
+    }
+
+    /**
+     * 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();
+            }
+        }
+    }
+
+
+    /**
+     * 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)) != 0) {
+            int newScreenState = getDesiredScreenPowerState();
+            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();
+
+            mDisplayReady = mDisplayPowerController.requestPowerState(mDisplayPowerRequest,
+                    mRequestWaitForNegativeProximity);
+            mRequestWaitForNegativeProximity = false;
+
+            if (DEBUG_SPEW) {
+                Slog.d(TAG, "updateScreenStateLocked: displayReady=" + 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 getDesiredScreenPowerState() {
+        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 onProximityNegative() {
+            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 handleBootCompletedLocked() {
+        final long now = SystemClock.uptimeMillis();
+        mBootCompleted = true;
+        mDirty |= DIRTY_BOOT_COMPLETED;
+        userActivityNoUpdateLocked(
+                now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
+        updatePowerStateLocked();
+    }
+
+    private void handleDockStateChangedLocked(int dockState) {
+        // TODO
+    }
+
+    /**
+     * Reboot the device immediately, passing 'reason' (may be null)
+     * to the underlying __reboot system call.  Should not return.
+     */
+    @Override // Binder call
+    public void reboot(String reason) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            rebootInternal(reason);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private void rebootInternal(final String reason) {
+        if (mHandler == null || !mSystemReady) {
+            throw new IllegalStateException("Too early to call reboot()");
+        }
+
+        Runnable runnable = new Runnable() {
+            public void run() {
+                synchronized (this) {
+                    ShutdownThread.reboot(mContext, reason, false);
+                }
+            }
+        };
+
+        // 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.
+        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()") {
+            public void run() {
+                throw new RuntimeException(message);
+            }
+        };
+        try {
+            t.start();
+            t.join();
+        } catch (InterruptedException e) {
+            Log.wtf(TAG, e);
+        }
+    }
+
+    @Override // Binder call
+    public void clearUserActivityTimeout(long now, long timeout) {
+        // TODO Auto-generated method stub
+        // Only used by phone app, delete this
+    }
+
+    @Override // Binder call
+    public void setPokeLock(int pokey, IBinder lock, String tag) {
+        // TODO Auto-generated method stub
+        // Only used by phone app, delete this
+    }
+
+    /**
+     * 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;
+    }
+
+    @Override // Binder call
+    public void preventScreenOn(boolean prevent) {
+        // TODO Auto-generated method stub
+        // Only used by phone app, delete this
+    }
+
+    /**
+     * 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 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("  mStayOn=" + mStayOn);
+            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("  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("  mTemporaryScreenBrightnessSettingOverride="
+                    + mTemporaryScreenBrightnessSettingOverride);
+            pw.println("  mTemporaryScreenAutoBrightnessAdjustmentSettingOverride="
+                    + mTemporaryScreenAutoBrightnessAdjustmentSettingOverride);
+            pw.println("  mScreenBrightnessSettingMinimum=" + mScreenBrightnessSettingMinimum);
+            pw.println("  mScreenBrightnessSettingMaximum=" + mScreenBrightnessSettingMaximum);
+            pw.println("  mScreenBrightnessSettingDefault=" + mScreenBrightnessSettingDefault);
+
+            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);
+            }
+
+            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) {
+            synchronized (mLock) {
+                handleBootCompletedLocked();
+            }
+        }
+    }
+
+    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);
+                handleDockStateChangedLocked(dockState);
+            }
+        }
+    }
+
+    private final class SettingsObserver extends ContentObserver {
+        public SettingsObserver(Handler handler) {
+            super(handler);
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            synchronized (mLock) {
+                handleSettingsChangedLocked();
+            }
+        }
+    }
+
+    private final WindowManagerPolicy.ScreenOnListener mScreenOnListener =
+            new WindowManagerPolicy.ScreenOnListener() {
+        @Override
+        public void onScreenOn() {
+        }
+    };
+
+    /**
+     * 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;
+            }
+        }
+    }
+
+    /**
+     * 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;
+            }
+        }
+    }
+}
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/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/updatable/CertPinInstallReceiver.java b/services/java/com/android/server/updatable/CertPinInstallReceiver.java
new file mode 100644
index 0000000..c03fbc3
--- /dev/null
+++ b/services/java/com/android/server/updatable/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/updatable/ConfigUpdateInstallReceiver.java b/services/java/com/android/server/updatable/ConfigUpdateInstallReceiver.java
new file mode 100644
index 0000000..a74a648
--- /dev/null
+++ b/services/java/com/android/server/updatable/ConfigUpdateInstallReceiver.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+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)) {
+                        EventLog.writeEvent(EventLogTags.CONFIG_INSTALL_FAILED,
+                                            "New version is not greater than 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", e);
+        }
+    }
+
+    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", e);
+            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!", e);
+            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) {
+        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());
+            }
+        } catch (IOException e) {
+            Slog.e(TAG, "Failed to write update", e);
+        } finally {
+            if (tmp != null) {
+                tmp.delete();
+            }
+            IoUtils.closeQuietly(out);
+        }
+    }
+
+    private void install(String content, int version) {
+        writeUpdate(updateDir, updateContent, content);
+        writeUpdate(updateDir, updateVersion, Long.toString(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..3ef6d4c 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -41,6 +41,7 @@
 import android.os.Parcelable;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
+import android.os.UserHandle;
 import android.os.storage.StorageManager;
 import android.os.storage.StorageVolume;
 import android.os.SystemClock;
@@ -114,6 +115,7 @@
     private boolean mAudioSourceEnabled;
     private Map<String, List<Pair<String, String>>> mOemModeMap;
     private String[] mAccessoryStrings;
+    private UsbDebuggingManager mDebuggingManager;
 
     private class AdbSettingsObserver extends ContentObserver {
         public AdbSettingsObserver() {
@@ -166,6 +168,10 @@
             if (DEBUG) Slog.d(TAG, "accessory attached at boot");
             startAccessoryMode();
         }
+
+        if ("1".equals(SystemProperties.get("ro.adb.secure"))) {
+            mDebuggingManager = new UsbDebuggingManager(context);
+        }
     }
 
     public void systemReady() {
@@ -177,12 +183,9 @@
         // 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
@@ -425,6 +428,9 @@
                 setEnabledFunctions(mDefaultFunctions, true);
                 updateAdbNotification();
             }
+            if (mDebuggingManager != null) {
+                mDebuggingManager.setAdbEnabled(mAdbEnabled);
+            }
         }
 
         private void setEnabledFunctions(String functions, boolean makeDefault) {
@@ -532,7 +538,7 @@
                 }
             }
 
-            mContext.sendStickyBroadcast(intent);
+            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
         }
 
         private void updateAudioSourceFunction() {
@@ -555,7 +561,7 @@
                         Slog.e(TAG, "could not open audio source PCM file", e);
                     }
                 }
-                mContext.sendStickyBroadcast(intent);
+                mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
                 mAudioSourceEnabled = enabled;
             }
         }
@@ -601,6 +607,9 @@
                     if (mCurrentAccessory != null) {
                         mSettingsManager.accessoryAttached(mCurrentAccessory);
                     }
+                    if (mDebuggingManager != null) {
+                        mDebuggingManager.setAdbEnabled(mAdbEnabled);
+                    }
                     break;
             }
         }
@@ -802,10 +811,25 @@
         return usbFunctions;
     }
 
+    public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
+        if (mDebuggingManager != null) {
+            mDebuggingManager.allowUsbDebugging(alwaysAllow, publicKey);
+        }
+    }
+
+    public void denyUsbDebugging() {
+        if (mDebuggingManager != null) {
+            mDebuggingManager.denyUsbDebugging();
+        }
+    }
+
     public void dump(FileDescriptor fd, PrintWriter pw) {
         if (mHandler != null) {
             mHandler.dump(fd, pw);
         }
+        if (mDebuggingManager != null) {
+            mDebuggingManager.dump(fd, pw);
+        }
     }
 
     private native String[] nativeGetAccessoryStrings();
diff --git a/services/java/com/android/server/usb/UsbService.java b/services/java/com/android/server/usb/UsbService.java
index 0205ef8..bebcd56 100644
--- a/services/java/com/android/server/usb/UsbService.java
+++ b/services/java/com/android/server/usb/UsbService.java
@@ -164,6 +164,16 @@
         }
     }
 
+    public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+        mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey);
+    }
+
+    public void denyUsbDebugging() {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+        mDeviceManager.denyUsbDebugging();
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
diff --git a/services/java/com/android/server/usb/UsbSettingsManager.java b/services/java/com/android/server/usb/UsbSettingsManager.java
index 9b3459b..a8453d3 100644
--- a/services/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/java/com/android/server/usb/UsbSettingsManager.java
@@ -35,6 +35,7 @@
 import android.os.Binder;
 import android.os.FileUtils;
 import android.os.Process;
+import android.os.UserHandle;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
 import android.util.Xml;
@@ -546,7 +547,7 @@
         }
 
         // Send broadcast to running activity with registered intent
-        mContext.sendBroadcast(intent);
+        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
 
         // Start activity with registered intent
         resolveActivity(intent, matches, defaultPackage, device, null);
@@ -559,7 +560,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 +587,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,
diff --git a/services/java/com/android/server/wm/AppWindowAnimator.java b/services/java/com/android/server/wm/AppWindowAnimator.java
index 13e8bc5..2445b98 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();
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
index 6ecbb8e..13b072c 100644
--- a/services/java/com/android/server/wm/AppWindowToken.java
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -104,7 +104,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..9bca834 100644
--- a/services/java/com/android/server/wm/DimAnimator.java
+++ b/services/java/com/android/server/wm/DimAnimator.java
@@ -39,24 +39,25 @@
     
     int mLastDimWidth, mLastDimHeight;
 
-    DimAnimator (SurfaceSession session) {
+    DimAnimator (SurfaceSession session, final int layerStack) {
         if (mDimSurface == null) {
             try {
                 if (WindowManagerService.DEBUG_SURFACE_TRACE) {
-                    mDimSurface = new WindowStateAnimator.SurfaceTrace(session, 0,
+                    mDimSurface = new WindowStateAnimator.SurfaceTrace(session,
                         "DimAnimator",
-                        -1, 16, 16, PixelFormat.OPAQUE,
-                        Surface.FX_SURFACE_DIM);
+                        16, 16, PixelFormat.OPAQUE,
+                        Surface.FX_SURFACE_DIM | Surface.HIDDEN);
                 } else {
-                    mDimSurface = new Surface(session, 0,
-                        "DimAnimator",
-                        -1, 16, 16, PixelFormat.OPAQUE,
-                        Surface.FX_SURFACE_DIM);
+                    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);
             }
@@ -211,5 +212,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..ddbd70d 100644
--- a/services/java/com/android/server/wm/DimSurface.java
+++ b/services/java/com/android/server/wm/DimSurface.java
@@ -30,24 +30,25 @@
     int mLayer = -1;
     int mLastDimWidth, mLastDimHeight;
 
-    DimSurface(SurfaceSession session) {
+    DimSurface(SurfaceSession session, final int layerStack) {
         if (mDimSurface == null) {
             try {
                 if (WindowManagerService.DEBUG_SURFACE_TRACE) {
-                    mDimSurface = new WindowStateAnimator.SurfaceTrace(session, 0,
+                    mDimSurface = new WindowStateAnimator.SurfaceTrace(session,
                         "DimSurface",
-                        -1, 16, 16, PixelFormat.OPAQUE,
-                        Surface.FX_SURFACE_DIM);
+                        16, 16, PixelFormat.OPAQUE,
+                        Surface.FX_SURFACE_DIM | Surface.HIDDEN);
                 } else {
-                    mDimSurface = new Surface(session, 0,
-                        "DimSurface",
-                        -1, 16, 16, PixelFormat.OPAQUE,
-                        Surface.FX_SURFACE_DIM);
+                    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);
             }
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..3898ebc
--- /dev/null
+++ b/services/java/com/android/server/wm/DisplayContent.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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;
+    final DisplayInfo mDisplayInfo = new DisplayInfo();
+    final Display mDisplay;
+
+    // Accessed directly by all users.
+    boolean layoutNeeded;
+    int pendingLayoutChanges;
+    final boolean isDefaultDisplay;
+
+    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..545fce5 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,10 @@
             Slog.d(WindowManagerService.TAG, "broadcasting DRAG_STARTED at (" + touchX + ", " + touchY + ")");
         }
 
-        final int N = mService.mWindows.size();
+        final WindowList windows = mService.getWindowListLocked(mDisplay);
+        final int N = windows.size();
         for (int i = 0; i < N; i++) {
-            sendDragStartedLw(mService.mWindows.get(i), touchX, touchY, mDataDescription);
+            sendDragStartedLw(windows.get(i), touchX, touchY, mDataDescription);
         }
     }
 
@@ -380,7 +391,8 @@
         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);
         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 2527f46..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..aa18ee4 100644
--- a/services/java/com/android/server/wm/InputMonitor.java
+++ b/services/java/com/android/server/wm/InputMonitor.java
@@ -19,11 +19,13 @@
 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.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;
@@ -128,7 +130,7 @@
         return 0; // abort dispatching
     }
 
-    private void addInputWindowHandleLw(InputWindowHandle windowHandle) {
+    private void addInputWindowHandleLw(final InputWindowHandle windowHandle) {
         if (mInputWindowHandles == null) {
             mInputWindowHandles = new InputWindowHandle[16];
         }
@@ -139,6 +141,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 +203,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 +227,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 +246,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..d935b8b
--- /dev/null
+++ b/services/java/com/android/server/wm/KeyguardDisableHandler.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.admin.DevicePolicyManager;
+import android.content.Context;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.TokenWatcher;
+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) {
+                    mAllowDisableKeyguard = dpm.getPasswordQuality(null)
+                            == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED ?
+                                    ALLOW_DISABLE_YES : ALLOW_DISABLE_NO;
+                }
+            }
+            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..16beeab 100644
--- a/services/java/com/android/server/wm/Session.java
+++ b/services/java/com/android/server/wm/Session.java
@@ -33,6 +33,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.util.Slog;
+import android.view.Display;
 import android.view.IWindow;
 import android.view.IWindowSession;
 import android.view.InputChannel;
@@ -134,15 +135,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 +280,7 @@
             // !!! 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();
+            mService.mDragState.register(callingWin.mDisplayContent.getDisplay());
             mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
             if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel,
                     mService.mDragState.mServerChannel)) {
@@ -389,6 +408,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..0a4e6d3 100644
--- a/services/java/com/android/server/wm/WindowAnimator.java
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -8,19 +8,23 @@
 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.SystemClock;
 import android.util.Log;
 import android.util.Slog;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+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.LayoutToAnimatorParams;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -32,26 +36,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,42 +63,191 @@
      * 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) {
+    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;
+        }
+    }
+
+    WindowAnimator(final WindowManagerService service) {
         mService = service;
-        mContext = context;
-        mPolicy = policy;
+        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) {
+        DisplayContentsAnimator displayAnimator = getDisplayContentsAnimatorLocked(displayId);
+        displayAnimator.mWindowAnimationBackgroundSurface =
+                new DimSurface(mService.mFxSession, displayId);
+        displayAnimator.mDimAnimator = new DimAnimator(mService.mFxSession, displayId);
+        if (displayId == Display.DEFAULT_DISPLAY) {
+            mInitialized = true;
+        }
+    }
+
+    void removeDisplayLocked(final int displayId) {
+        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);
+            }
+
+            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) {
-        if ((mService.mWallpaperTarget == w && mService.mLowerWallpaperTarget == null)
-                || mService.mWallpaperTarget == null) {
-            for (final WindowToken token : mService.mWallpaperTokens) {
-                for (final WindowState wallpaper : token.windows) {
+        if ((mWallpaperTarget == w && mLowerWallpaperTarget == null) || mWallpaperTarget == null) {
+            final int numTokens = mWallpaperTokens.size();
+            for (int i = numTokens - 1; i >= 0; i--) {
+                final WindowToken token = mWallpaperTokens.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);
                     }
                 }
                 token.hidden = true;
@@ -108,62 +255,19 @@
         }
     }
 
-    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 +282,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 +313,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 +329,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 +378,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 +390,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 +406,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 +441,134 @@
         }
     }
 
+    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;
+                    }
+                }
+            }
+
+            windowAnimationBackgroundSurface.show(mDw, mDh,
+                    animLayer - WindowManagerService.LAYER_OFFSET_DIM,
+                    windowAnimationBackgroundColor);
+        } else {
+            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 +576,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();
-
         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 (dimParams != null) {
+                    dimAnimator.updateParameters(
+                            mContext.getResources(), dimParams, mCurrentTime);
+                }
+                if (dimAnimator != null && dimAnimator.mDimShown) {
+                    mAnimating |= dimAnimator.updateSurface(isDimmingLocked(displayId),
+                            mCurrentTime, !mService.okToDisplay());
                 }
             }
 
@@ -495,19 +662,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 +705,107 @@
         mInnerDh = appHeight;
     }
 
-    void startDimming(final WindowStateAnimator winAnimator, final float target,
-                      final int width, final int height) {
-        if (mDimAnimator == null) {
-            mDimAnimator = new DimAnimator(mService.mFxSession);
-        }
-        // 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)));
-        }
+    boolean isDimmingLocked(int displayId) {
+        return getDisplayContentsAnimatorLocked(displayId).mDimParams != null;
     }
 
-    // TODO(cmautner): Move into Handler
-    void stopDimming() {
-        mService.mH.sendMessage(mService.mH.obtainMessage(SET_DIM_PARAMETERS, null));
+    boolean isDimmingLocked(final WindowStateAnimator winAnimator) {
+        DimAnimator.Parameters dimParams =
+                getDisplayContentsAnimatorLocked(winAnimator.mWin.getDisplayId()).mDimParams;
+        return dimParams != null && dimParams.mDimWinAnimator == winAnimator;
     }
 
-    boolean isDimming() {
-        return mDimParams != null;
-    }
-
-    boolean isDimming(final WindowStateAnimator winAnimator) {
-        return mDimParams != null && mDimParams.mDimWinAnimator == winAnimator;
-    }
-
-    public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
+    public void dumpLocked(PrintWriter pw, String prefix, boolean dumpAll) {
         if (dumpAll) {
             if (mWindowDetachedWallpaper != null) {
                 pw.print(prefix); pw.print("mWindowDetachedWallpaper=");
-                        pw.println(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);
+                pw.print(mAnimTransactionSequence);
+                pw.println(" mForceHiding=" + forceHidingToString());
+            for (int i = 0; i < mDisplayContentsAnimators.size(); i++) {
+                pw.print(prefix); pw.print("DisplayContentsAnimator #");
+                    pw.println(mDisplayContentsAnimators.keyAt(i));
+                DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
+                final String subPrefix = "  " + prefix;
+                final String subSubPrefix = "  " + subPrefix;
+                if (displayAnimator.mWindowAnimationBackgroundSurface != null) {
+                    pw.println(subPrefix + "mWindowAnimationBackgroundSurface:");
+                    displayAnimator.mWindowAnimationBackgroundSurface.printTo(subSubPrefix, pw);
+                }
+                if (displayAnimator.mDimAnimator != null) {
+                    pw.println(subPrefix + "mDimAnimator:");
+                    displayAnimator.mDimAnimator.printTo(subSubPrefix, pw);
+                } else {
+                    pw.println(subPrefix + "no DimAnimator ");
+                }
+                if (displayAnimator.mDimParams != null) {
+                    pw.println(subPrefix + "mDimParams:");
+                    displayAnimator.mDimParams.printTo(subSubPrefix, pw);
+                } else {
+                    pw.println(subPrefix + "no DimParams ");
+                }
+                if (displayAnimator.mScreenRotationAnimation != null) {
+                    pw.println(subPrefix + "mScreenRotationAnimation:");
+                    displayAnimator.mScreenRotationAnimation.printTo(subSubPrefix, pw);
+                } else {
+                    pw.print(subPrefix + "no ScreenRotationAnimation ");
+                }
             }
-            if (mDimAnimator != null) {
-                pw.print(prefix); pw.print("mDimAnimator:");
-                mDimAnimator.printTo(prefix + "  ", pw);
-            } else {
-                pw.print(prefix); pw.print("no DimAnimator ");
+            pw.println();
+        }
+    }
+
+    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();
+            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 static class DisplayContentsAnimator {
+        WinAnimatorList mWinAnimators = new WinAnimatorList();
+        DimAnimator mDimAnimator = null;
+        DimAnimator.Parameters mDimParams = null;
+        DimSurface mWindowAnimationBackgroundSurface = null;
+        ScreenRotationAnimation mScreenRotationAnimation = null;
     }
 }
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 7011343..55a7c46 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -31,6 +31,7 @@
 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_UNIVERSE_BACKGROUND;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 
 import com.android.internal.app.IBatteryStats;
@@ -42,12 +43,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 +56,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 +71,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 +125,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 +139,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 +160,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;
@@ -267,58 +278,30 @@
 
     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);
+            } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+                final int newUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+                mCurrentUserId = newUserId;
             }
         }
     };
 
+    // 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 +366,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 +429,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 +440,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 +452,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 +468,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 +485,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 +502,6 @@
     final ArrayList<AppWindowToken> mOpeningApps = new ArrayList<AppWindowToken>();
     final ArrayList<AppWindowToken> mClosingApps = new ArrayList<AppWindowToken>();
 
-    Display mDisplay;
-
     boolean mIsTouchDevice;
 
     final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
@@ -583,10 +538,10 @@
     WindowState mWallpaperTarget = null;
     // If non-null, we are in the middle of animating from one wallpaper target
     // to another, and this is the lower one in Z-order.
-    WindowState mLowerWallpaperTarget = null;
+    private 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 +566,8 @@
     float mAnimatorDurationScale = 1.0f;
 
     final InputManagerService mInputManager;
+    final DisplayManagerService mDisplayManagerService;
+    final DisplayManager mDisplayManager;
 
     // Who is holding the screen on.
     Session mHoldingScreenOn;
@@ -626,7 +583,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;
@@ -641,7 +598,45 @@
         private float mButtonBrightness = -1;
         private boolean mUpdateRotation = false;
     }
-    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 +645,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 +716,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 +739,38 @@
     // 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 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,
+                        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, Handler uiHandler,
             boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
         mContext = context;
         mHaveInputMethods = haveInputMethods;
@@ -880,7 +778,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);
@@ -897,42 +805,37 @@
                 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);
+        setAnimatorDurationScale(Settings.System.getFloat(context.getContentResolver(),
+                Settings.System.ANIMATOR_DURATION_SCALE, mTransitionAnimationScale));
 
         // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
         IntentFilter filter = new IntentFilter();
         filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
+        // Track user switching.
+        filter.addAction(Intent.ACTION_USER_SWITCHED);
         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);
+        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) {
-                }
-            }
-        }
+        initPolicy(uiHandler);
 
         mInputManager.start();
 
         // 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() {
@@ -955,34 +858,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 +890,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 +975,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 +989,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 +1002,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 +1031,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 +1040,7 @@
                                 Slog.v(TAG, "Adding window " + win + " at "
                                         + i + " of " + N);
                             }
-                            localmWindows.add(i, win);
+                            windows.add(i, win);
                             mWindowsChanged = true;
                         }
                     }
@@ -1118,18 +1049,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 +1069,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 +1088,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 {
@@ -1193,6 +1123,10 @@
         if (win.mAppToken != null && addToToken) {
             win.mAppToken.allAppWindows.add(win);
         }
+
+        if (windows.size() == 1) {
+            mDisplayManagerService.setDisplayHasContent(win.getDisplayId(), true);
+        }
     }
 
     /** TODO(cmautner): Is this the same as {@link WindowState#canReceiveKeys()} */
@@ -1226,13 +1160,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));
@@ -1247,7 +1184,7 @@
                 if (!willMove
                         && w.mAttrs.type == WindowManager.LayoutParams.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,12 +1204,13 @@
         // 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);
+        final WindowState curTarget = mInputMethodTarget;
+        if (curTarget != null && w != null
+                && curTarget.isDisplayedLw()
+                && curTarget.mExiting) {
+            if (curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
+                w = curTarget;
+                i = windows.indexOf(w);
                 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, switching to: " + w);
             }
         }
@@ -1281,20 +1219,20 @@
                 + 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 +1277,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 +1290,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 +1304,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 +1343,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 +1371,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 +1401,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 +1420,7 @@
             }
             if (DEBUG_INPUT_METHOD) {
                 Slog.v(TAG, "Final window list:");
-                logWindowList("  ");
+                logWindowList(windows, "  ");
             }
             return;
         }
@@ -1502,7 +1430,7 @@
             reAddWindowToListInOrderLocked(win);
             if (DEBUG_INPUT_METHOD) {
                 Slog.v(TAG, "No IM target, final list:");
-                logWindowList("  ");
+                logWindowList(windows, "  ");
             }
         }
     }
@@ -1514,6 +1442,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 +1452,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 +1470,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 +1478,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 +1492,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 +1521,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;
@@ -1631,13 +1562,15 @@
         mInnerFields.mWallpaperMayChange = false;
         int changed = 0;
 
-        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,7 +1580,7 @@
         int i = N;
         while (i > 0) {
             i--;
-            w = localmWindows.get(i);
+            w = windows.get(i);
             if ((w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER)) {
                 if (topCurW == null) {
                     topCurW = w;
@@ -1656,7 +1589,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) {
@@ -1682,7 +1615,7 @@
                     continue;
                 }
                 break;
-            } else if (w == mAnimator.mWindowDetachedWallpaper) {
+            } else if (w == mWindowDetachedWallpaper) {
                 windowDetachedI = i;
             }
         }
@@ -1741,7 +1674,7 @@
                             + " old animation: " + oldAnim);
                 }
                 if (foundAnim && oldAnim) {
-                    int oldI = localmWindows.indexOf(oldW);
+                    int oldI = windows.indexOf(oldW);
                     if (DEBUG_WALLPAPER) {
                         Slog.v(TAG, "New i: " + foundI + " old i: " + oldI);
                     }
@@ -1760,7 +1693,7 @@
                             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.
@@ -1825,7 +1758,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 +1784,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) {
@@ -1876,7 +1809,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();
@@ -1901,18 +1834,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--;
@@ -1925,7 +1858,7 @@
                             + " from " + oldIndex + " to " + foundI);
                 }
 
-                localmWindows.add(foundI, wallpaper);
+                windows.add(foundI, wallpaper);
                 mWindowsChanged = true;
                 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED;
             }
@@ -2040,14 +1973,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 +2009,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;
@@ -2120,8 +2039,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 +2052,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 +2067,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;
         }
 
@@ -2161,13 +2082,13 @@
         long origId;
 
         synchronized(mWindowMap) {
-            if (mDisplay == null) {
+            if (!mDisplayReady) {
                 throw new IllegalStateException("Display has not been initialialized");
             }
 
             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) {
@@ -2175,13 +2096,13 @@
                 if (attachedWindow == null) {
                     Slog.w(TAG, "Attempted to add window with token that is not a window: "
                           + attrs.token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
+                    return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
                 }
                 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
                         && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
                     Slog.w(TAG, "Attempted to add window with token that is a sub-window: "
                             + attrs.token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
+                    return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
                 }
             }
 
@@ -2192,22 +2113,22 @@
                         && attrs.type <= LAST_APPLICATION_WINDOW) {
                     Slog.w(TAG, "Attempted to add application window with unknown token "
                           + attrs.token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
                 if (attrs.type == TYPE_INPUT_METHOD) {
                     Slog.w(TAG, "Attempted to add input method window with unknown token "
                           + attrs.token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
                 if (attrs.type == TYPE_WALLPAPER) {
                     Slog.w(TAG, "Attempted to add wallpaper window with unknown token "
                           + attrs.token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
                 if (attrs.type == TYPE_DREAM) {
                     Slog.w(TAG, "Attempted to add Dream window with unknown token "
                           + attrs.token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
                 token = new WindowToken(this, attrs.token, -1, false);
                 addToken = true;
@@ -2217,68 +2138,69 @@
                 if (atoken == null) {
                     Slog.w(TAG, "Attempted to add window with non-application token "
                           + token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_NOT_APP_TOKEN;
+                    return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
                 } else if (atoken.removed) {
                     Slog.w(TAG, "Attempted to add window with exiting application token "
                           + token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_APP_EXITING;
+                    return WindowManagerGlobal.ADD_APP_EXITING;
                 }
                 if (attrs.type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
                     // No need for this guy!
                     if (localLOGV) Slog.v(
                             TAG, "**** NO NEED TO START: " + attrs.getTitle());
-                    return WindowManagerImpl.ADD_STARTING_NOT_NEEDED;
+                    return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED;
                 }
             } else if (attrs.type == TYPE_INPUT_METHOD) {
                 if (token.windowType != TYPE_INPUT_METHOD) {
                     Slog.w(TAG, "Attempted to add input method window with bad token "
                             + attrs.token + ".  Aborting.");
-                      return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+                      return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
             } else if (attrs.type == TYPE_WALLPAPER) {
                 if (token.windowType != TYPE_WALLPAPER) {
                     Slog.w(TAG, "Attempted to add wallpaper window with bad token "
                             + attrs.token + ".  Aborting.");
-                      return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+                      return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
             } else if (attrs.type == TYPE_DREAM) {
                 if (token.windowType != TYPE_DREAM) {
                     Slog.w(TAG, "Attempted to add Dream window with bad token "
                             + attrs.token + ".  Aborting.");
-                      return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+                      return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
             }
 
+            final DisplayContent displayContent = getDisplayContentLocked(displayId);
             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);
 
             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();
 
@@ -2319,13 +2241,17 @@
 
             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 +2269,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 +2283,7 @@
             if (localLOGV) Slog.v(
                 TAG, "New client " + client.asBinder()
                 + ": window=" + win);
-            
+
             if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
                 reportNewConfig = true;
             }
@@ -2423,13 +2349,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,7 +2412,12 @@
 
         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);
+        if (windows.isEmpty()) {
+            mDisplayManagerService.setDisplayHasContent(win.getDisplayId(), false);
+        }
         mPendingRemove.remove(win);
         mWindowsChanged = true;
         if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win);
@@ -2543,14 +2475,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 +2542,7 @@
                         w.mGivenVisibleInsets.scale(w.mGlobalScale);
                         w.mGivenTouchableRegion.scale(w.mGlobalScale);
                     }
-                    mLayoutNeeded = true;
+                    w.mDisplayContent.layoutNeeded = true;
                     performLayoutAndPlaceSurfacesLocked();
                 }
             }
@@ -2683,6 +2615,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 +2735,7 @@
             }
 
             winAnimator.mSurfaceDestroyDeferred =
-                    (flags&WindowManagerImpl.RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
+                    (flags&WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
 
             int attrChanges = 0;
             int flagChanges = 0;
@@ -2772,9 +2778,10 @@
                     WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM |
                     WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)) != 0;
 
-            boolean focusMayChange = win.mViewVisibility != viewVisibility
+            final boolean isDefaultDisplay = win.isDefaultDisplay();
+            boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility
                     || ((flagChanges&WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0)
-                    || (!win.mRelayoutCalled);
+                    || (!win.mRelayoutCalled));
 
             boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
                     && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
@@ -2848,7 +2855,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 +2863,7 @@
                     return 0;
                 }
                 if (toBeDisplayed) {
-                    focusMayChange = true;
+                    focusMayChange = isDefaultDisplay;
                 }
                 if (win.mAttrs.type == TYPE_INPUT_METHOD
                         && mInputMethodWindow == null) {
@@ -2893,7 +2900,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
@@ -2911,6 +2918,7 @@
                             }
                             winAnimator.destroySurfaceLocked();
                         }
+                        scheduleNotifyWindowTranstionIfNeededLocked(win, transit);
                     }
                 }
 
@@ -2947,15 +2955,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();
@@ -2989,10 +2999,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) {
@@ -3035,20 +3045,118 @@
                 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 == WindowManager.LayoutParams.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 == WindowManager.LayoutParams.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 +3236,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 +3277,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 +3302,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 +3318,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 +3325,106 @@
                         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) {
+                // 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 +3437,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 +3517,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 +3530,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 +3549,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 +3566,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 +3591,7 @@
         Slog.w(TAG, msg);
         return false;
     }
-    
+
     boolean okToDisplay() {
         return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully();
     }
@@ -3470,10 +3621,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()")) {
@@ -3499,13 +3652,16 @@
                         }
 
                         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;
                         }
                     }
 
                     if (changed) {
-                        mLayoutNeeded = true;
                         performLayoutAndPlaceSurfacesLocked();
                         updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
                                 false /*updateInputWindows*/);
@@ -3515,6 +3671,7 @@
                         mExitingTokens.add(wtoken);
                     } else if (wtoken.windowType == TYPE_WALLPAPER) {
                         mWallpaperTokens.remove(wtoken);
+                        updateLayoutToAnimWallpaperTokens();
                     }
                 }
 
@@ -3530,18 +3687,18 @@
      *  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
@@ -3567,30 +3724,31 @@
         }
 
         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.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 +3756,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 +3775,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 +3793,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 +3807,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 +3828,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 +3862,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 +3872,7 @@
         return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
     }
 
+    @Override
     public Configuration updateOrientationFromAppTokens(
             Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
@@ -3721,7 +3882,7 @@
 
         Configuration config = null;
         long ident = Binder.clearCallingIdentity();
-        
+
         synchronized(mWindowMap) {
             config = updateOrientationFromAppTokensLocked(currentConfig,
                     freezeThisOneIfNeeded);
@@ -3737,10 +3898,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 +3917,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 +3934,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 +3971,7 @@
         return req;
     }
 
+    @Override
     public void setNewConfiguration(Configuration config) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "setNewConfiguration()")) {
@@ -3822,7 +3984,8 @@
             performLayoutAndPlaceSurfacesLocked();
         }
     }
-    
+
+    @Override
     public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "setAppOrientation()")) {
@@ -3830,16 +3993,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 +4015,7 @@
         }
     }
 
+    @Override
     public void setFocusedApp(IBinder token, boolean moveFocusNow) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "setFocusedApp()")) {
@@ -3888,6 +4053,7 @@
         }
     }
 
+    @Override
     public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "prepareAppTransition()")) {
@@ -3926,6 +4092,7 @@
         }
     }
 
+    @Override
     public int getPendingAppTransition() {
         return mNextAppTransition;
     }
@@ -3936,6 +4103,7 @@
         }
     }
 
+    @Override
     public void overridePendingAppTransition(String packageName,
             int enterAnim, int exitAnim, IRemoteCallback startedCallback) {
         synchronized(mWindowMap) {
@@ -3953,6 +4121,7 @@
         }
     }
 
+    @Override
     public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
             int startHeight) {
         synchronized(mWindowMap) {
@@ -3970,15 +4139,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 +4159,7 @@
         }
     }
 
+    @Override
     public void executeAppTransition() {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "executeAppTransition()")) {
@@ -4075,7 +4246,7 @@
                         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 +4288,7 @@
 
                         updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
                                 true /*updateInputWindows*/);
-                        mLayoutNeeded = true;
+                        getDefaultDisplayContentLocked().layoutNeeded = true;
                         performLayoutAndPlaceSurfacesLocked();
                         Binder.restoreCallingIdentity(origId);
                         return;
@@ -4263,6 +4434,10 @@
                 if (applyAnimationLocked(wtoken, lp, transit, visible)) {
                     delayed = runningAppAnimation = true;
                 }
+                WindowState window = wtoken.findMainWindow();
+                if (window != null) {
+                    scheduleNotifyWindowTranstionIfNeededLocked(window, transit);
+                }
                 changed = true;
             }
 
@@ -4280,15 +4455,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 +4491,6 @@
                       + wtoken.hiddenRequested);
 
             if (changed) {
-                mLayoutNeeded = true;
                 mInputMonitor.setUpdateInputWindowsNeededLw();
                 if (performLayout) {
                     updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
@@ -4438,6 +4618,7 @@
                         mInnerFields.mOrientationChangeComplete = false;
                     }
                     unfrozeWindows = true;
+                    w.mDisplayContent.layoutNeeded = true;
                 }
             }
             if (force || unfrozeWindows) {
@@ -4447,7 +4628,6 @@
             }
             if (unfreezeSurfaceNow) {
                 if (unfrozeWindows) {
-                    mLayoutNeeded = true;
                     performLayoutAndPlaceSurfacesLocked();
                 }
                 stopFreezingDisplayLocked();
@@ -4472,7 +4652,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 +4792,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 +4818,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 +4843,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 +4862,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 +4871,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 +4884,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 +4893,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 +4967,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 +5014,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 +5054,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 +5161,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 +5269,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 +5321,7 @@
                 mTransitionAnimationScale = fixScale(scales[1]);
             }
             if (scales.length >= 3) {
-                mAnimatorDurationScale = fixScale(scales[2]);
+                setAnimatorDurationScale(fixScale(scales[2]));
             }
         }
 
@@ -5103,6 +5329,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,17 +5379,20 @@
 
     // 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);
     }
 
@@ -5247,9 +5481,11 @@
                         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);
+                    WindowState w = windows.get(i);
                     if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD) {
                         // Only if there is a keyguard attached to the window manager
                         // will we consider ourselves as having a keyguard.  If it
@@ -5401,8 +5637,9 @@
             // 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 +5654,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 +5677,11 @@
      * 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) {
+    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,8 +5699,10 @@
         synchronized(mWindowMap) {
             long ident = Binder.clearCallingIdentity();
 
-            dw = mCurDisplayWidth;
-            dh = mCurDisplayHeight;
+            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+            dw = displayInfo.logicalWidth;
+            dh = displayInfo.logicalHeight;
 
             int aboveAppLayer = mPolicy.windowTypeToLayerLw(
                     WindowManager.LayoutParams.TYPE_APPLICATION) * TYPE_LAYER_MULTIPLIER
@@ -5474,8 +5716,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 +5770,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 +5805,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 +5919,7 @@
         synchronized(mWindowMap) {
             changed = updateRotationUncheckedLocked(false);
             if (!changed || forceRelayout) {
-                mLayoutNeeded = true;
+                getDefaultDisplayContentLocked().layoutNeeded = true;
                 performLayoutAndPlaceSurfacesLocked();
             }
         }
@@ -5687,6 +5931,7 @@
         Binder.restoreCallingIdentity(origId);
     }
 
+    // TODO(multidisplay): Rotate any display?
     /**
      * Updates the current rotation.
      *
@@ -5701,8 +5946,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.
@@ -5752,60 +5998,70 @@
         mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
         mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT), 2000);
         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 +6120,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 +6133,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 +6144,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 +6258,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 +6274,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 +6300,7 @@
         return result;
     }
 
+    // TODO(multidisplay): Extend to multiple displays.
     /**
      * Returns the focused window in the following format:
      * windowHashCodeInHexadecimal windowName
@@ -6180,6 +6442,110 @@
         return success;
     }
 
+    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.mDisplayContentChangeListeners == null) {
+                displayContent.mDisplayContentChangeListeners =
+                        new RemoteCallbackList<IDisplayContentChangeListener>();
+            displayContent.mDisplayContentChangeListeners.register(listener);
+            }
+        }
+    }
+
+    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.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();
+        }
+    }
+
     public void addWindowChangeListener(WindowChangeListener listener) {
         synchronized(mWindowMap) {
             mWindowChangeListeners.add(listener);
@@ -6224,15 +6590,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,25 +6639,27 @@
         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);
@@ -6370,8 +6737,10 @@
         return curLayout;
     }
 
-    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 +6753,28 @@
             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);
+        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.SCREENLAYOUT_SIZE_XLARGE
                 | Configuration.SCREENLAYOUT_LONG_YES;
         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.screenLayout = sl;
+        outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
+        outConfig.screenLayout =
+                sl|(outConfig.screenLayout&Configuration.SCREENLAYOUT_LAYOUTDIR_MASK);
     }
 
     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 +6786,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 +6797,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 +6874,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 +7007,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 +7093,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 +7107,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 +7154,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();
+            final Display display = displayContent.getDisplay();
+            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();
+    }
+
+    public void displayReady(int displayId) {
+        synchronized(mWindowMap) {
+            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            final DisplayInfo displayInfo;
+            mAnimator.addDisplayLocked(displayId);
+            synchronized(displayContent.mDisplaySizeLock) {
+                // Bootstrap the default logical display from the display manager.
+                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 +7208,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 +7235,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 +7248,22 @@
         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 DO_DISPLAY_ADDED = 31;
+        public static final int DO_DISPLAY_REMOVED = 32;
+        public static final int DO_DISPLAY_CHANGED = 33;
+
+        public static final int CLIENT_FREEZE_TIMEOUT = 34;
 
         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 +7498,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 +7516,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) {
@@ -7191,18 +7542,22 @@
                 }
 
                 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 +7587,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 +7671,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();
                         }
@@ -7363,21 +7696,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 +7708,46 @@
                     }
                     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 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 +7774,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 +7810,148 @@
                             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);
+        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) {
+    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;
-            }
-            setForcedDisplaySizeLocked(width, height);
-            Settings.Secure.putString(mContext.getContentResolver(),
-                    Settings.Secure.DISPLAY_SIZE_FORCED, width + "," + height);
+            // 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);
+
+            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);
         }
     }
 
-    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) {
+    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;
+    public void clearForcedDisplaySize(int displayId) {
+        synchronized(mWindowMap) {
+            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
+                    displayContent.mInitialDisplayHeight);
+            Settings.Global.putString(mContext.getContentResolver(),
+                    Settings.Global.DISPLAY_SIZE_FORCED, "");
+        }
+    }
+
+    public void setForcedDisplayDensity(int displayId, int density) {
+        synchronized(mWindowMap) {
+            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            setForcedDisplayDensityLocked(displayContent, density);
+            Settings.Global.putString(mContext.getContentResolver(),
+                    Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
+        }
+    }
+
+    private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) {
+        Slog.i(TAG, "Using new display density: " + density);
+
+        synchronized(displayContent.mDisplaySizeLock) {
+            displayContent.mBaseDisplayDensity = density;
+        }
+        reconfigureDisplayLocked(displayContent);
+    }
+
+    public void clearForcedDisplayDensity(int displayId) {
+        synchronized(mWindowMap) {
+            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            setForcedDisplayDensityLocked(displayContent, displayContent.mInitialDisplayDensity);
+            Settings.Secure.putString(mContext.getContentResolver(),
+                    Settings.Secure.DISPLAY_DENSITY_FORCED, "");
+        }
+    }
+
+    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 +7964,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 +8013,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 +8033,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 +8044,19 @@
                 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 == WindowManager.LayoutParams.TYPE_WALLPAPER
+                        || w.mAttrs.type == WindowManager.LayoutParams.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 +8064,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);
@@ -7733,8 +8096,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;
@@ -7746,7 +8109,7 @@
         }
 
         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;
@@ -7779,9 +8142,9 @@
             if (winAnimator.mAnimLayer != oldLayer) {
                 layerChanged = 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);
@@ -7808,7 +8171,7 @@
             return;
         }
         
-        if (mDisplay == null) {
+        if (!mDisplayReady) {
             // Not yet initialized, nothing to do.
             return;
         }
@@ -7839,35 +8202,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,32 +8231,41 @@
         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;
@@ -7925,7 +8275,7 @@
         // 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
@@ -7950,13 +8300,14 @@
                         + (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_UNIVERSE_BACKGROUND) {
                 if (!win.mLayoutAttached) {
                     if (initial) {
                         //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
@@ -7974,6 +8325,16 @@
                     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;
         }
 
         // Now perform layout of attached windows, which usually
@@ -7981,7 +8342,7 @@
         // 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
@@ -8042,10 +8403,10 @@
 
     /**
      * 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();
@@ -8200,15 +8561,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++) {
@@ -8248,9 +8617,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 +8636,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 +8660,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 +8678,6 @@
 
     /**
      * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
-     *
      * @return bitmap indicating if another pass through layout must be made.
      */
     private int handleAnimatingStoppedAndTransitionLocked() {
@@ -8473,17 +8848,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;
+                        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 +8886,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;
 
@@ -8550,193 +8917,238 @@
         mInnerFields.mButtonBrightness = -1;
         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 (mWatermark != null) {
+                mWatermark.positionSurface(defaultDw, defaultDh);
+            }
+            if (mStrictModeFlash != null) {
+                mStrictModeFlash.positionSurface(defaultDw, defaultDh);
+            }
 
-                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;
+            // Give the display manager a chance to adjust properties
+            // like display rotation if it needs to.
+            mDisplayManagerService.performTraversalInTransactionFromWindowManager();
 
             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);
-                }
+                int repeats = 0;
+                do {
+                    repeats++;
+                    if (repeats > 6) {
+                        Slog.w(TAG, "Animation repeat aborted after too many iterations");
+                        displayContent.layoutNeeded = false;
+                        break;
+                    }
 
-                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();
-                }
+                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner",
+                        displayContent.pendingLayoutChanges);
 
-                final WindowStateAnimator winAnimator = w.mWinAnimator;
+                    if (isDefaultDisplay && ((displayContent.pendingLayoutChanges
+                            & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0)
+                            && ((adjustWallpaperWindowsLocked()
+                                    & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0)) {
+                        assignLayersLocked(windows);
+                        displayContent.layoutNeeded = true;
+                    }
 
-                // 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_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);
+                        }
+                    }
 
-                //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
-                w.mContentChanged = false;
+                    if ((displayContent.pendingLayoutChanges
+                            & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
+                        displayContent.layoutNeeded = true;
+                    }
 
-                // 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);
+                    // 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.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;
+                                displayContent.pendingLayoutChanges |=
+                                        WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+                                if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
+                                    debugLayoutRepeats(
+                                        "wallpaper 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;
+                        }
+
+                        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
+                                    == 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);
                                     }
                                 }
-                            } 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;
+                if (!mInnerFields.mDimming && mAnimator.isDimmingLocked(displayId)) {
+                    stopDimmingLocked(displayId);
                 }
-
-                updateResizingWindows(w);
             }
 
             if (updateAllDrawn) {
@@ -8746,23 +9158,21 @@
             if (focusDisplayed) {
                 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
             }
-
-            if (!mInnerFields.mDimming && mAnimator.isDimming()) {
-                mAnimator.stopDimming();
-            }
         } catch (RuntimeException e) {
             Log.wtf(TAG, "Unhandled exception in Window Manager", e);
         } finally {
             Surface.closeTransaction();
         }
 
+        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,22 +9184,22 @@
             // 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;
 
@@ -8802,26 +9212,27 @@
         if ((mInnerFields.mAdjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
             if (DEBUG_WALLPAPER) 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,
                     "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()) {
@@ -8847,9 +9258,7 @@
                     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,
+                    win.mClient.resized(win.mFrame, win.mLastContentInsets, win.mLastVisibleInsets,
                             winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING,
                             configChanged ? win.mConfiguration : null);
                     win.mContentInsetsChanged = false;
@@ -8899,6 +9308,7 @@
                 mExitingTokens.remove(i);
                 if (token.windowType == TYPE_WALLPAPER) {
                     mWallpaperTokens.remove(token);
+                    updateLayoutToAnimWallpaperTokens();
                 }
             }
         }
@@ -8930,41 +9340,40 @@
             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);
-        }
 
         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 +9386,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--) {
@@ -9040,13 +9474,17 @@
         }
     }
 
-    /**
-     * Must be called with the main window manager lock held.
-     */
-    void setHoldScreenLocked(boolean holding) {
-        boolean state = mHoldingScreenWakeLock.isHeld();
-        if (holding != state) {
-            if (holding) {
+    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) {
                 mPolicy.screenOnStartedLw();
                 mHoldingScreenWakeLock.acquire();
             } else {
@@ -9056,6 +9494,13 @@
         }
     }
 
+    @Override
+    public void requestTraversal() {
+        synchronized (mWindowMap) {
+            requestTraversalLocked();
+        }
+    }
+
     void requestTraversalLocked() {
         if (!mTraversalScheduled) {
             mTraversalScheduled = true;
@@ -9063,13 +9508,135 @@
         }
     }
 
+    /** 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);
+            }
+
+            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));
+                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 +9655,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 +9674,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 +9692,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 +9758,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;
+                    getDefaultDisplayContentLocked().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;
+                getDefaultDisplayContentLocked().layoutNeeded = true;
                 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
-                    performLayoutLockedInner(true /*initial*/, updateInputWindows);
+                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
                 }
             }
 
@@ -9232,12 +9806,19 @@
         WindowState result = null;
         WindowState win;
 
+        if (mAnimator.mUniverseBackground != null
+                && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) {
+            return mAnimator.mUniverseBackground.mWin;
+        }
+
         int nextAppIndex = mAppTokens.size()-1;
         WindowToken nextApp = nextAppIndex >= 0
             ? mAppTokens.get(nextAppIndex) : null;
 
-        for (int i = mWindows.size() - 1; i >= 0; i--) {
-            win = mWindows.get(i);
+        // TODO(multidisplay): IMEs are only supported on the default display.
+        WindowList windows = getDefaultWindowListLocked();
+        for (int i = windows.size() - 1; i >= 0; i--) {
+            win = windows.get(i);
 
             if (localLOGV || DEBUG_FOCUS) Slog.v(
                 TAG, "Looking for focus: " + i
@@ -9295,12 +9876,13 @@
         return result;
     }
 
-    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;
@@ -9326,20 +9908,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 +9932,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 +10029,7 @@
         return val;
     }
 
-    void createWatermark() {
+    void createWatermarkInTransaction() {
         if (mWatermark != null) {
             return;
         }
@@ -9448,7 +10043,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 +10074,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 +10147,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);
             }
@@ -9699,10 +10299,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);
             }
@@ -9809,28 +10411,12 @@
                         pw.print(": "); pw.println(pair.second);
             }
         }
-        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 +10433,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));
@@ -9871,21 +10458,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 +10510,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) {
@@ -9934,17 +10528,18 @@
             pw.print("  mStartingIconInTransition="); pw.print(mStartingIconInTransition);
                     pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
             pw.println("  Window Animator:");
-            mAnimator.dump(pw, "    ", dumpAll);
+            mAnimator.dumpLocked(pw, "    ", dumpAll);
         }
     }
 
     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 +10554,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);
@@ -10133,7 +10729,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 +10742,155 @@
         }
     }
 
-    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);
+    }
+
+    public DisplayContent getDisplayContentLocked(final int displayId) {
+        DisplayContent displayContent = mDisplayContents.get(displayId);
+        if (displayContent == null) {
+            displayContent = new DisplayContent(mDisplayManager.getDisplay(displayId));
+            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");
+        }
+    }
+
+    public DisplayContent getDefaultDisplayContentLocked() {
+        return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
+    }
+
+    public WindowList getDefaultWindowListLocked() {
+        return getDefaultDisplayContentLocked().getWindowList();
+    }
+
+    public DisplayInfo getDefaultDisplayInfoLocked() {
+        return getDefaultDisplayContentLocked().getDisplayInfo();
+    }
+
+    public WindowList getWindowListLocked(final Display display) {
+        return getDisplayContentLocked(display.getDisplayId()).getWindowList();
+    }
+
+    @Override
+    public void onDisplayAdded(int displayId) {
+        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
+    }
+
+    private void handleDisplayAddedLocked(int displayId) {
+        createDisplayContentLocked(mDisplayManager.getDisplay(displayId));
+        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);
+        mDisplayContents.delete(displayId);
+        WindowList windows = displayContent.getWindowList();
+        for (int i = windows.size() - 1; i >= 0; --i) {
+            final WindowState win = windows.get(i);
+            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 a00e8a5..b62028e 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -22,6 +22,9 @@
 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_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 
 import com.android.server.input.InputWindowHandle;
 
@@ -33,8 +36,11 @@
 import android.graphics.RectF;
 import android.graphics.Region;
 import android.os.IBinder;
+import android.os.Process;
 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 +53,9 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 
+class WindowList extends ArrayList<WindowState> {
+}
+
 /**
  * A window in the window manager.
  */
@@ -251,15 +260,22 @@
 
     boolean mHasSurface = false;
 
+    DisplayContent  mDisplayContent;
+
+    // UserId and appId of the owner. Don't display windows of non-current user.
+    final int mOwnerUid;
+
     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();
@@ -317,9 +333,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 +348,9 @@
         mRootToken = appToken;
         mAppToken = appToken.appWindowToken;
 
+        mWinAnimator = new WindowStateAnimator(this);
+        mWinAnimator.mAlpha = a.alpha;
+
         mRequestedWidth = 0;
         mRequestedHeight = 0;
         mLastRequestedWidth = 0;
@@ -343,7 +359,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 +496,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 +514,21 @@
         }
     }
 
+    MagnificationSpec getWindowMagnificationSpecLocked() {
+        MagnificationSpec spec = mDisplayContent.mMagnificationSpec;
+        if (spec != null && !spec.isNop()) {
+            if (mAttachedWindow != null) {
+                if (!mPolicy.canMagnifyWindow(mAttachedWindow.mAttrs)) {
+                    return null;
+                }
+            }
+            if (!mPolicy.canMagnifyWindow(mAttrs)) {
+                return null;
+            }
+        }
+        return spec;
+    }
+
     @Override
     public Rect getFrameLw() {
         return mFrame;
@@ -544,6 +577,7 @@
     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,20 +592,22 @@
             // 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;
     }
@@ -579,7 +615,11 @@
     public IApplicationToken getAppToken() {
         return mAppToken != null ? mAppToken.appToken : null;
     }
-    
+
+    public int getDisplayId() {
+        return mDisplayContent.getDisplayId();
+    }
+
     public long getInputDispatchingTimeoutNanos() {
         return mAppToken != null
                 ? mAppToken.inputDispatchingTimeoutNanos
@@ -766,7 +806,7 @@
         return mViewVisibility == View.GONE
                 || !mRelayoutCalled
                 || (atoken == null && mRootToken.hidden)
-                || (atoken != null && (atoken.hiddenRequested || atoken.hidden))
+                || (atoken != null && atoken.hiddenRequested)
                 || mAttachedHidden
                 || mExiting || mDestroying;
     }
@@ -884,6 +924,11 @@
     }
 
     boolean showLw(boolean doAnimation, boolean requestAnim) {
+        if (isOtherUsersAppWindow()) {
+            Slog.w(TAG, "Current user " + mService.mCurrentUserId + " trying to display "
+                    + this + ", type " + mAttrs.type + ", belonging to " + mOwnerUid);
+            return false;
+        }
         if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
             // Already showing.
             return false;
@@ -907,7 +952,7 @@
             mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_ENTER, true);
         }
         if (requestAnim) {
-            mService.scheduleAnimationLocked();
+            mService.updateLayoutToAnimationLocked();
         }
         return true;
     }
@@ -950,7 +995,7 @@
             }
         }
         if (requestAnim) {
-            mService.scheduleAnimationLocked();
+            mService.updateLayoutToAnimationLocked();
         }
         return true;
     }
@@ -960,6 +1005,22 @@
         return mClient.asBinder().isBinderAlive();
     }
 
+    @Override
+    public boolean isDefaultDisplay() {
+        return mDisplayContent.isDefaultDisplay;
+    }
+
+    boolean isOtherUsersAppWindow() {
+        final int type = mAttrs.type;
+        if ((UserHandle.getUserId(mOwnerUid) != mService.mCurrentUserId)
+                && (mOwnerUid != Process.SYSTEM_UID)
+                && (type >= TYPE_BASE_APPLICATION) && (type <= LAST_APPLICATION_WINDOW)
+                && (type != TYPE_APPLICATION_STARTING)) {
+            return true;
+        }
+        return false;
+    }
+
     private static void applyInsets(Region outRegion, Rect frame, Rect inset) {
         outRegion.set(
                 frame.left + inset.left, frame.top + inset.top,
@@ -988,8 +1049,13 @@
         }
     }
 
+    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("mAttrs="); pw.println(mAttrs);
         pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
@@ -1060,11 +1126,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);
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index 03e52fe..000a191 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;
+    final 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? */
@@ -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();
@@ -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));
@@ -534,6 +550,13 @@
         }
 
         @Override
+        public void setLayerStack(int layerStack) {
+            super.setLayerStack(layerStack);
+            mLayerStack = layerStack;
+            Slog.v(SURFACE_TAG, "setLayerStack: " + this + ". Called by " + Debug.getCallers(3));
+        }
+
+        @Override
         public void hide() {
             super.hide();
             mShown = false;
@@ -574,7 +597,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 +615,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 +659,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 +708,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);
@@ -799,31 +818,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 +847,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 +889,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 +939,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 +967,113 @@
         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 is easy, just use the entire display.
+            w.mSystemDecorRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
         } 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 +1092,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 +1142,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,9 +1181,9 @@
 
         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()) {
@@ -1151,7 +1242,7 @@
                                 + " during relayout");
                         if (showSurfaceRobustlyLocked()) {
                             mLastHidden = false;
-                            if (w.mIsWallpaper) {
+                            if (mIsWallpaper) {
                                 mService.dispatchWallpaperVisibility(w, true);
                             }
                         } else {
@@ -1169,8 +1260,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 +1269,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 +1330,11 @@
 
     // This must be called while inside a transaction.
     boolean performShowLocked() {
+        if (mWin.isOtherUsersAppWindow()) {
+            Slog.w(TAG, "Current user " + 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 +1354,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 +1370,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 +1382,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 +1397,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 +1466,8 @@
         } else {
             transit = WindowManagerPolicy.TRANSIT_SHOW;
         }
-
         applyAnimationLocked(transit, true);
+        mService.scheduleNotifyWindowTranstionIfNeededLocked(mWin, transit);
     }
 
     // TODO(cmautner): Move back to WindowState?
@@ -1483,6 +1579,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);
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..319cacd 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);
@@ -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,
@@ -578,14 +536,9 @@
 
     JNIEnv* env = jniEnv();
 
-    switch (switchCode) {
-    case SW_LID:
-        // When switch value is set indicates lid is closed.
-        env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyLidSwitchChanged,
-                when, switchValue == 0 /*lidOpen*/);
-        checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged");
-        break;
-    }
+    env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifySwitch,
+            when, switchCode, switchValue);
+    checkAndClearExceptionFromCallback(env, "notifySwitch");
 }
 
 void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
@@ -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..3f3970b
--- /dev/null
+++ b/services/jni/com_android_server_power_PowerManagerService.cpp
@@ -0,0 +1,286 @@
+/*
+ * 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 <gui/ISurfaceComposer.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 <private/gui/ComposerService.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 nativeSetScreenState(JNIEnv *env, jclass clazz, jboolean on) {
+    sp<ISurfaceComposer> s(ComposerService::getComposerService());
+    if (on) {
+        {
+            ALOGD_IF_SLOW(50, "Excessive delay in autosuspend_disable() while turning screen on");
+            autosuspend_disable();
+        }
+
+        if (gPowerModule) {
+            ALOGD_IF_SLOW(10, "Excessive delay in setInteractive(true) while turning screen on");
+            gPowerModule->setInteractive(gPowerModule, true);
+        }
+
+        {
+            ALOGD_IF_SLOW(20, "Excessive delay in unblank() while turning screen on");
+            s->unblank();
+        }
+    } else {
+        {
+            ALOGD_IF_SLOW(20, "Excessive delay in blank() while turning screen off");
+            s->blank();
+        }
+
+        if (gPowerModule) {
+            ALOGD_IF_SLOW(10, "Excessive delay in setInteractive(false) while turning screen off");
+            gPowerModule->setInteractive(gPowerModule, false);
+        }
+
+        {
+            ALOGD_IF_SLOW(50, "Excessive delay in autosuspend_enable() while turning screen off");
+            autosuspend_enable();
+        }
+    }
+}
+
+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 },
+    { "nativeSetScreenState", "(Z)V",
+            (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/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..8aeb2af 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" />
+    
     <application>
         <uses-library android:name="android.test.runner" />
 
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/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/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..59a86c2 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -16,11 +16,11 @@
 
 package com.android.server.pm;
 
-import com.android.server.pm.UserManager;
-
+import android.content.Context;
 import android.content.pm.UserInfo;
 import android.os.Debug;
 import android.os.Environment;
+import android.os.UserManager;
 import android.test.AndroidTestCase;
 
 import java.util.List;
@@ -32,19 +32,7 @@
 
     @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);
     }
 
     public void testHasPrimary() throws Exception {
@@ -52,12 +40,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 +54,12 @@
             }
         }
         assertTrue(found);
+        mUserManager.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 +67,14 @@
         assertTrue(findUser(0));
         assertTrue(findUser(user1.id));
         assertTrue(findUser(user2.id));
+        mUserManager.removeUser(user1.id);
+        mUserManager.removeUser(user2.id);
     }
 
     public void testRemoveUser() throws Exception {
-        final UserManager details = mUserManager;
+        UserInfo userInfo = mUserManager.createUser("Guest 1", UserInfo.FLAG_GUEST);
 
-        UserInfo userInfo = details.createUser("Guest 1", UserInfo.FLAG_GUEST);
-
-        details.removeUser(userInfo.id);
+        mUserManager.removeUser(userInfo.id);
 
         assertFalse(findUser(userInfo.id));
     }
@@ -104,4 +89,18 @@
         }
         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));
+        mUserManager.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));
+        mUserManager.removeUser(user2.id);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/updatable/CertPinInstallReceiverTest.java b/services/tests/servicestests/src/com/android/server/updatable/CertPinInstallReceiverTest.java
new file mode 100644
index 0000000..b6742a1
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/updatable/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
index 65c220f..a3f7860 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.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,70 +20,83 @@
 import android.os.Parcelable;
 
 /**
- * CellIdentity is to represent ONE unique cell in the world
+ * CellIdentity is immutable and represents 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;
+    // 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;
 
-    private int mCellIdType;
-    private String mCellIdAttributes;
-
-    protected CellIdentity(int type, String attr) {
-        this.mCellIdType = type;
-        this.mCellIdAttributes = new String(attr);
+    /** @hide */
+    protected CellIdentity() {
     }
 
+    /** @hide */
     protected CellIdentity(Parcel in) {
-        this.mCellIdType = in.readInt();
-        this.mCellIdAttributes = new String(in.readString());
     }
 
+    /** @hide */
     protected CellIdentity(CellIdentity cid) {
-        this.mCellIdType = cid.mCellIdType;
-        this.mCellIdAttributes = new String(cid.mCellIdAttributes);
     }
 
     /**
-     * @return Cell Identity type as one of CELLID_TYPE_XXXX
+     * @return a copy of this object with package visibility.
      */
-    public int getCellIdType() {
-        return mCellIdType;
+    abstract CellIdentity copy();
+
+    @Override
+    public abstract int hashCode();
+
+    @Override
+    public boolean equals(Object other) {
+        if (other == null) {
+            return false;
+        }
+        if (this == other) {
+            return true;
+        }
+        return (other instanceof CellIdentity);
     }
 
-
-    /**
-     * @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;
+    @Override
+    public String toString() {
+        return "";
     }
 
-
-    /** 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(mCellIdType);
-        dest.writeString(mCellIdAttributes);
     }
+
+    /** Implement the Parcelable interface */
+    public static final Creator<CellIdentity> CREATOR =
+            new Creator<CellIdentity>() {
+        @Override
+        public CellIdentity createFromParcel(Parcel in) {
+            int type = in.readInt();
+            switch (type) {
+                case TYPE_GSM: return CellIdentityGsm.createFromParcelBody(in);
+                case TYPE_CDMA: return CellIdentityCdma.createFromParcelBody(in);
+                case TYPE_LTE: return CellIdentityLte.createFromParcelBody(in);
+                default: throw new RuntimeException("Bad CellIdentity Parcel");
+            }
+        }
+
+        @Override
+        public CellIdentity[] newArray(int size) {
+            return new CellIdentity[size];
+        }
+    };
 }
diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java
new file mode 100644
index 0000000..fccf98c
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentityCdma.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package 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 extends CellIdentity 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) {
+        super(cid);
+        mNetworkId = cid.mNetworkId;
+        mSystemId = cid.mSystemId;
+        mBasestationId = cid.mBasestationId;
+        mLongitude = cid.mLongitude;
+        mLatitude = cid.mLatitude;
+    }
+
+    @Override
+    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(TYPE_CDMA);
+        super.writeToParcel(dest, flags);
+        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) {
+        super(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) {
+            in.readInt(); // Skip past token, we know what it is
+            return createFromParcelBody(in);
+        }
+
+        @Override
+        public CellIdentityCdma[] newArray(int size) {
+            return new CellIdentityCdma[size];
+        }
+    };
+
+    /** @hide */
+    static CellIdentityCdma createFromParcelBody(Parcel in) {
+        return new CellIdentityCdma(in);
+    }
+
+    /**
+     * 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..dead049f
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentityGsm.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 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 extends CellIdentity 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) {
+        super(cid);
+        mMcc = cid.mMcc;
+        mMnc = cid.mMnc;
+        mLac = cid.mLac;
+        mCid = cid.mCid;
+        mPsc = cid.mPsc;
+    }
+
+    @Override
+    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(TYPE_GSM);
+        super.writeToParcel(dest, flags);
+        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) {
+        super(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) {
+            in.readInt(); // Skip past token, we know what it is
+            return createFromParcelBody(in);
+        }
+
+        @Override
+        public CellIdentityGsm[] newArray(int size) {
+            return new CellIdentityGsm[size];
+        }
+    };
+
+    /** @hide */
+    static CellIdentityGsm createFromParcelBody(Parcel in) {
+        return new CellIdentityGsm(in);
+    }
+
+    /**
+     * 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..832cbe1
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentityLte.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.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 extends CellIdentity 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) {
+        super(cid);
+        mMcc = cid.mMcc;
+        mMnc = cid.mMnc;
+        mCi = cid.mCi;
+        mPci = cid.mPci;
+        mTac = cid.mTac;
+    }
+
+    @Override
+    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(TYPE_LTE);
+        super.writeToParcel(dest, flags);
+        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) {
+        super(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) {
+            in.readInt(); // Skip past token, we know what it is
+            return createFromParcelBody(in);
+        }
+
+        @Override
+        public CellIdentityLte[] newArray(int size) {
+            return new CellIdentityLte[size];
+        }
+    };
+
+    /** @hide */
+    static CellIdentityLte createFromParcelBody(Parcel in) {
+        return new CellIdentityLte(in);
+    }
+
+    /**
+     * 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..1946b5d 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,175 @@
 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 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);
         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>() {
+    /** @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..1c41ba4
--- /dev/null
+++ b/telephony/java/android/telephony/CellInfoCdma.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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) {
+        if (DBG) log("writeToParcel(Parcel, int): " + toString());
+        dest.writeInt(TYPE_LTE);
+        super.writeToParcel(dest, flags);
+        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..c644cb3
--- /dev/null
+++ b/telephony/java/android/telephony/CellInfoGsm.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 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) {
+        dest.writeInt(TYPE_LTE);
+        super.writeToParcel(dest, flags);
+        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..8921db2
--- /dev/null
+++ b/telephony/java/android/telephony/CellInfoLte.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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 = false;
+
+    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() {
+        return mCellIdentityLte;
+    }
+    /** @hide */
+    public void setCellIdentity(CellIdentityLte cid) {
+        mCellIdentityLte = cid;
+    }
+
+    public CellSignalStrengthLte getCellSignalStrength() {
+        return mCellSignalStrengthLte;
+    }
+    /** @hide */
+    public void setCellSignalStrength(CellSignalStrengthLte 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());
+        dest.writeInt(TYPE_LTE);
+        super.writeToParcel(dest, flags);
+        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..581efc2
--- /dev/null
+++ b/telephony/java/android/telephony/CellSignalStrength.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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Abstract base class for cell phone signal strength related information.
+ */
+public abstract class CellSignalStrength 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;
+
+
+    /** @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);
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public abstract void writeToParcel(Parcel dest, int flags);
+
+    /** Implement the Parcelable interface */
+    public static final Creator<CellSignalStrength> CREATOR =
+            new Creator<CellSignalStrength>() {
+        @Override
+        public CellSignalStrength createFromParcel(Parcel in) {
+            int type = in.readInt();
+            switch (type) {
+                case TYPE_GSM: return CellSignalStrengthGsm.createFromParcelBody(in);
+                case TYPE_CDMA: return CellSignalStrengthCdma.createFromParcelBody(in);
+                case TYPE_LTE: return CellSignalStrengthLte.createFromParcelBody(in);
+                default: throw new RuntimeException("Bad CellSignalStrength Parcel");
+            }
+        }
+
+        @Override
+        public CellSignalStrength[] newArray(int size) {
+            return new CellSignalStrength[size];
+        }
+    };
+}
diff --git a/telephony/java/android/telephony/CellSignalStrengthCdma.java b/telephony/java/android/telephony/CellSignalStrengthCdma.java
new file mode 100644
index 0000000..3912629
--- /dev/null
+++ b/telephony/java/android/telephony/CellSignalStrengthCdma.java
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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 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(CellSignalStrength.TYPE_CDMA);
+        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) {
+            if (in.readInt() != CellSignalStrength.TYPE_CDMA) {
+                throw new RuntimeException("Expecting TYPE_CDMA");
+            }
+            return createFromParcelBody(in);
+        }
+
+        @Override
+        public CellSignalStrengthCdma[] newArray(int size) {
+            return new CellSignalStrengthCdma[size];
+        }
+    };
+
+    /** @hide */
+    public static CellSignalStrengthCdma createFromParcelBody(Parcel in) {
+        return new CellSignalStrengthCdma(in);
+    }
+
+    /**
+     * 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..30b444b
--- /dev/null
+++ b/telephony/java/android/telephony/CellSignalStrengthGsm.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 android.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * LTE signal strength related information.
+ */
+public 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(CellSignalStrength.TYPE_GSM);
+        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) {
+            if (in.readInt() != CellSignalStrength.TYPE_GSM) {
+                throw new RuntimeException("Expecting TYPE_GSM");
+            }
+            return createFromParcelBody(in);
+        }
+
+        @Override
+        public CellSignalStrengthGsm[] newArray(int size) {
+            return new CellSignalStrengthGsm[size];
+        }
+    };
+
+    /** @hide */
+    public static CellSignalStrengthGsm createFromParcelBody(Parcel in) {
+        return new CellSignalStrengthGsm(in);
+    }
+
+    /**
+     * 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..7a4d626
--- /dev/null
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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 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(CellSignalStrength.TYPE_LTE);
+        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) {
+            if (in.readInt() != CellSignalStrength.TYPE_LTE) {
+                throw new RuntimeException("Expecting TYPE_LTE");
+            }
+            return createFromParcelBody(in);
+        }
+
+        @Override
+        public CellSignalStrengthLte[] newArray(int size) {
+            return new CellSignalStrengthLte[size];
+        }
+    };
+
+    /** @hide */
+    public static CellSignalStrengthLte createFromParcelBody(Parcel in) {
+        return new CellSignalStrengthLte(in);
+    }
+
+    /**
+     * 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..15ffd63 100755
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1271,8 +1271,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..5c9282e 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();
@@ -471,7 +524,23 @@
     }
 
     @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..cd7ee76 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -39,7 +39,9 @@
 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 +140,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();
@@ -213,6 +221,13 @@
         throw new UnsupportedOperationException();
     }
 
+    /** @hide */
+    @Override
+    public List<ResolveInfo> queryIntentActivitiesForUser(Intent intent,
+                                                   int flags, int userId) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
             Intent[] specifics, Intent intent, int flags) {
@@ -224,6 +239,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();
@@ -479,7 +500,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 +535,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..9dfe4a1 100644
--- a/tests/ActivityTests/AndroidManifest.xml
+++ b/tests/ActivityTests/AndroidManifest.xml
@@ -20,6 +20,7 @@
     <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" />
     <application android:label="ActivityTest">
         <activity android:name="ActivityTestMain">
             <intent-filter>
@@ -27,5 +28,16 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+        <service android:name="SingleUserService"
+            android:singleUser="true" android:exported="true">
+        </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..2348e99 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
@@ -16,38 +16,53 @@
 
 package com.google.android.test.activity;
 
-import java.util.ArrayList;
 import java.util.List;
 
 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.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.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;
+
+    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 +116,12 @@
         super.onCreate(savedInstanceState);
 
         mAm = (ActivityManager)getSystemService(ACTIVITY_SERVICE);
+        if (savedInstanceState != null) {
+            mOverrideConfig = savedInstanceState.getParcelable(KEY_CONFIGURATION);
+            if (mOverrideConfig != null) {
+                applyOverrideConfiguration(mOverrideConfig);
+            }
+        }
     }
 
     @Override
@@ -114,6 +135,80 @@
                 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);
+                    }
+                };
+                bindService(intent, conn, Context.BIND_AUTO_CREATE);
+                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 1!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+            @Override public boolean onMenuItemClick(MenuItem item) {
+                Intent intent = new Intent(ActivityTestMain.this, UserTarget.class);
+                sendOrderedBroadcastAsUser(intent, new UserHandle(1), null,
+                        new BroadcastResultReceiver(), 
+                        null, Activity.RESULT_OK, null, null);
+                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 +218,14 @@
         buildUi();
     }
 
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        if (mOverrideConfig != null) {
+            outState.putParcelable(KEY_CONFIGURATION, mOverrideConfig);
+        }
+    }
+
     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/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..c40582a
--- /dev/null
+++ b/tests/ActivityTests/src/com/google/android/test/activity/SingleUserService.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.google.android.test.activity;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+
+public class SingleUserService extends Service {
+    Binder mBinder = new Binder();
+
+    @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..4e229ec 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -33,6 +33,42 @@
         <meta-data android:name="android.graphics.renderThread" android:value="true" />
 
         <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="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 +78,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 +195,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 +331,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/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/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/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/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/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/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 2edfec7..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..7b8ec04
--- /dev/null
+++ b/tests/RenderScriptTests/ComputeBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rs
@@ -0,0 +1,408 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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(approx_recip);
+    BENCH_FN_FUNC_FN(approx_sqrt);
+    BENCH_FN_FUNC_FN(approx_rsqrt);
+    BENCH_FN_FUNC_FN(approx_length);
+    BENCH_FN_FUNC_FN_FN(approx_distance);
+    BENCH_FN_FUNC_FN(approx_normalize);
+    BENCH_FN_FUNC_FN(approx_atan);
+}
+
+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..434d592 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/img640x427.jpg b/tests/RenderScriptTests/ImageProcessing/res/drawable-nodpi/img640x427.jpg
new file mode 100644
index 0000000..5bce392
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/res/drawable-nodpi/img640x427.jpg
Binary files differ
diff --git a/tests/RenderScriptTests/ImageProcessing/res/layout/main.xml b/tests/RenderScriptTests/ImageProcessing/res/layout/main.xml
index 08a010d..bd56d62 100644
--- a/tests/RenderScriptTests/ImageProcessing/res/layout/main.xml
+++ b/tests/RenderScriptTests/ImageProcessing/res/layout/main.xml
@@ -50,8 +50,12 @@
                         android:textSize="8pt"
                         android:text="@string/saturation"/>
             </LinearLayout>
+            <Spinner
+                android:id="@+id/filterselection"
+                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 +63,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 +77,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 +91,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,49 +105,21 @@
                 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: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/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:id="@+id/slider5"
                 android:layout_marginLeft="10sp"
                 android:layout_marginRight="10sp"
                 android:layout_width="match_parent"
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/src/com/android/rs/image/Blur25.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Blur25.java
new file mode 100644
index 0000000..9728c12
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Blur25.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.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 ScriptC_vertical_blur mScriptVBlur;
+    private ScriptC_horizontal_blur mScriptHBlur;
+    private int 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 boolean onBar2Setup(SeekBar b, TextView t) {
+        b.setProgress(50);
+        t.setText("Saturation");
+        return true;
+    }
+
+
+    public void onBar1Changed(int progress) {
+        float fRadius = progress / 100.0f;
+        fRadius *= (float)(MAX_RADIUS);
+        mRadius = (int)fRadius;
+        mScript.set_radius(mRadius);
+    }
+    public void onBar2Changed(int progress) {
+        mSaturation = (float)progress / 50.0f;
+        mScriptVBlur.invoke_setSaturation(mSaturation);
+    }
+
+
+    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(25.f);
+            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());
+
+            mScriptVBlur = new ScriptC_vertical_blur(mRS, res, R.raw.vertical_blur);
+            mScriptHBlur = new ScriptC_horizontal_blur(mRS, res, R.raw.horizontal_blur);
+
+            mScript = new ScriptC_threshold(mRS, res, R.raw.threshold);
+            mScript.set_width(width);
+            mScript.set_height(height);
+            mScript.set_radius(mRadius);
+
+            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);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mOutPixelsAllocation);
+        } else {
+            mScript.invoke_filter();
+        }
+    }
+
+    public void setupBenchmark() {
+        if (mUseIntrinsic) {
+            mIntrinsic.setRadius(MAX_RADIUS);
+        } else {
+            mScript.set_radius(MAX_RADIUS);
+        }
+    }
+
+    public void exitBenchmark() {
+        if (mUseIntrinsic) {
+            mIntrinsic.setRadius(mRadius);
+        } else {
+            mScript.set_radius(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..b3914d1
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Convolve5x5.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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;
+
+        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..cd54c2e
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Grain.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.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);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mInPixelsAllocation.getType().getX();
+        int height = mInPixelsAllocation.getType().getY();
+
+        Type.Builder tb = new Type.Builder(mRS, Element.U8(mRS));
+        tb.setX(width);
+        tb.setY(height);
+        mNoise = Allocation.createTyped(mRS, tb.create());
+        mNoise2 = Allocation.createTyped(mRS, tb.create());
+
+        mScript = new ScriptC_grain(mRS, res, R.raw.grain);
+        mScript.set_gWidth(width);
+        mScript.set_gHeight(height);
+        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..732da4e
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/GroupTest.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.renderscript.Matrix4f;
+import android.renderscript.ScriptGroup;
+import android.util.Log;
+
+public class GroupTest extends TestBase {
+    private ScriptC_convolve3x3 mConvolve;
+    private ScriptC_colormatrix 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 = new ScriptC_convolve3x3(mRS, res, R.raw.convolve3x3);
+        mMatrix = new ScriptC_colormatrix(mRS, res, R.raw.colormatrix);
+
+        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.set_gCoeffs(f);
+
+        Matrix4f m = new Matrix4f();
+        m.set(1, 0, 0.2f);
+        m.set(1, 1, 0.9f);
+        m.set(1, 2, 0.2f);
+        mMatrix.invoke_setMatrix(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.addConnection(connect, mConvolve, mMatrix, null);
+            mGroup = b.create();
+
+        } else {
+            mScratchPixelsAllocation1 = Allocation.createTyped(mRS, connect);
+        }
+    }
+
+    public void runTest() {
+        mConvolve.set_gIn(mInPixelsAllocation);
+        mConvolve.set_gWidth(mWidth);
+        mConvolve.set_gHeight(mHeight);
+        if (mUseNative) {
+            mGroup.setOutput(mMatrix, mOutPixelsAllocation);
+            mGroup.execute();
+        } else {
+            mConvolve.forEach_root(mScratchPixelsAllocation1);
+            mMatrix.forEach_root(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..7b84355 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,65 @@
 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 {
+                                       implements 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;
+    Bitmap mBitmapIn;
+    Bitmap mBitmapOut;
+    String mTestNames[];
 
-    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;
+    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);
-        }
-    }
-
-    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();
+            mTest.updateBitmap(mBitmapOut);
+            mDisplayView.invalidate();
         }
     }
 
@@ -156,103 +97,208 @@
     public void onStopTrackingTouch(SeekBar seekBar) {
     }
 
+    void setupBars() {
+        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) {
+        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;
+        }
+
+        mTest.createBaseTest(this, mBitmapIn);
+        setupBars();
+
+        mTest.runTest();
+        mTest.updateBitmap(mBitmapOut);
+        mDisplayView.invalidate();
+        mBenchmarkResult.setText("Result: not run");
+    }
+
+    void setupTests() {
+        mTestNames = new String[27];
+        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";
+        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);
+        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);
+        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);
 
-        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.setOnSeekBarChangeListener(this);
+        mBar2.setOnSeekBarChangeListener(this);
+        mBar3.setOnSeekBarChangeListener(this);
+        mBar4.setOnSeekBarChangeListener(this);
+        mBar5.setOnSeekBarChangeListener(this);
 
-        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);
+        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);
 
-        mGammaSeekBar = (SeekBar)findViewById(R.id.inGamma);
-        mGammaSeekBar.setOnSeekBarChangeListener(this);
-        mGammaSeekBar.setMax(150);
-        mGammaSeekBar.setProgress(100);
-
-        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 +316,41 @@
 
     // 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");
     }
 
     // For benchmark test
-    public long getBenchmark() {
+    public float getBenchmark() {
+        mDoingBenchmark = true;
+
+        mTest.setupBenchmark();
+        long result = 0;
+
+        Log.v(TAG, "Warming");
+        long t = java.lang.System.currentTimeMillis() + 2000;
+        do {
+            mTest.runTest();
+            mTest.finish();
+        } while (t > java.lang.System.currentTimeMillis());
+
+
         Log.v(TAG, "Benchmarking");
-        int oldRadius = mRadius;
-        mRadius = MAX_RADIUS;
-        mScript.set_radius(mRadius);
-
-        mScript.invoke_filter();
-        mRS.finish();
-
-        long t = java.lang.System.currentTimeMillis();
-
-        mScript.invoke_filter();
-        mOutPixelsAllocation.copyTo(mBitmapOut);
-
+        t = java.lang.System.currentTimeMillis();
+        for (int i=0; i<10; i++) {
+            mTest.runTest();
+        }
+        mTest.finish();
         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 /= 10;
 
-        mScript.invoke_filter();
-        mOutPixelsAllocation.copyTo(mBitmapOut);
-        return t;
+        Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + ft);
+        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/TestBase.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/TestBase.java
new file mode 100644
index 0000000..3a6241d
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/TestBase.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.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;
+
+public class TestBase  {
+    protected final String TAG = "Img";
+
+    protected RenderScript mRS;
+    protected Allocation mInPixelsAllocation;
+    protected Allocation mOutPixelsAllocation;
+
+    // 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 final void createBaseTest(ImageProcessingActivity act, Bitmap b) {
+        mRS = RenderScript.create(act);
+        mInPixelsAllocation = Allocation.createFromBitmap(mRS, b,
+                                                          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 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/colormatrix.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/colormatrix.rs
new file mode 100644
index 0000000..a83e819
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/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.image)
+#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/ImageProcessing/src/com/android/rs/image/convolve3x3.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve3x3.rs
new file mode 100644
index 0000000..455fcc2
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/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.image)
+#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-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(((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/ImageProcessing/src/com/android/rs/image/convolve5x5.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve5x5.rs
new file mode 100644
index 0000000..fe6cf31
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/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.image)
+#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(((uchar4 *)rsGetElementAt(gIn, x0, y0))[0]) * gCoeffs[0]
+              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x1, y0))[0]) * gCoeffs[1]
+              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x2, y0))[0]) * gCoeffs[2]
+              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x3, y0))[0]) * gCoeffs[3]
+              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x4, y0))[0]) * gCoeffs[4];
+
+    float4 p1 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x0, y1))[0]) * gCoeffs[5]
+              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x1, y1))[0]) * gCoeffs[6]
+              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x2, y1))[0]) * gCoeffs[7]
+              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x3, y1))[0]) * gCoeffs[8]
+              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x4, y1))[0]) * gCoeffs[9];
+
+    float4 p2 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x0, y2))[0]) * gCoeffs[10]
+              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x1, y2))[0]) * gCoeffs[11]
+              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x2, y2))[0]) * gCoeffs[12]
+              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x3, y2))[0]) * gCoeffs[13]
+              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x4, y2))[0]) * gCoeffs[14];
+
+    float4 p3 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x0, y3))[0]) * gCoeffs[15]
+              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x1, y3))[0]) * gCoeffs[16]
+              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x2, y3))[0]) * gCoeffs[17]
+              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x3, y3))[0]) * gCoeffs[18]
+              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x4, y3))[0]) * gCoeffs[19];
+
+    float4 p4 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x0, y4))[0]) * gCoeffs[20]
+              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x1, y4))[0]) * gCoeffs[21]
+              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x2, y4))[0]) * gCoeffs[22]
+              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x3, y4))[0]) * gCoeffs[23]
+              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x4, y4))[0]) * gCoeffs[24];
+
+    p0 = clamp(p0 + p1 + p2 + p3 + p4, 0.f, 255.f);
+    *out = convert_uchar4(p0);
+}
+
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/copy.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/copy.rs
new file mode 100644
index 0000000..9eb5d43
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/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.image)
+
+void root(const uchar4 *v_in, uchar4 *v_out) {
+    *v_out = *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..3809912
--- /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.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/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..008acbe
--- /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.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 = approx_rsqrt(dist2);
+    const float radian = M_PI_2 - approx_atan((alpha * approx_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/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.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_relaxed.rs
new file mode 100644
index 0000000..3e76368
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/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.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.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_relaxed.rs
new file mode 100644
index 0000000..dc3ffcb
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/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.image)
+#pragma rs_fp_relaxed
+
+#include "fisheye.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.rs
new file mode 100644
index 0000000..783bc4a
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/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.image)
+#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 gWidth;
+int32_t gHeight;
+
+rs_allocation gBlendSource;
+void blend9(uchar *out, uint32_t x, uint32_t y) {
+    uint32_t x1 = min((int32_t)x+1, (int32_t)(gWidth -1));
+    uint32_t x2 = max((int32_t)x-1, (int32_t)0);
+    uint32_t y1 = min((int32_t)y+1, (int32_t)(gHeight -1));
+    uint32_t y2 = max((int32_t)y-1, (int32_t)0);
+
+    uint p00 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x1, y1))[0];
+    uint p01 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x, y1))[0];
+    uint p02 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x2, y1))[0];
+    uint p10 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x1, y))[0];
+    uint p11 = 230 * ((uchar *)rsGetElementAt(gBlendSource, x, y))[0];
+    uint p12 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x2, y))[0];
+    uint p20 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x1, y2))[0];
+    uint p21 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x, y2))[0];
+    uint p22 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x2, y2))[0];
+
+    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) ((uchar *)rsGetElementAt(gNoise, x, y))[0];
+
+    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/ImageProcessing/src/com/android/rs/image/greyscale.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/greyscale.rs
new file mode 100644
index 0000000..c420cac
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/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.image)
+#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/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..7c5d930
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/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/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.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_relaxed.rs
new file mode 100644
index 0000000..b115445
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/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.image)
+#pragma rs_fp_relaxed
+
+#include "levels.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs
index d93238c..77cd5be 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs
@@ -88,6 +88,6 @@
 
     fs.ain = rsGetAllocation(ScratchPixel2);
     rsForEach(vBlurScript, fs.ain, rsGetAllocation(OutPixel), &fs, sizeof(fs));
-    rsSendToClientBlocking(CMD_FINISHED);
+    //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
index a6da192..60fd71b 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vertical_blur.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vertical_blur.rs
@@ -3,29 +3,9 @@
 
 #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;
 
@@ -52,10 +32,6 @@
     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;
@@ -76,12 +52,8 @@
     }
 
     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);
-
+    temp = clamp(temp, 0.f, 255.f);
     out->xyz = convert_uchar3(temp);
-    //output->w = input->w;
+    out->w = 0xff;
 }
 
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..a1e4ae5
--- /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.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/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..19d0117
--- /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.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 = approx_length(axis_scale * coord)  * sloped_inv_max_dist;
+    // TODO:  add approx_exp once implemented
+    const float lumen = opp_shade + shade * approx_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/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.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx_relaxed.rs
new file mode 100644
index 0000000..9120612
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/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.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.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_relaxed.rs
new file mode 100644
index 0000000..8e47ea9
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/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.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/layout/main.xml b/tests/RenderScriptTests/ImageProcessing2/res/layout/main.xml
new file mode 100644
index 0000000..bd56d62
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/res/layout/main.xml
@@ -0,0 +1,130 @@
+<?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"/>
+            <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"/>
+            </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..cc5cc4d
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/res/values/strings.xml
@@ -0,0 +1,33 @@
+<?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>
+
+</resources>
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..be87716
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blur25.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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 int MAX_RADIUS = 25;
+    private ScriptC_threshold mScript;
+    private ScriptC_vertical_blur mScriptVBlur;
+    private ScriptC_horizontal_blur mScriptHBlur;
+    private int mRadius = MAX_RADIUS;
+    private float mSaturation = 1.0f;
+    private Allocation mScratchPixelsAllocation1;
+    private Allocation mScratchPixelsAllocation2;
+
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Radius");
+        b.setProgress(100);
+        return true;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        b.setProgress(50);
+        t.setText("Saturation");
+        return true;
+    }
+
+
+    public void onBar1Changed(int progress) {
+        float fRadius = progress / 100.0f;
+        fRadius *= (float)(MAX_RADIUS);
+        mRadius = (int)fRadius;
+        mScript.set_radius(mRadius);
+    }
+    public void onBar2Changed(int progress) {
+        mSaturation = (float)progress / 50.0f;
+        mScriptVBlur.invoke_setSaturation(mSaturation);
+    }
+
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mInPixelsAllocation.getType().getX();
+        int height = mInPixelsAllocation.getType().getY();
+
+        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());
+
+        mScriptVBlur = new ScriptC_vertical_blur(mRS, res, R.raw.vertical_blur);
+        mScriptHBlur = new ScriptC_horizontal_blur(mRS, res, R.raw.horizontal_blur);
+
+        mScript = new ScriptC_threshold(mRS, res, R.raw.threshold);
+        mScript.set_width(width);
+        mScript.set_height(height);
+        mScript.set_radius(mRadius);
+
+        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);
+    }
+
+    public void runTest() {
+        mScript.invoke_filter();
+    }
+
+    public void setupBenchmark() {
+        mScript.set_radius(MAX_RADIUS);
+    }
+
+    public void exitBenchmark() {
+        mScript.set_radius(mRadius);
+    }
+}
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..995cf9d
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Fisheye.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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 final boolean relaxed;
+    private float center_x = 0.5f;
+    private float center_y = 0.5f;
+    private float scale = 0.5f;
+
+    public Fisheye(boolean relaxed) {
+        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 (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 (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 (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..e00edd7
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Grain.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.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);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mInPixelsAllocation.getType().getX();
+        int height = mInPixelsAllocation.getType().getY();
+
+        Type.Builder tb = new Type.Builder(mRS, Element.U8(mRS));
+        tb.setX(width);
+        tb.setY(height);
+        mNoise = Allocation.createTyped(mRS, tb.create());
+        mNoise2 = Allocation.createTyped(mRS, tb.create());
+
+        mScript = new ScriptC_grain(mRS, res, R.raw.grain);
+        mScript.set_gWidth(width);
+        mScript.set_gHeight(height);
+        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..b9fbb59
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/GroupTest.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.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class GroupTest extends TestBase {
+    private ScriptC_convolve3x3 mConvolve;
+    private ScriptC_colormatrix 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 = new ScriptC_convolve3x3(mRS, res, R.raw.convolve3x3);
+        mMatrix = new ScriptC_colormatrix(mRS, res, R.raw.colormatrix);
+
+        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.set_gCoeffs(f);
+
+        Matrix4f m = new Matrix4f();
+        m.set(1, 0, 0.2f);
+        m.set(1, 1, 0.9f);
+        m.set(1, 2, 0.2f);
+        mMatrix.invoke_setMatrix(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.addConnection(connect, mConvolve, mMatrix, null);
+            mGroup = b.create();
+
+        } else {
+            mScratchPixelsAllocation1 = Allocation.createTyped(mRS, connect);
+        }
+    }
+
+    public void runTest() {
+        mConvolve.set_gIn(mInPixelsAllocation);
+        mConvolve.set_gWidth(mWidth);
+        mConvolve.set_gHeight(mHeight);
+        if (mUseNative) {
+            mGroup.setOutput(mMatrix, mOutPixelsAllocation);
+            mGroup.execute();
+        } else {
+            mConvolve.forEach_root(mScratchPixelsAllocation1);
+            mMatrix.forEach_root(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..9b36da14
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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;
+
+public class ImageProcessingActivity2 extends Activity
+                                       implements SeekBar.OnSeekBarChangeListener {
+    private final String TAG = "Img";
+    Bitmap mBitmapIn;
+    Bitmap mBitmapOut;
+    String mTestNames[];
+
+    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 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();
+            mTest.updateBitmap(mBitmapOut);
+            mDisplayView.invalidate();
+        }
+    }
+
+    public void onStartTrackingTouch(SeekBar seekBar) {
+    }
+
+    public void onStopTrackingTouch(SeekBar seekBar) {
+    }
+
+    void setupBars() {
+        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) {
+        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();
+            break;
+        case 5:
+            mTest = new Greyscale();
+            break;
+        case 6:
+            mTest = new Grain();
+            break;
+        case 7:
+            mTest = new Fisheye(false);
+            break;
+        case 8:
+            mTest = new Fisheye(true);
+            break;
+        case 9:
+            mTest = new Vignette(false);
+            break;
+        case 10:
+            mTest = new Vignette(true);
+            break;
+        case 11:
+            mTest = new GroupTest(false);
+            break;
+        case 12:
+            mTest = new GroupTest(true);
+            break;
+        }
+
+        mTest.createBaseTest(this, mBitmapIn);
+        setupBars();
+
+        mTest.runTest();
+        mTest.updateBitmap(mBitmapOut);
+        mDisplayView.invalidate();
+        mBenchmarkResult.setText("Result: not run");
+    }
+
+    void setupTests() {
+        mTestNames = new String[13];
+        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] = "Greyscale";
+        mTestNames[6] = "Grain";
+        mTestNames[7] = "Fisheye Full";
+        mTestNames[8] = "Fisheye Relaxed";
+        mTestNames[9] = "Vignette Full";
+        mTestNames[10] = "Vignette Relaxed";
+        mTestNames[11] = "Group Test (emulated)";
+        mTestNames[12] = "Group Test (native)";
+        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);
+
+        mSurfaceView = (SurfaceView) findViewById(R.id.surface);
+
+        mDisplayView = (ImageView) findViewById(R.id.display);
+        mDisplayView.setImageBitmap(mBitmapOut);
+
+        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) {
+        long t = getBenchmark();
+        //long javaTime = javaFilter();
+        //mBenchmarkResult.setText("RS: " + t + " ms  Java: " + javaTime + " ms");
+        mBenchmarkResult.setText("Result: " + t + " ms");
+    }
+
+    // For benchmark test
+    public long getBenchmark() {
+        mDoingBenchmark = true;
+
+        mTest.setupBenchmark();
+        long result = 0;
+
+        Log.v(TAG, "Warming");
+        long t = java.lang.System.currentTimeMillis() + 2000;
+        do {
+            mTest.runTest();
+            mTest.finish();
+        } while (t > java.lang.System.currentTimeMillis());
+
+
+        Log.v(TAG, "Benchmarking");
+        t = java.lang.System.currentTimeMillis();
+        mTest.runTest();
+        mTest.finish();
+        t = java.lang.System.currentTimeMillis() - t;
+
+        Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t);
+        mTest.exitBenchmark();
+        mDoingBenchmark = false;
+
+        return t;
+    }
+}
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/TestBase.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/TestBase.java
new file mode 100644
index 0000000..35170af
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/TestBase.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.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;
+
+public class TestBase  {
+    protected final String TAG = "Img";
+
+    protected RenderScript mRS;
+    protected Allocation mInPixelsAllocation;
+    protected Allocation mOutPixelsAllocation;
+
+    // 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 final void createBaseTest(ImageProcessingActivity2 act, Bitmap b) {
+        mRS = RenderScript.create(act);
+        mInPixelsAllocation = Allocation.createFromBitmap(mRS, b,
+                                                          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 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..fc69eba
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Vignette.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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 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 relaxed) {
+        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 (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 (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 (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/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/fisheye.rsh b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye.rsh
new file mode 100644
index 0000000..4dcfc1d
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye.rsh
@@ -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.
+ */
+
+rs_allocation in_alloc;
+rs_sampler sampler;
+
+static float2 center, dimensions;
+static float2 scale;
+static float alpha;
+static float radius2;
+static float factor;
+
+void init_filter(uint32_t dim_x, uint32_t dim_y, float focus_x, float focus_y, float k) {
+    center.x = focus_x;
+    center.y = focus_y;
+    dimensions.x = (float)dim_x;
+    dimensions.y = (float)dim_y;
+
+    alpha = k * 2.0 + 0.75;
+    float bound2 = 0.25;
+    if (dim_x > dim_y) {
+        scale.x = 1.0;
+        scale.y = dimensions.y / dimensions.x;
+        bound2 *= (scale.y*scale.y + 1);
+    } else {
+        scale.x = dimensions.x / dimensions.y;
+        scale.y = 1.0;
+        bound2 *= (scale.x*scale.x + 1);
+    }
+    const float bound = sqrt(bound2);
+    const float radius = 1.15 * bound;
+    radius2 = radius*radius;
+    const float max_radian = 0.5f * M_PI - 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
+    float2 coord;
+    coord.x = (float)x / dimensions.x;
+    coord.y = (float)y / dimensions.y;
+    coord -= center;
+    const float dist = length(scale * coord);
+    const float radian = M_PI_2 - atan((alpha * sqrt(radius2 - dist * dist)) / dist);
+    const float scalar = radian * factor / dist;
+    const float2 new_coord = 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_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..75f4021
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.rs
@@ -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.
+ */
+
+#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 gWidth;
+int32_t gHeight;
+
+rs_allocation gBlendSource;
+void blend9(uchar *out, uint32_t x, uint32_t y) {
+    uint32_t x1 = min(x+1, (uint32_t)gWidth);
+    uint32_t x2 = max(x-1, (uint32_t)0);
+    uint32_t y1 = min(y+1, (uint32_t)gHeight);
+    uint32_t y2 = max(y-1, (uint32_t)0);
+
+    uint p00 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x1, y1))[0];
+    uint p01 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x, y1))[0];
+    uint p02 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x2, y1))[0];
+    uint p10 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x1, y))[0];
+    uint p11 = 230 * ((uchar *)rsGetElementAt(gBlendSource, x, y))[0];
+    uint p12 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x2, y))[0];
+    uint p20 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x1, y2))[0];
+    uint p21 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x, y2))[0];
+    uint p22 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x2, y2))[0];
+
+    p00 += p01;
+    p02 += p10;
+    p11 += p12;
+    p20 += p21;
+
+    p22 += p00;
+    p02 += p11;
+
+    p20 += p22;
+    p20 += p02;
+
+    *out = (uchar)(p20 >> 10);
+}
+
+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) ((uchar *)rsGetElementAt(gNoise, x, y))[0];
+
+    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/horizontal_blur.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/horizontal_blur.rs
new file mode 100644
index 0000000..ee83496
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/horizontal_blur.rs
@@ -0,0 +1,28 @@
+#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/ImageProcessing2/src/com/android/rs/image/ip.rsh b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ip.rsh
new file mode 100644
index 0000000..0cdf9e1
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ip.rsh
@@ -0,0 +1,15 @@
+#pragma rs java_package_name(com.android.rs.image2)
+
+#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/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/threshold.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/threshold.rs
new file mode 100644
index 0000000..77cd5be
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/threshold.rs
@@ -0,0 +1,93 @@
+#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/ImageProcessing2/src/com/android/rs/image/vertical_blur.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vertical_blur.rs
new file mode 100644
index 0000000..60fd71b
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vertical_blur.rs
@@ -0,0 +1,59 @@
+#pragma version(1)
+#pragma rs_fp_relaxed
+
+#include "ip.rsh"
+
+static float saturation;
+static rs_matrix3x3 colorMat;
+
+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 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);
+    out->xyz = convert_uchar3(temp);
+    out->w = 0xff;
+}
+
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_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..f21331f
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/CameraPreviewActivity.java
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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);
+            mFilterYuv.copyOut(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..cced198
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/RsYuv.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.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;
+
+    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);
+
+        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));
+
+        mScript.bind_gYuvIn(mAllocationIn);
+    }
+
+    private long mTiming[] = new long[50];
+    private int mTimingSlot = 0;
+
+    void execute(byte[] yuv) {
+        mAllocationIn.copyFrom(yuv);
+        mRS.finish();
+
+        long t1 = java.lang.System.currentTimeMillis();
+        mScript.forEach_root(mAllocationOut);
+        mRS.finish();
+        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("yuv", "core time = " + total);
+            mTimingSlot = 0;
+        }
+    }
+
+    void copyOut(Bitmap b) {
+        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..6057eff
--- /dev/null
+++ b/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/yuv.rs
@@ -0,0 +1,132 @@
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.livepreview)
+#pragma rs_fp_relaxed
+
+uchar *gYuvIn;
+
+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(uchar4 *out, uint32_t x, uint32_t y) {
+    uchar Y = gYuvIn[(y * gWidth) + x];
+    uchar *uv = &gYuvIn[gWidth * gHeight];
+    uv += (((x>>1)<<1) + (y>>1) * gWidth);
+
+    uchar4 p = rsYuvToRGBA_uchar4(Y, uv[1], uv[0]);
+    p = crossProcess_i(p);
+    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..4d6fd10 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
@@ -67,6 +67,7 @@
         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_clamp(this, mRes, mCtx));
@@ -84,6 +85,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_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_element.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_element.java
index f52fe6f..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_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..40f7213
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_agree.java
@@ -0,0 +1,539 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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);
+        // FIXME:  generate signed char vectors once bug 6865598 is fixed
+        /*
+        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));
+        // FIXME:  set char input vectors once bug 6865598 is fixed
+        /*
+        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)));
+        // FIXME:  set char min reference vectors once bug 6865598 is fixed
+        /*
+        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)));
+        // FIXME:  set signed char max reference vectors once bug 6865598 is fixed
+        /*
+        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/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/math_agree.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/math_agree.rs
new file mode 100644
index 0000000..1adb036
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/math_agree.rs
@@ -0,0 +1,412 @@
+#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_UC_UC_ALL(func)            \
+TEST_SS_SS_ALL(func)            \
+TEST_US_US_ALL(func)            \
+TEST_SI_SI_ALL(func)            \
+TEST_UI_UI_ALL(func)
+
+// FIXME:  Add char tests back in once bug 6865598 is fixed
+#if 0
+TEST_SC_SC_ALL(func)
+#endif
+// 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/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..e38bb6c 100644
--- a/tests/StatusBar/src/com/android/statusbartest/PowerTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/PowerTest.java
@@ -16,32 +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.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,6 +84,28 @@
                 mProx.release(PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE);
             }
         },
+        new Test("Enable proximity, wait 5 seconds then disable") {
+            public void run() {
+                mProx.acquire();
+                mHandler.postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        mProx.release();
+                    }
+                }, 5000);
+            }
+        },
+        new Test("Enable proximity, wait 5 seconds then disable  (WAIT_FOR_PROXIMITY_NEGATIVE)") {
+            public void run() {
+                mProx.acquire();
+                mHandler.postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        mProx.release(PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE);
+                    }
+                }, 5000);
+            }
+        },
         new Test("Touch events don't poke") {
             public void run() {
                 mPokeState |= LocalPowerManager.POKE_LOCK_IGNORE_TOUCH_EVENTS;
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/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/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/src/android/os/SystemClock_Delegate.java b/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java
index bd332a6..26cb97b 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 elapsedRealtimeNano() {
+        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/Display_Delegate.java b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java
index 8868c65..6ccdcb6 100644
--- a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java
@@ -31,57 +31,4 @@
  */
 public class Display_Delegate {
 
-    // ---- Overridden methods ----
-
-    @LayoutlibDelegate
-    public static IWindowManager getWindowManager() {
-        return RenderAction.getCurrentContext().getIWindowManager();
-    }
-
-    // ---- 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/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 3ae660d..428c4c2 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
@@ -61,10 +61,13 @@
 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.CompatibilityInfoHolder;
+import android.view.Display;
 import android.view.Surface;
 import android.view.View;
 import android.view.ViewGroup;
@@ -440,7 +443,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 +920,18 @@
     }
 
     @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 +1164,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 +1209,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 +1240,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 +1319,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 +1369,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..0c85204 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,7 +39,7 @@
     }
 
     @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.
     }
@@ -55,18 +55,7 @@
     }
 
     @Override
-    public int getSupportedWakeLockFlags() throws RemoteException {
-        // pass for now.
-        return 0;
-    }
-
-    @Override
-    public void goToSleep(long arg0) throws RemoteException {
-        // pass for now.
-    }
-
-    @Override
-    public void goToSleepWithReason(long arg0, int arg1) throws RemoteException {
+    public void goToSleep(long arg0, int arg1) throws RemoteException {
         // pass for now.
     }
 
@@ -91,17 +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 {
+    public void setMaximumScreenOffTimeoutFromDeviceAdmin(int arg0) throws RemoteException {
         // pass for now.
     }
 
@@ -121,12 +110,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
index 8ab875f..b8d21f3 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
@@ -22,7 +22,6 @@
 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;
@@ -31,15 +30,13 @@
 import android.view.Display_Delegate;
 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.InputChannel;
-import android.view.InputDevice;
-import android.view.InputEvent;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
+import android.view.WindowInfo;
 
 import java.util.List;
 
@@ -72,23 +69,6 @@
         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
@@ -111,9 +91,13 @@
     }
 
     @Override
-    public void clearForcedDisplaySize() throws RemoteException {
+    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
@@ -123,6 +107,16 @@
     }
 
     @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
 
@@ -240,7 +234,7 @@
 
     @Override
     public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY,
-            IRemoteCallback startedCallback, boolean delayed) throws RemoteException {
+            IRemoteCallback startedCallback, boolean scaleUp) throws RemoteException {
         // TODO Auto-generated method stub
     }
 
@@ -281,7 +275,8 @@
     }
 
     @Override
-    public Bitmap screenshotApplications(IBinder arg0, int arg1, int arg2) throws RemoteException {
+    public Bitmap screenshotApplications(IBinder arg0, int displayId, int arg1, int arg2)
+            throws RemoteException {
         // TODO Auto-generated method stub
         return null;
     }
@@ -307,7 +302,6 @@
     @Override
     public void setAppOrientation(IApplicationToken arg0, int arg1) throws RemoteException {
         // TODO Auto-generated method stub
-
     }
 
     @Override
@@ -315,7 +309,6 @@
             CharSequence arg4, int arg5, int arg6, int arg7, IBinder arg8, boolean arg9)
             throws RemoteException {
         // TODO Auto-generated method stub
-
     }
 
     @Override
@@ -327,37 +320,36 @@
     @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 {
+    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
@@ -368,19 +360,16 @@
     @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
@@ -392,13 +381,11 @@
     @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
@@ -410,7 +397,6 @@
     @Override
     public void thawRotation() throws RemoteException {
         // TODO Auto-generated method stub
-
     }
 
     @Override
@@ -455,4 +441,51 @@
     public void lockNow() {
         // TODO Auto-generated method stub
     }
+
+    @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/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/impl/RenderAction.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
index 7323c6a..de65fd4 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
@@ -100,7 +100,7 @@
 
         // setup the display Metrics.
         DisplayMetrics metrics = new DisplayMetrics();
-        metrics.densityDpi = mParams.getDensity().getDpiValue();
+        metrics.densityDpi = metrics.noncompatDensityDpi = mParams.getDensity().getDpiValue();
 
         metrics.density = metrics.noncompatDensity =
                 metrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT;
@@ -335,6 +335,7 @@
         } else {
             config.smallestScreenWidthDp = config.screenWidthDp;
         }
+        config.densityDpi = density.getDpiValue();
 
         // never run in compat mode:
         config.compatScreenWidthDp = config.screenWidthDp;
diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp
index 673a650..1579e6a 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..aa59158 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();
     }
 
     /**
@@ -890,6 +906,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 +1154,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 +1202,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 +1230,153 @@
         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;
+                    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 +1387,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 +1410,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 +1434,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 +1453,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 +1521,8 @@
             return mService.getWifiServiceMessenger();
         } catch (RemoteException e) {
             return null;
+        } catch (SecurityException e) {
+            return null;
         }
     }
 
@@ -1492,8 +1539,6 @@
         }
     }
 
-
-
     /**
      * Returns the file in which IP and proxy configuration data is stored
      * @hide
@@ -1926,4 +1971,11 @@
              return false;
         }
     }
+
+    /** @hide */
+    public void captivePortalCheckComplete() {
+        try {
+            mService.captivePortalCheckComplete();
+        } catch (RemoteException e) {}
+    }
 }
diff --git a/wifi/java/android/net/wifi/WifiMonitor.java b/wifi/java/android/net/wifi/WifiMonitor.java
index 17c930b..ab54a15 100644
--- a/wifi/java/android/net/wifi/WifiMonitor.java
+++ b/wifi/java/android/net/wifi/WifiMonitor.java
@@ -645,9 +645,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 +693,7 @@
             if (newSupplicantState == SupplicantState.INVALID) {
                 Log.w(TAG, "Invalid supplicant state: " + newState);
             }
-            notifySupplicantStateChange(networkId, SSID, BSSID, newSupplicantState);
+            notifySupplicantStateChange(networkId, wifiSsid, BSSID, newSupplicantState);
         }
     }
 
@@ -739,13 +742,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..6f36111
--- /dev/null
+++ b/wifi/java/android/net/wifi/WifiSsid.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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('\\');
+                            break;
+                        case '"':
+                            octets.write('"');
+                            break;
+                        case 'n':
+                            octets.write('\n');
+                            break;
+                        case 'r':
+                            octets.write('\r');
+                            break;
+                        case 't':
+                            octets.write('\t');
+                            break;
+                        case 'e':
+                            octets.write(27); //escape char
+                            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() {
+        if (octets.size() <= 0) 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(octets.toByteArray()), out, true);
+        out.flip();
+        if (result.isError()) {
+            return NONE;
+        }
+        return out.toString();
+    }
+
+    /** @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..4aa092b 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,11 @@
     private ConnectivityManager mCm;
 
     private final boolean mP2pSupported;
+    private final AtomicBoolean mP2pConnected = new AtomicBoolean(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 +140,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 +257,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 +338,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;
@@ -390,21 +384,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;
@@ -466,6 +471,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 +597,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.Secure.getInt(mContext.getContentResolver(),
+                    Settings.Secure.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1);
 
         mContext.registerReceiver(
             new BroadcastReceiver() {
@@ -622,32 +632,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 +659,16 @@
                 },
                 new IntentFilter(ACTION_DELAYED_DRIVER_STOP));
 
+        mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
+                Settings.Secure.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED), false,
+                new ContentObserver(getHandler()) {
+                    @Override
+                    public void onChange(boolean selfChange) {
+                        mUserWantsSuspendOpt.set(Settings.Secure.getInt(mContext.getContentResolver(),
+                                Settings.Secure.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1);
+                    }
+                });
+
         mScanResultCache = new LruCache<String, ScanResult>(SCAN_RESULT_CACHE_SIZE);
 
         PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
@@ -682,6 +693,7 @@
                         addState(mL2ConnectedState, mConnectModeState);
                             addState(mObtainingIpState, mL2ConnectedState);
                             addState(mVerifyingLinkState, mL2ConnectedState);
+                            addState(mCaptivePortalCheckState, mL2ConnectedState);
                             addState(mConnectedState, mL2ConnectedState);
                         addState(mDisconnectingState, mConnectModeState);
                         addState(mDisconnectedState, mConnectModeState);
@@ -852,6 +864,10 @@
         }
     }
 
+    public void captivePortalCheckComplete() {
+        sendMessage(obtainMessage(CMD_CAPTIVE_CHECK_COMPLETE));
+    }
+
     /**
      * TODO: doc
      */
@@ -878,7 +894,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;
+        }
     }
 
     /**
@@ -1143,6 +1165,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 +1184,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 +1197,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 +1208,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);
@@ -1293,6 +1336,30 @@
         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 +1381,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 +1406,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 +1568,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);
@@ -1550,14 +1617,14 @@
     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.sendBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     private void sendNetworkStateChangeBroadcast(String bssid) {
@@ -1571,21 +1638,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 +1666,7 @@
         }
 
         if (state != mNetworkInfo.getDetailedState()) {
-            mNetworkInfo.setDetailedState(state, null, null);
+            mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID());
         }
     }
 
@@ -1624,11 +1691,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 +1713,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 +1772,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 +1856,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 +1917,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 +1968,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 +2009,13 @@
                     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;
                 default:
                     loge("Error! unhandled message" + message);
@@ -2336,10 +2414,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);
@@ -2474,6 +2552,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 +2719,6 @@
                 mWifiNative.stopFilteringMulticastV4Packets();
             }
 
-            mWifiNative.setPowerSave(mPowerSaveEnabled);
-
             if (mIsScanMode) {
                 mWifiNative.setScanResultHandling(SCAN_ONLY_MODE);
                 mWifiNative.disconnect();
@@ -2654,9 +2733,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) {
@@ -2765,20 +2854,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 +2879,9 @@
             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);
         }
     }
 
@@ -3140,10 +3227,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 +3260,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 +3328,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 +3355,6 @@
                     } catch (IllegalStateException e) {
                         loge("Failed to enable IPv6: " + e);
                     }
-
                     setNetworkDetailedState(DetailedState.CONNECTED);
                     mWifiConfigStore.updateStatus(mLastNetworkId, DetailedState.CONNECTED);
                     sendNetworkStateChangeBroadcast(mLastBssid);
@@ -3354,8 +3465,8 @@
             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,
+            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 +3492,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 +3503,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 +3564,21 @@
                     /* 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);
+                    }
                 default:
                     ret = NOT_HANDLED;
             }
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index bfb91e2..a5a2469 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -23,6 +23,7 @@
 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;
@@ -113,6 +114,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}
      */
@@ -235,9 +244,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..7fa6aac 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,221 @@
     /* 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;
+    /*
+     * 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 +312,7 @@
 
         setupNetworkReceiver();
 
-        // The content observer to listen needs a handler
+        // the content observer to listen needs a handler
         registerForSettingsChanges();
         registerForWatchdogToggle();
         addState(mDefaultState);
@@ -243,9 +321,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,15 +340,14 @@
                 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
+        // disable poor network avoidance
         if (sWifiOnly) {
-            log("Disabling poor network avoidance for wi-fi only device");
+            logd("Disabling poor network avoidance for wi-fi only device");
             putSettingsBoolean(contentResolver,
                     Settings.Secure.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED, false);
         }
@@ -286,15 +362,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 +384,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);
     }
 
@@ -334,59 +418,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),
-                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 +428,29 @@
         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);
+        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);
-        } else {
-            notificationManager.cancel(WALLED_GARDEN_NOTIFICATION_ID, 1);
-        }
-        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 +458,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 +509,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 +521,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 (DBG) logd("Ignoring link verification, mWifiInfo is NULL");
+                                    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 +626,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 +678,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 +707,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 +723,10 @@
         }
 
         private void handleRssiChange() {
-            if (mCurrentSignalLevel <= RSSI_LEVEL_MONITOR) {
-                transitionTo(mRssiMonitoringState);
+            if (mCurrentSignalLevel <= LINK_MONITOR_LEVEL_THRESHOLD) {
+                transitionTo(mLinkMonitoringState);
             } else {
-                //stay here
+                // stay here
             }
         }
 
@@ -746,16 +735,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 +744,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,107 +855,75 @@
         }
    }
 
-    /* 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");
+    private void sendLinkStatusNotification(boolean isGood) {
+        if (DBG) logd("########################################");
+        if (isGood) {
+            mWsmChannel.sendMessage(GOOD_LINK_DETECTED);
+            mCurrentBssid.mLastTimeGood = SystemClock.elapsedRealtime();
+            logd("Good link notification is sent");
         } else {
-
-            if (mMinIntervalArrayIndex < MIN_INTERVAL_AVOID_BSSID_MS.length - 1) {
-                mMinIntervalArrayIndex++;
-            }
-            if (DBG) log("mMinIntervalArrayIndex: " + mMinIntervalArrayIndex);
+            mWsmChannel.sendMessage(POOR_LINK_DETECTED);
+            mCurrentBssid.mLastTimePoor = SystemClock.elapsedRealtime();
+            logd("Poor link notification is sent");
         }
-
-        mLastBssidAvoidedTime = android.os.SystemClock.elapsedRealtime();
     }
 
     /**
@@ -932,30 +942,28 @@
     }
 
     /**
-     * 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.
+     * 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.
+     * @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.
@@ -966,11 +974,258 @@
         return Settings.Secure.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/WifiP2pDevice.java b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
index c86ec8b..863a055 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;
         }
 
@@ -273,6 +282,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 +302,7 @@
             deviceCapability = source.deviceCapability;
             groupCapability = source.groupCapability;
             status = source.status;
+            wfdInfo = source.wfdInfo;
         }
     }
 
@@ -305,6 +316,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 +337,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..2093bda 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
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..35dd764 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;
@@ -134,19 +135,7 @@
     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 = 5;
 
     private static final int BASE = Protocol.BASE_WIFI_P2P_SERVICE;
 
@@ -158,6 +147,9 @@
     /* User rejected a peer request */
     private static final int PEER_CONNECTION_USER_REJECT    =   BASE + 3;
 
+    /* Commands to the WifiStateMachine */
+    public static final int P2P_CONNECTION_CHANGED         =   BASE + 11;
+
     private final boolean mP2pSupported;
 
     private WifiP2pDevice mThisDevice = new WifiP2pDevice();
@@ -358,8 +350,8 @@
         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();
+        private final WifiP2pGroupList mGroups = new WifiP2pGroupList(null,
                 new GroupDeleteListener() {
             @Override
             public void onDeleteGroup(int netId) {
@@ -369,7 +361,7 @@
                 sendP2pPersistentGroupsChangedBroadcast();
             }
         });
-        private WifiP2pInfo mWifiP2pInfo = new WifiP2pInfo();
+        private final WifiP2pInfo mWifiP2pInfo = new WifiP2pInfo();
         private WifiP2pGroup mGroup;
 
         // Saved WifiP2pConfig for a peer connection
@@ -495,18 +487,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(
@@ -628,6 +627,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;
             }
@@ -740,6 +743,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 +753,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();
@@ -1349,7 +1365,7 @@
                     }
 
                     if (mGroup.isGroupOwner()) {
-                        stopDhcpServer();
+                        stopDhcpServer(mGroup.getInterface());
                     } else {
                         if (DBG) logd("stop DHCP client");
                         mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP);
@@ -1475,7 +1491,7 @@
         public void exit() {
             mSavedProvDiscDevice = null;
             updateThisDevice(WifiP2pDevice.AVAILABLE);
-            setWifiP2pInfoOnGroupTermination();
+            resetWifiP2pInfo();
             mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
             sendP2pConnectionChangedBroadcast();
         }
@@ -1534,7 +1550,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 +1564,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 +1587,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,9 +1617,10 @@
         logd("Started Dhcp server on " + intf);
    }
 
-    private void stopDhcpServer() {
+    private void stopDhcpServer(String intf) {
         try {
             mNwService.stopTethering();
+            mNwService.clearInterfaceAddresses(intf);
         } catch (Exception e) {
             loge("Error stopping Dhcp server" + e);
             return;
@@ -1953,7 +1972,7 @@
         mWifiP2pInfo.groupOwnerAddress = NetworkUtils.numericToInetAddress(serverAddress);
     }
 
-    private void setWifiP2pInfoOnGroupTermination() {
+    private void resetWifiP2pInfo() {
         mWifiP2pInfo.groupFormed = false;
         mWifiP2pInfo.isGroupOwner = false;
         mWifiP2pInfo.groupOwnerAddress = null;
@@ -2016,6 +2035,27 @@
         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;
+    }
+
     private void initializeP2pSettings() {
         mWifiNative.setPersistentReconnect(true);
         mThisDevice.deviceName = getPersistedDeviceName();
@@ -2048,6 +2088,9 @@
     }
 
     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 */
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];
+            }
+        };
+}