am 6ab3ea5f: am 147ef944: am 60d1e1a0: Merge "Watchdog: Improvement of debuggability"

* commit '6ab3ea5f48abfd777d5bd18d92acc3bc766f78ce':
  Watchdog: Improvement of debuggability
diff --git a/Android.mk b/Android.mk
index b9157fe..07500b1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -74,6 +74,7 @@
 	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 \
@@ -89,7 +90,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 +115,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 +141,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 +153,8 @@
 	core/java/android/view/accessibility/IAccessibilityManager.aidl \
 	core/java/android/view/accessibility/IAccessibilityManagerClient.aidl \
 	core/java/android/view/IApplicationToken.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 +200,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 +239,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 +306,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 +724,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..d002449
--- /dev/null
+++ b/api/17.txt
@@ -0,0 +1,48036 @@
+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 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_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 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();
+    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 deprecated int getId();
+    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 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();
+    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 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);
+    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 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);
+    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 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 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 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);
+    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 deprecated int getVisibleTitleHeight();
+    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 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 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 deprecated void setPictureListener(android.webkit.WebView.PictureListener);
+    method public void setVerticalScrollbarOverlay(boolean);
+    method public void setWebChromeClient(android.webkit.WebChromeClient);
+    method public void setWebViewClient(android.webkit.WebViewClient);
+    method public boolean showFindDialog(java.lang.String, boolean);
+    method public void stopLoading();
+    method public boolean zoomIn();
+    method public boolean zoomOut();
+    field public static final java.lang.String SCHEME_GEO = "geo:0,0?q=";
+    field public static final java.lang.String SCHEME_MAILTO = "mailto:";
+    field public static final java.lang.String SCHEME_TEL = "tel:";
+  }
+
+  public static abstract interface WebView.FindListener {
+    method public abstract void onFindResultReceived(int, int, boolean);
+  }
+
+  public static class WebView.HitTestResult {
+    method public java.lang.String getExtra();
+    method public int getType();
+    field public static final deprecated int ANCHOR_TYPE = 1; // 0x1
+    field public static final int EDIT_TEXT_TYPE = 9; // 0x9
+    field public static final int EMAIL_TYPE = 4; // 0x4
+    field public static final int GEO_TYPE = 3; // 0x3
+    field public static final deprecated int IMAGE_ANCHOR_TYPE = 6; // 0x6
+    field public static final int IMAGE_TYPE = 5; // 0x5
+    field public static final int PHONE_TYPE = 2; // 0x2
+    field public static final int SRC_ANCHOR_TYPE = 7; // 0x7
+    field public static final int SRC_IMAGE_ANCHOR_TYPE = 8; // 0x8
+    field public static final int UNKNOWN_TYPE = 0; // 0x0
+  }
+
+  public static abstract deprecated interface WebView.PictureListener {
+    method public abstract deprecated void onNewPicture(android.webkit.WebView, android.graphics.Picture);
+  }
+
+  public class WebView.WebViewTransport {
+    ctor public WebView.WebViewTransport();
+    method public synchronized android.webkit.WebView getWebView();
+    method public synchronized void setWebView(android.webkit.WebView);
+  }
+
+  public class WebViewClient {
+    ctor public WebViewClient();
+    method public void doUpdateVisitedHistory(android.webkit.WebView, java.lang.String, boolean);
+    method public void onFormResubmission(android.webkit.WebView, android.os.Message, android.os.Message);
+    method public void onLoadResource(android.webkit.WebView, java.lang.String);
+    method public void onPageFinished(android.webkit.WebView, java.lang.String);
+    method public void onPageStarted(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
+    method public void onReceivedError(android.webkit.WebView, int, java.lang.String, java.lang.String);
+    method public void onReceivedHttpAuthRequest(android.webkit.WebView, android.webkit.HttpAuthHandler, java.lang.String, java.lang.String);
+    method public void onReceivedLoginRequest(android.webkit.WebView, java.lang.String, java.lang.String, java.lang.String);
+    method public void onReceivedSslError(android.webkit.WebView, android.webkit.SslErrorHandler, android.net.http.SslError);
+    method public void onScaleChanged(android.webkit.WebView, float, float);
+    method public deprecated void onTooManyRedirects(android.webkit.WebView, android.os.Message, android.os.Message);
+    method public void onUnhandledKeyEvent(android.webkit.WebView, android.view.KeyEvent);
+    method public android.webkit.WebResourceResponse shouldInterceptRequest(android.webkit.WebView, java.lang.String);
+    method public boolean shouldOverrideKeyEvent(android.webkit.WebView, android.view.KeyEvent);
+    method public boolean shouldOverrideUrlLoading(android.webkit.WebView, java.lang.String);
+    field public static final int ERROR_AUTHENTICATION = -4; // 0xfffffffc
+    field public static final int ERROR_BAD_URL = -12; // 0xfffffff4
+    field public static final int ERROR_CONNECT = -6; // 0xfffffffa
+    field public static final int ERROR_FAILED_SSL_HANDSHAKE = -11; // 0xfffffff5
+    field public static final int ERROR_FILE = -13; // 0xfffffff3
+    field public static final int ERROR_FILE_NOT_FOUND = -14; // 0xfffffff2
+    field public static final int ERROR_HOST_LOOKUP = -2; // 0xfffffffe
+    field public static final int ERROR_IO = -7; // 0xfffffff9
+    field public static final int ERROR_PROXY_AUTHENTICATION = -5; // 0xfffffffb
+    field public static final int ERROR_REDIRECT_LOOP = -9; // 0xfffffff7
+    field public static final int ERROR_TIMEOUT = -8; // 0xfffffff8
+    field public static final int ERROR_TOO_MANY_REQUESTS = -15; // 0xfffffff1
+    field public static final int ERROR_UNKNOWN = -1; // 0xffffffff
+    field public static final int ERROR_UNSUPPORTED_AUTH_SCHEME = -3; // 0xfffffffd
+    field public static final int ERROR_UNSUPPORTED_SCHEME = -10; // 0xfffffff6
+  }
+
+  public class WebViewDatabase {
+    method public void clearFormData();
+    method public void clearHttpAuthUsernamePassword();
+    method public void clearUsernamePassword();
+    method public static synchronized android.webkit.WebViewDatabase getInstance(android.content.Context);
+    method public boolean hasFormData();
+    method public boolean hasHttpAuthUsernamePassword();
+    method public boolean hasUsernamePassword();
+    field protected static final java.lang.String LOGTAG = "webviewdatabase";
+  }
+
+  public class WebViewFragment extends android.app.Fragment {
+    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 880170d..7d1c203 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -62,17 +62,21 @@
     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 INTERACT_ACROSS_USERS = "android.permission.INTERACT_ACROSS_USERS";
     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 MANAGE_USERS = "android.permission.MANAGE_USERS";
     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 NET_TUNNELING = "android.permission.NET_TUNNELING";
     field public static final java.lang.String NFC = "android.permission.NFC";
+    field public static final java.lang.String PACKAGE_VERIFICATION_AGENT = "android.permission.PACKAGE_VERIFICATION_AGENT";
     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";
@@ -602,15 +606,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 +632,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 +663,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 +737,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
@@ -879,6 +896,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
@@ -935,6 +953,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 +984,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 +1024,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
@@ -2992,6 +3013,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);
@@ -3851,6 +3873,8 @@
     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 int getTargetUid();
+    method public android.os.UserHandle getTargetUserHandle();
     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;
@@ -4333,6 +4357,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();
   }
@@ -4429,6 +4454,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 +5080,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 +5267,7 @@
     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 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);
@@ -5298,8 +5326,10 @@
     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 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, 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);
@@ -5336,6 +5366,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 +5392,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 +5412,7 @@
     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 createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public java.lang.String[] databaseList();
     method public boolean deleteDatabase(java.lang.String);
@@ -5430,8 +5463,10 @@
     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 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, 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);
@@ -5805,7 +5840,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";
@@ -5954,6 +5991,8 @@
   public class IntentSender implements android.os.Parcelable {
     method public int describeContents();
     method public java.lang.String getTargetPackage();
+    method public int getTargetUid();
+    method public android.os.UserHandle getTargetUserHandle();
     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,6 +6225,7 @@
     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
@@ -6209,6 +6249,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 +6295,7 @@
     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_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 +6304,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 +6477,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;
@@ -6552,6 +6596,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
@@ -6587,6 +6632,17 @@
     field public java.lang.String packageName;
   }
 
+  public class PackageUserState {
+    ctor public PackageUserState();
+    ctor public PackageUserState(android.content.pm.PackageUserState);
+    field public java.util.HashSet disabledComponents;
+    field public int enabled;
+    field public java.util.HashSet enabledComponents;
+    field public boolean installed;
+    field public boolean notLaunched;
+    field public boolean stopped;
+  }
+
   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);
@@ -6630,7 +6686,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 +6734,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;
@@ -6779,6 +6838,7 @@
     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
@@ -6829,6 +6889,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 +7003,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 +7368,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 +7385,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 +8145,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 +8173,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 +8663,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 +8713,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 +9308,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 +9336,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);
@@ -9803,7 +9871,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 +9994,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 {
@@ -10120,6 +10205,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 +10485,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 +10531,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 +10575,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 +10599,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 +10621,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 +11430,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 +11492,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 +11587,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 +12485,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 +12530,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 +12608,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 +13248,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 +13882,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 +14957,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 +14987,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 +15547,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
@@ -15332,6 +15641,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 +16301,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 +16335,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;
@@ -16156,6 +16468,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 +16490,20 @@
     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();
+    method public boolean supportsMultipleUsers();
+  }
+
   public abstract class Vibrator {
     method public abstract void cancel();
     method public abstract boolean hasVibrator();
@@ -16956,9 +17283,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";
   }
@@ -18478,7 +18807,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";
@@ -19681,6 +20010,10 @@
 
 package android.security {
 
+  public class AndroidKeyPairGeneratorSpec implements java.security.spec.AlgorithmParameterSpec {
+    ctor public AndroidKeyPairGeneratorSpec(android.content.Context, java.lang.String, javax.security.auth.x500.X500Principal, java.math.BigInteger, java.util.Date, java.util.Date);
+  }
+
   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);
@@ -19706,6 +20039,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 +20369,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 +20559,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 +20570,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 +20696,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 +21217,7 @@
     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 createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public java.lang.String[] databaseList();
     method public boolean deleteDatabase(java.lang.String);
@@ -20774,8 +21267,10 @@
     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 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, 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);
@@ -20855,6 +21350,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;
@@ -22051,6 +22547,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 +22819,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);
@@ -22430,7 +22948,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 +23012,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 +23085,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 {
@@ -22633,6 +23159,17 @@
     method public void set(T, V);
   }
 
+  public class PropertyValueModel extends android.util.ValueModel {
+    method public T get();
+    method public H getHost();
+    method public android.util.Property<H, T> getProperty();
+    method public java.lang.Class<T> getType();
+    method public static android.util.PropertyValueModel<H, T> of(H, android.util.Property<H, T>);
+    method public static android.util.PropertyValueModel<H, T> of(H, java.lang.Class<T>, java.lang.String);
+    method public static android.util.PropertyValueModel of(java.lang.Object, java.lang.String);
+    method public void set(T);
+  }
+
   public class SparseArray implements java.lang.Cloneable {
     ctor public SparseArray();
     ctor public SparseArray(int);
@@ -22781,6 +23318,14 @@
     field public int type;
   }
 
+  public abstract class ValueModel {
+    ctor protected ValueModel();
+    method public abstract T get();
+    method public abstract java.lang.Class<T> getType();
+    method public abstract void set(T);
+    field public static final android.util.ValueModel EMPTY;
+  }
+
   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;
@@ -22891,21 +23436,25 @@
   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 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 +23527,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 +24445,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 +24576,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 +24630,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 +24645,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);
@@ -24112,6 +24670,7 @@
     method public boolean getKeepScreenOn();
     method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
     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 +24694,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 +24728,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 +24779,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 +24833,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 +24884,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);
@@ -24347,6 +24932,7 @@
     method public void setImportantForAccessibility(int);
     method public void setKeepScreenOn(boolean);
     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 +24956,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 +24981,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 +25041,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 +25095,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 +25413,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,10 +25428,18 @@
     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 setMargins(int, int, int, int);
     field public int bottomMargin;
+    field public int endMargin;
     field public int leftMargin;
     field public int rightMargin;
+    field public int startMargin;
     field public int topMargin;
   }
 
@@ -25128,7 +25743,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
@@ -26285,7 +26900,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);
@@ -26348,6 +26963,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,6 +26975,7 @@
     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();
@@ -26408,6 +27025,7 @@
     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);
@@ -27047,6 +27665,7 @@
     method public void setListSelection(int);
     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();
@@ -27137,10 +27756,12 @@
     method public abstract void onSelectedDayChange(android.widget.CalendarView, int, int, int);
   }
 
-  public class CheckBox extends android.widget.CompoundButton {
+  public class CheckBox extends android.widget.CompoundButton implements android.widget.ValueEditor {
     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);
+    method public android.util.ValueModel<java.lang.Boolean> getValueModel();
+    method public void setValueModel(android.util.ValueModel<java.lang.Boolean>);
   }
 
   public abstract interface Checkable {
@@ -27155,7 +27776,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 +27918,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);
   }
@@ -27314,14 +27934,16 @@
     method public void setSize(int, int);
   }
 
-  public class EditText extends android.widget.TextView {
+  public class EditText extends android.widget.TextView implements android.widget.ValueEditor {
     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 android.util.ValueModel<java.lang.CharSequence> getValueModel();
     method public void selectAll();
     method public void setSelection(int, int);
     method public void setSelection(int);
+    method public void setValueModel(android.util.ValueModel<java.lang.CharSequence>);
   }
 
   public abstract interface ExpandableListAdapter {
@@ -27762,6 +28384,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 +28737,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 +28768,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;
   }
 
@@ -28338,11 +28968,13 @@
     method public abstract java.lang.Object[] getSections();
   }
 
-  public class SeekBar extends android.widget.AbsSeekBar {
+  public class SeekBar extends android.widget.AbsSeekBar implements android.widget.ValueEditor {
     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 android.util.ValueModel<java.lang.Integer> getValueModel();
     method public void setOnSeekBarChangeListener(android.widget.SeekBar.OnSeekBarChangeListener);
+    method public void setValueModel(android.util.ValueModel<java.lang.Integer>);
   }
 
   public static abstract interface SeekBar.OnSeekBarChangeListener {
@@ -28440,7 +29072,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 +29299,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 +29361,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 +29394,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 +29444,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 +29464,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 +29540,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);
@@ -28908,6 +29548,11 @@
     method public android.widget.TextView getText2();
   }
 
+  public abstract interface ValueEditor {
+    method public abstract android.util.ValueModel<T> getValueModel();
+    method public abstract void setValueModel(android.util.ValueModel<T>);
+  }
+
   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);
@@ -28926,6 +29571,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 +29583,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..7f3dbe5 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -31,13 +31,13 @@
 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.util.AndroidException;
+import android.view.Display;
 import android.view.IWindowManager;
 
 import java.io.BufferedReader;
@@ -132,12 +132,16 @@
             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);
         }
@@ -320,7 +324,6 @@
                 mUserId = Integer.parseInt(nextArgRequired());
             } else {
                 System.err.println("Error: Unknown option: " + opt);
-                showUsage();
                 return null;
             }
         }
@@ -390,7 +393,7 @@
     private void runStartService() throws Exception {
         Intent intent = makeIntent();
         System.out.println("Starting service: " + intent);
-        ComponentName cn = mAm.startService(null, intent, intent.getType());
+        ComponentName cn = mAm.startService(null, intent, intent.getType(), 0);
         if (cn == null) {
             System.err.println("Error: Not found; no service started.");
         }
@@ -591,7 +594,6 @@
                 no_window_animation = true;
             } else {
                 System.err.println("Error: Unknown option: " + opt);
-                showUsage();
                 return;
             }
         }
@@ -735,7 +737,6 @@
                 persistent = true;
             } else {
                 System.err.println("Error: Unknown option: " + opt);
-                showUsage();
                 return;
             }
         }
@@ -749,13 +750,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 +1059,6 @@
                 gdbPort = nextArgRequired();
             } else {
                 System.err.println("Error: Unknown option: " + opt);
-                showUsage();
                 return;
             }
         }
@@ -1062,7 +1076,6 @@
             enabled = false;
         } else {
             System.err.println("Error: enabled mode must be 'on' or 'off' at " + mode);
-            showUsage();
             return;
         }
 
@@ -1087,7 +1100,6 @@
             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);
@@ -1097,7 +1109,6 @@
                 n = Integer.parseInt(nstr);
             } catch (NumberFormatException e) {
                 System.err.println("Error: bad number " + e);
-                showUsage();
                 return;
             }
         }
@@ -1117,9 +1128,46 @@
 
         try {
             if (m >= 0 && n >= 0) {
-                wm.setForcedDisplaySize(m, n);
+                // TODO(multidisplay): For now Configuration only applies to main screen.
+                wm.setForcedDisplaySize(Display.DEFAULT_DISPLAY, m, n);
             } 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) {
         }
@@ -1299,8 +1347,11 @@
                 "       am monitor [--gdb <port>]\n" +
                 "       am screen-compat [on|off] <PACKAGE>\n" +
                 "       am display-size [reset|MxN]\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" +
@@ -1353,10 +1404,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" +
+                "  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" +
+                "  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/installd/commands.c b/cmds/installd/commands.c
index 41e7b8d..ab64747 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -26,6 +26,7 @@
 dir_rec_t android_asec_dir;
 dir_rec_t android_app_dir;
 dir_rec_t android_app_private_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)
@@ -193,6 +194,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 +218,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 +276,11 @@
         }
         closedir(d);
     }
+
+    if (ensure_media_user_dirs((userid_t) target_persona) == -1) {
+        return -1;
+    }
+
     return 0;
 }
 
@@ -273,17 +295,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 +304,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)
@@ -413,7 +433,7 @@
     return 0;
 }
 
-int get_size(const char *pkgname, const char *apkpath,
+int get_size(const char *pkgname, int persona, const char *apkpath,
              const char *fwdlock_apkpath, const char *asecpath,
              int64_t *_codesize, int64_t *_datasize, int64_t *_cachesize,
              int64_t* _asecsize)
@@ -460,7 +480,7 @@
         }
     }
 
-    if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, 0)) {
+    if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, persona)) {
         goto done;
     }
 
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index fa4b8a6..d559639 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -85,8 +85,9 @@
     int64_t asecsize = 0;
     int res = 0;
 
-        /* pkgdir, apkpath */
-    res = get_size(arg[0], arg[1], arg[2], arg[3], &codesize, &datasize, &cachesize, &asecsize);
+        /* pkgdir, persona, apkpath */
+    res = get_size(arg[0], atoi(arg[1]), arg[2], arg[3], arg[4],
+            &codesize, &datasize, &cachesize, &asecsize);
 
     /*
      * Each int64_t can take up 22 characters printed out. Make sure it
@@ -150,7 +151,7 @@
     { "freecache",            1, do_free_cache },
     { "rmcache",              1, do_rm_cache },
     { "protect",              2, do_protect },
-    { "getsize",              4, do_get_size },
+    { "getsize",              5, do_get_size },
     { "rmuserdata",           2, do_rm_user_data },
     { "movefiles",            0, do_movefiles },
     { "linklib",              2, do_linklib },
@@ -297,6 +298,11 @@
         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 +332,163 @@
 }
 
 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;
 }
 
 int main(const int argc, const char *argv[]) {
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index 1b843fd..5b81d2c 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,8 @@
 
 #define APP_SUBDIR             "app/" // 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
@@ -91,8 +95,36 @@
 extern dir_rec_t android_app_private_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 +140,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 +157,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 +184,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,7 +200,7 @@
 int move_dex(const char *src, const char *dst);
 int rm_dex(const char *path);
 int protect(char *pkgname, gid_t gid);
-int get_size(const char *pkgname, const char *apkpath, const char *fwdlock_apkpath,
+int get_size(const char *pkgname, int persona, const char *apkpath, const char *fwdlock_apkpath,
              const char *asecpath, int64_t *codesize, int64_t *datasize, int64_t *cachesize,
              int64_t *asecsize);
 int free_cache(int64_t free_size);
diff --git a/cmds/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..e621ceb 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -20,6 +20,7 @@
 
 import android.app.ActivityManagerNative;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ContainerEncryptionParams;
 import android.content.pm.FeatureInfo;
@@ -35,13 +36,16 @@
 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.IUserManager;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserManager;
 
 import java.io.File;
 import java.lang.reflect.Field;
@@ -59,6 +63,7 @@
 
 public final class Pm {
     IPackageManager mPm;
+    IUserManager mUm;
 
     private WeakHashMap<String, Resources> mResourceCache
             = new WeakHashMap<String, Resources>();
@@ -82,6 +87,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 +163,11 @@
             return;
         }
 
+        if ("trim-caches".equals(op)) {
+            runTrimCaches();
+            return;
+        }
+
         if ("create-user".equals(op)) {
             runCreateUser();
             return;
@@ -167,11 +178,6 @@
             return;
         }
 
-        if ("list-users".equals(op)) {
-            runListUsers();
-            return;
-        }
-
         try {
             if (args.length == 1) {
                 if (args[0].equalsIgnoreCase("-l")) {
@@ -211,7 +217,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 +235,6 @@
             runListUsers();
         } else {
             System.err.println("Error: unknown list type '" + type + "'");
-            showUsage();
         }
     }
 
@@ -265,13 +269,11 @@
                     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;
         }
 
@@ -420,13 +422,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 +518,6 @@
                     dangerousOnly = true;
                 } else {
                     System.err.println("Error: Unknown option: " + opt);
-                    showUsage();
                     return;
                 }
             }
@@ -667,7 +666,6 @@
         String pkg = nextArg();
         if (pkg == null) {
             System.err.println("Error: no package specified");
-            showUsage();
             return;
         }
         displayPackageFilePath(pkg);
@@ -725,20 +723,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 +760,7 @@
     }
 
     private void runInstall() {
-        int installFlags = 0;
+        int installFlags = PackageManager.INSTALL_ALL_USERS;
         String installerPackageName = null;
 
         String opt;
@@ -777,6 +772,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 +784,6 @@
                 installerPackageName = nextOptionData();
                 if (installerPackageName == null) {
                     System.err.println("Error: no value specified for -i");
-                    showUsage();
                     return;
                 }
             } else if (opt.equals("-t")) {
@@ -798,51 +794,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 +855,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 +862,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 +888,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 +910,6 @@
             apkURI = Uri.fromFile(new File(apkFilePath));
         } else {
             System.err.println("Error: no package specified");
-            showUsage();
             return;
         }
 
@@ -910,8 +924,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 +983,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 +1002,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 +1025,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 {
@@ -1061,7 +1058,7 @@
 
         String opt = nextOption();
         if (opt != null && opt.equals("-k")) {
-            unInstallFlags = PackageManager.DONT_DELETE_DATA;
+            unInstallFlags = PackageManager.DELETE_KEEP_DATA;
         }
 
         String pkg = nextArg();
@@ -1098,7 +1095,7 @@
         return obs.result;
     }
 
-    class ClearDataObserver extends IPackageDataObserver.Stub {
+    static class ClearDataObserver extends IPackageDataObserver.Stub {
         boolean finished;
         boolean result;
 
@@ -1272,6 +1269,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
@@ -1360,19 +1426,24 @@
         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 +1472,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 +1483,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 +1508,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/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..ec3ec3e 100644
--- a/cmds/svc/src/com/android/commands/svc/PowerCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/PowerCommand.java
@@ -37,7 +37,7 @@
     public String longHelp() {
         return shortHelp() + "\n"
                 + "\n"
-                + "usage: svc power stayon [true|false|usb|ac]\n"
+                + "usage: svc power stayon [true|false|usb|ac|wireless]\n"
                 + "         Set the 'keep awake while plugged in' setting.\n";
     }
 
@@ -48,7 +48,8 @@
                     int val;
                     if ("true".equals(args[2])) {
                         val = BatteryManager.BATTERY_PLUGGED_AC |
-                                BatteryManager.BATTERY_PLUGGED_USB;
+                                BatteryManager.BATTERY_PLUGGED_USB |
+                                BatteryManager.BATTERY_PLUGGED_WIRELESS;
                     }
                     else if ("false".equals(args[2])) {
                         val = 0;
@@ -56,15 +57,16 @@
                         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);
+                        pm.acquireWakeLock(lock, PowerManager.FULL_WAKE_LOCK, "svc power", null);
                         pm.setStayOnSetting(val);
                         pm.releaseWakeLock(lock, 0);
                     }
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/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 22e454f..7a9f285 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,
@@ -1218,7 +1222,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>(
@@ -2265,7 +2269,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 +2303,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/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/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..f874d56 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();
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..d5580b7 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;
 
@@ -2708,7 +2709,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 +3385,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.
      *
@@ -4728,6 +4759,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));
+        }
     }
 
     /**
@@ -4990,7 +5044,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());
@@ -5037,7 +5093,7 @@
         if (mStopped) {
             mStopped = false;
             if (mToken != null && mParent == null) {
-                WindowManagerImpl.getDefault().setStoppedState(mToken, false);
+                WindowManagerGlobal.getInstance().setStoppedState(mToken, false);
             }
 
             synchronized (mManagedCursors) {
@@ -5137,7 +5193,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..26d8c17 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -30,6 +30,8 @@
 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 +42,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 +211,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 +377,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 +385,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 +543,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;
@@ -1346,6 +1389,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
@@ -1814,12 +1864,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 +1890,18 @@
         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;
+    }
+
     /**
      * Returns the usage statistics of each installed package.
      *
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index e12fa19..05c009f 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;
@@ -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);
@@ -454,8 +480,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 +697,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 +710,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;
@@ -1541,6 +1570,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();
@@ -1764,6 +1804,42 @@
         data.recycle();
         return result;
     }
+
+    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);
+        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_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,
@@ -2163,12 +2239,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 +2536,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 +2544,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 +2553,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 +2561,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();
@@ -3688,11 +3767,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();
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..4a1bf75 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;
@@ -62,7 +64,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 +72,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,8 +81,9 @@
 import android.view.ViewRootImpl;
 import android.view.Window;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
+import android.view.WindowManagerGlobal;
 import android.renderscript.RenderScript;
+import android.security.AndroidKeyStoreProvider;
 
 import com.android.internal.os.BinderInternal;
 import com.android.internal.os.RuntimeInit;
@@ -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;
@@ -165,6 +170,8 @@
             = new HashMap<IBinder, Service>();
     AppBindData mBoundApplication;
     Profiler mProfiler;
+    int mCurDefaultDisplayDpi;
+    boolean mDensityCompatMode;
     Configuration mConfiguration;
     Configuration mCompatConfiguration;
     Configuration mResConfiguration;
@@ -1052,7 +1059,7 @@
         @Override
         public void dumpGfxInfo(FileDescriptor fd, String[] args) {
             dumpGraphicsInfo(fd);
-            WindowManagerImpl.getDefault().dumpGfxInfo(fd);
+            WindowManagerGlobal.getInstance().dumpGfxInfo(fd);
         }
 
         @Override
@@ -1305,6 +1312,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 +1475,25 @@
 
     private static class ResourcesKey {
         final private String mResDir;
+        final private Configuration mOverrideConfiguration;
         final private float mScale;
         final private int mHash;
 
-        ResourcesKey(String resDir, float scale) {
+        ResourcesKey(String resDir, Configuration overrideConfiguration, float scale) {
             mResDir = resDir;
+            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 + (mOverrideConfiguration != null
+                    ? mOverrideConfiguration.hashCode() : 0);
+            hash = 31 * hash + Float.floatToIntBits(mScale);
+            mHash = hash;
         }
 
         @Override
@@ -1487,7 +1507,21 @@
                 return false;
             }
             ResourcesKey peer = (ResourcesKey) obj;
-            return mResDir.equals(peer.mResDir) && mScale == peer.mScale;
+            if (!mResDir.equals(peer.mResDir)) {
+                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;
         }
     }
 
@@ -1523,11 +1557,23 @@
         if (dm != null && !forceUpdate) {
             return dm;
         }
+
+        DisplayManagerGlobal displayManager = DisplayManagerGlobal.getInstance();
+        if (displayManager == null) {
+            // may be null early in system startup
+            dm = new DisplayMetrics();
+            dm.setToDefaults();
+            return dm;
+        }
+
         if (dm == null) {
             dm = new DisplayMetrics();
             mDisplayMetrics.put(ci, dm);
         }
-        Display d = WindowManagerImpl.getDefault(ci).getDefaultDisplay();
+
+        CompatibilityInfoHolder cih = new CompatibilityInfoHolder();
+        cih.set(ci);
+        Display d = displayManager.getCompatibleDisplay(Display.DEFAULT_DISPLAY, cih);
         d.getMetrics(dm);
         //Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h="
         //        + metrics.heightPixels + " den=" + metrics.density
@@ -1536,14 +1582,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 +1602,10 @@
      * @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, Configuration overrideConfiguration,
+            CompatibilityInfo compInfo) {
+        ResourcesKey key = new ResourcesKey(resDir, overrideConfiguration,
+                compInfo.applicationScale);
         Resources r;
         synchronized (mPackages) {
             // Resources is app scale dependent.
@@ -1588,13 +1637,20 @@
 
         //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
         DisplayMetrics metrics = getDisplayMetricsLocked(null, false);
-        r = new Resources(assets, metrics, getConfiguration(), compInfo);
+        Configuration config;
+        if (key.mOverrideConfiguration != null) {
+            config = new Configuration(getConfiguration());
+            config.updateFrom(key.mOverrideConfiguration);
+        } else {
+            config = getConfiguration();
+        }
+        r = new Resources(assets, metrics, 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 +1670,10 @@
     /**
      * 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, Configuration overrideConfiguration,
+            LoadedApk pkgInfo) {
+        return getTopLevelResources(resDir, overrideConfiguration,
+                pkgInfo.mCompatibilityInfo.get());
     }
 
     final Handler getHandler() {
@@ -1652,7 +1710,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 +1727,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))
@@ -2587,7 +2645,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");
             }
         }
@@ -2727,7 +2785,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);
                 }
             }
@@ -3121,7 +3180,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 +3369,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 +3381,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 +3520,8 @@
         
         // If there was a pending configuration change, execute it first.
         if (changedConfig != null) {
+            mCurDefaultDisplayDpi = changedConfig.densityDpi;
+            updateDefaultDensity();
             handleConfigurationChanged(changedConfig, null);
         }
 
@@ -3543,8 +3604,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.
@@ -3665,18 +3726,28 @@
 
         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);
+                Configuration override = entry.getKey().mOverrideConfiguration;
+                if (override != null) {
+                    if (tmpConfig == null) {
+                        tmpConfig = new Configuration();
+                    }
+                    tmpConfig.setTo(config);
+                    tmpConfig.updateFrom(override);
+                    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 +3759,14 @@
         return changes != 0;
     }
 
-    final Configuration applyCompatConfiguration() {
+    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 +3781,8 @@
             if (mPendingConfiguration != null) {
                 if (!mPendingConfiguration.isOtherSeqNewer(config)) {
                     config = mPendingConfiguration;
+                    mCurDefaultDisplayDpi = config.densityDpi;
+                    updateDefaultDensity();
                 }
                 mPendingConfiguration = null;
             }
@@ -3731,12 +3804,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 +3949,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 +3962,7 @@
             callbacks.get(i).onTrimMemory(level);
         }
 
-        windowManager.endTrimMemory();        
+        windowManager.endTrimMemory();
     }
 
     private void setupGraphicsSupport(LoadedApk info, File cacheDir) {
@@ -3910,8 +3983,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);
@@ -3930,8 +4015,7 @@
             // Persistent processes on low-memory devices do not get to
             // use hardware accelerated drawing, since this can add too much
             // overhead to the process.
-            Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
-            if (!ActivityManager.isHighEndGfx(display)) {
+            if (!ActivityManager.isHighEndGfx()) {
                 HardwareRenderer.disable(false);
             }
         }
@@ -3967,19 +4051,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 +4101,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);
@@ -4725,6 +4817,8 @@
         // StrictMode) on debug builds, but using DropBox, not logs.
         CloseGuard.setEnabled(false);
 
+        Security.addProvider(new AndroidKeyStoreProvider());
+
         Process.setArgV0("<pre-initialized>");
 
         Looper.prepareMainLooper();
diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java
index e37b3fa..7809e73 100644
--- a/core/java/android/app/AlertDialog.java
+++ b/core/java/android/app/AlertDialog.java
@@ -566,7 +566,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 +583,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 +934,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..0f10c4f 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -41,16 +41,18 @@
 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 java.lang.ref.WeakReference;
@@ -69,7 +71,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 +201,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 +216,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 +231,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 +246,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 +261,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;
             }
@@ -424,7 +426,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 +450,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);
         }
@@ -462,7 +464,7 @@
                 intent,
                 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                 flags,
-                UserId.myUserId());
+                UserHandle.myUserId());
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -494,7 +496,7 @@
         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);
         }
@@ -507,7 +509,7 @@
                 intent,
                 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                 flags,
-                UserId.myUserId());
+                UserHandle.myUserId());
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -520,7 +522,7 @@
                 intent,
                 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                 flags,
-                UserId.myUserId());
+                UserHandle.myUserId());
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -533,7 +535,7 @@
                 intent,
                 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                 flags,
-                UserId.myUserId());
+                UserHandle.myUserId());
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -543,7 +545,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);
         }
@@ -713,7 +715,7 @@
         }
         Resources r = mContext.mMainThread.getTopLevelResources(
             app.uid == Process.myUid() ? app.sourceDir
-            : app.publicSourceDir, mContext.mPackageInfo);
+            : app.publicSourceDir, null, mContext.mPackageInfo);
         if (r != null) {
             return r;
         }
@@ -984,6 +986,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 +1022,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 +1072,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 +1105,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 +1145,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 +1195,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 +1204,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 +1215,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 +1224,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/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 411f6d0..efe4b7b 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;
@@ -294,6 +301,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 +349,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 +421,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 +490,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 +502,16 @@
 
         registerService(WINDOW_SERVICE, new ServiceFetcher() {
                 public Object getService(ContextImpl ctx) {
-                    return WindowManagerImpl.getDefault(ctx.mPackageInfo.mCompatibilityInfo);
+                    return new WindowManagerImpl(ctx.getOuterContext(),
+                            Display.DEFAULT_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 +530,7 @@
 
     @Override
     public AssetManager getAssets() {
-        return mResources.getAssets();
+        return getResources().getAssets();
     }
 
     @Override
@@ -743,7 +770,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 +907,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 +926,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);
@@ -953,19 +999,6 @@
         }
     }
 
-    /** @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);
-        } catch (RemoteException e) {
-        }
-    }
-
     @Override
     public void sendBroadcast(Intent intent, String receiverPermission) {
         String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
@@ -1027,6 +1060,50 @@
     }
 
     @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 sendOrderedBroadcastAsUser(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, false, user.getIdentifier());
+        } catch (RemoteException e) {
+        }
+    }
+
+    @Override
     public void sendStickyBroadcast(Intent intent) {
         String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
         try {
@@ -1144,11 +1221,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 +1248,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 +1267,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 +1294,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 +1307,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);
@@ -1508,10 +1601,25 @@
     }
 
     @Override
+    public Context createConfigurationContext(Configuration overrideConfiguration) {
+        ContextImpl c = new ContextImpl();
+        c.init(mPackageInfo, null, mMainThread);
+        c.mResources = mMainThread.getTopLevelResources(
+                mPackageInfo.getResDir(), overrideConfiguration,
+                mResources.getCompatibilityInfo());
+        return c;
+    }
+
+    @Override
     public boolean isRestricted() {
         return mRestricted;
     }
 
+    @Override
+    public CompatibilityInfoHolder getCompatibilityInfo() {
+        return mPackageInfo.mCompatibilityInfo;
+    }
+
     private File getDataDirFile() {
         if (mPackageInfo != null) {
             return mPackageInfo.getDataDirFile();
@@ -1576,12 +1684,11 @@
                         " compatiblity info:" + container.getDisplayMetrics());
             }
             mResources = mainThread.getTopLevelResources(
-                    mPackageInfo.getResDir(), container.getCompatibilityInfo());
+                    mPackageInfo.getResDir(), null, container.getCompatibilityInfo());
         }
         mMainThread = mainThread;
         mContentResolver = new ApplicationContentResolver(this, mainThread);
-
-        setActivityToken(activityToken);
+        mActivityToken = activityToken;
     }
 
     final void init(Resources resources, ActivityThread mainThread) {
@@ -1608,10 +1715,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..16112cb 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -1106,10 +1106,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/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 39e2423..52a6557 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -20,6 +20,7 @@
 import android.animation.AnimatorInflater;
 import android.animation.AnimatorListenerAdapter;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.os.Bundle;
 import android.os.Handler;
@@ -427,6 +428,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 +542,8 @@
     @Override
     public void putFragment(Bundle bundle, String key, Fragment fragment) {
         if (fragment.mIndex < 0) {
-            throw new IllegalStateException("Fragment " + fragment
-                    + " is not currently in the FragmentManager");
+            throwException(new IllegalStateException("Fragment " + fragment
+                    + " is not currently in the FragmentManager"));
         }
         bundle.putInt(key, fragment.mIndex);
     }
@@ -532,13 +555,13 @@
             return null;
         }
         if (index >= mActive.size()) {
-            throw new IllegalStateException("Fragement no longer exists for key "
-                    + key + ": index " + index);
+            throwException(new IllegalStateException("Fragement no longer exists for key "
+                    + key + ": index " + index));
         }
         Fragment f = mActive.get(index);
         if (f == null) {
-            throw new IllegalStateException("Fragement no longer exists for key "
-                    + key + ": index " + index);
+            throwException(new IllegalStateException("Fragement no longer exists for key "
+                    + key + ": index " + index));
         }
         return f;
     }
@@ -546,8 +569,8 @@
     @Override
     public Fragment.SavedState saveFragmentInstanceState(Fragment fragment) {
         if (fragment.mIndex < 0) {
-            throw new IllegalStateException("Fragment " + fragment
-                    + " is not currently in the FragmentManager");
+            throwException(new IllegalStateException("Fragment " + fragment
+                    + " is not currently in the FragmentManager"));
         }
         if (fragment.mState > Fragment.INITIALIZING) {
             Bundle result = saveFragmentBasicState(fragment);
@@ -732,6 +755,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;
@@ -820,9 +847,11 @@
                             if (f.mContainerId != 0) {
                                 container = (ViewGroup)mActivity.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;
@@ -1583,12 +1612,9 @@
             Fragment f = mActive.get(i);
             if (f != null) {
                 if (f.mIndex < 0) {
-                    String msg = "Failure saving state: active " + f
-                            + " has cleared index: " + f.mIndex;
-                    Slog.e(TAG, msg);
-                    dump("  ", null, new PrintWriter(new LogWriter(
-                            Log.ERROR, TAG, Log.LOG_ID_SYSTEM)), new String[] { });
-                    throw new IllegalStateException(msg);
+                    throwException(new IllegalStateException(
+                            "Failure saving state: active " + f
+                            + " has cleared index: " + f.mIndex));
                 }
 
                 haveFragments = true;
@@ -1601,12 +1627,9 @@
 
                     if (f.mTarget != null) {
                         if (f.mTarget.mIndex < 0) {
-                            String msg = "Failure saving state: " + f
-                                + " has target not in fragment manager: " + f.mTarget;
-                            Slog.e(TAG, msg);
-                            dump("  ", null, new PrintWriter(new LogWriter(
-                                    Log.ERROR, TAG, Log.LOG_ID_SYSTEM)), new String[] { });
-                            throw new IllegalStateException(msg);
+                            throwException(new IllegalStateException(
+                                    "Failure saving state: " + f
+                                    + " has target not in fragment manager: " + f.mTarget));
                         }
                         if (fs.mSavedFragmentState == null) {
                             fs.mSavedFragmentState = new Bundle();
@@ -1645,12 +1668,9 @@
                 for (int i=0; i<N; i++) {
                     added[i] = mAdded.get(i).mIndex;
                     if (added[i] < 0) {
-                        String msg = "Failure saving state: active " + mAdded.get(i)
-                                + " has cleared index: " + added[i];
-                        Slog.e(TAG, msg);
-                        dump("  ", null, new PrintWriter(new LogWriter(
-                                Log.ERROR, TAG, Log.LOG_ID_SYSTEM)), new String[] { });
-                        throw new IllegalStateException(msg);
+                        throwException(new IllegalStateException(
+                                "Failure saving state: active " + mAdded.get(i)
+                                + " has cleared index: " + added[i]));
                     }
                     if (DEBUG) Log.v(TAG, "saveAllState: adding fragment #" + i
                             + ": " + mAdded.get(i));
@@ -1755,8 +1775,8 @@
             for (int i=0; i<fms.mAdded.length; i++) {
                 Fragment f = mActive.get(fms.mAdded[i]);
                 if (f == null) {
-                    throw new IllegalStateException(
-                            "No instantiated fragment for index #" + fms.mAdded[i]);
+                    throwException(new IllegalStateException(
+                            "No instantiated fragment for index #" + fms.mAdded[i]));
                 }
                 f.mAdded = true;
                 if (DEBUG) Log.v(TAG, "restoreAllState: making added #" + i + ": " + f);
@@ -1784,7 +1804,7 @@
     }
     
     public void attachActivity(Activity activity) {
-        if (mActivity != null) throw new IllegalStateException();
+        if (mActivity != null) throw new IllegalStateException("Already attached");
         mActivity = activity;
     }
     
@@ -1923,7 +1943,7 @@
         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 != null && !f.mHidden) {
                     if (f.onContextItemSelected(item)) {
                         return true;
                     }
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 031e39b..70d8445 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -55,6 +55,10 @@
             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,
@@ -102,7 +106,7 @@
     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 +133,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,
@@ -327,6 +331,7 @@
 
     // 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 removeSubTask(int taskId, int subTaskIndex) throws RemoteException;
@@ -606,4 +611,6 @@
     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;
 }
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/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/res/res/values-sw720dp-land/arrays.xml b/core/java/android/app/IStopUserCallback.aidl
similarity index 61%
copy from core/res/res/values-sw720dp-land/arrays.xml
copy to core/java/android/app/IStopUserCallback.aidl
index d845875..19ac1d5 100644
--- a/core/res/res/values-sw720dp-land/arrays.xml
+++ b/core/java/android/app/IStopUserCallback.aidl
@@ -1,7 +1,4 @@
-<?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");
@@ -16,14 +13,15 @@
 ** 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>
+package android.app;
 
-</resources>
+/**
+ * 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/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..1e89bb2 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -37,7 +37,7 @@
 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;
@@ -120,8 +120,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;
@@ -195,7 +195,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 +358,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 +471,7 @@
 
     public Resources getResources(ActivityThread mainThread) {
         if (mResources == null) {
-            mResources = mainThread.getTopLevelResources(mResDir, this);
+            mResources = mainThread.getTopLevelResources(mResDir, null, this);
         }
         return mResources;
     }
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..69c20b0 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -17,10 +17,9 @@
 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.util.Log;
 
@@ -88,6 +87,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
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 8adc8a2..a57c516 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.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;
 
 /**
@@ -617,6 +618,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 getTargetUid() {
+        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 getTargetUserHandle() {
+        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/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/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index c131549..1ad2e6d 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 {
@@ -688,7 +690,7 @@
     public void setWallpaperOffsets(IBinder windowToken, float xOffset, float yOffset) {
         try {
             //Log.v(TAG, "Sending new wallpaper offsets from app...");
-            ViewRootImpl.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
+            WindowManagerGlobal.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
                     windowToken, xOffset, yOffset, mWallpaperXStep, mWallpaperYStep);
             //Log.v(TAG, "...app returning after sending offsets!");
         } catch (RemoteException e) {
@@ -726,7 +728,7 @@
             int x, int y, int z, Bundle extras) {
         try {
             //Log.v(TAG, "Sending new wallpaper offsets from app...");
-            ViewRootImpl.getWindowSession(mContext.getMainLooper()).sendWallpaperCommand(
+            WindowManagerGlobal.getWindowSession(mContext.getMainLooper()).sendWallpaperCommand(
                     windowToken, action, x, y, z, extras, false);
             //Log.v(TAG, "...app returning after sending offsets!");
         } catch (RemoteException e) {
@@ -746,7 +748,7 @@
      */
     public void clearWallpaperOffsets(IBinder windowToken) {
         try {
-            ViewRootImpl.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
+            WindowManagerGlobal.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
                     windowToken, -1, -1, -1, -1);
         } catch (RemoteException e) {
             // Ignore.
@@ -768,12 +770,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 +788,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/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 08bc0ac..c76bf91 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -29,6 +29,7 @@
 import android.util.DisplayMetrics;
 import android.util.TypedValue;
 import android.widget.RemoteViews;
+import android.widget.RemoteViews.OnClickHandler;
 
 import com.android.internal.appwidget.IAppWidgetHost;
 import com.android.internal.appwidget.IAppWidgetService;
@@ -41,7 +42,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 +67,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 +84,7 @@
         public UpdateHandler(Looper looper) {
             super(looper);
         }
-        
+
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case HANDLE_UPDATE: {
@@ -88,6 +95,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,16 +106,25 @@
             }
         }
     }
-    
+
     Handler mHandler;
 
     int mHostId;
     Callbacks mCallbacks = new Callbacks();
     final HashMap<Integer,AppWidgetHostView> mViews = new HashMap<Integer, AppWidgetHostView>();
+    private OnClickHandler mOnClickHandler;
 
     public AppWidgetHost(Context context, int hostId) {
+        this(context, hostId, null);
+    }
+
+    /**
+     * @hide
+     */
+    public AppWidgetHost(Context context, int hostId, OnClickHandler handler) {
         mContext = context;
         mHostId = hostId;
+        mOnClickHandler = handler;
         mHandler = new UpdateHandler(context.getMainLooper());
         mDisplayMetrics = context.getResources().getDisplayMetrics();
         synchronized (sServiceLock) {
@@ -122,7 +142,7 @@
     public void startListening() {
         int[] updatedIds;
         ArrayList<RemoteViews> updatedViews = new ArrayList<RemoteViews>();
-        
+
         try {
             if (mPackageName == null) {
                 mPackageName = mContext.getPackageName();
@@ -170,7 +190,7 @@
     }
 
     /**
-     * Stop listening to changes for this AppWidget.  
+     * Stop listening to changes for this AppWidget.
      */
     public void deleteAppWidgetId(int appWidgetId) {
         synchronized (mViews) {
@@ -225,6 +245,7 @@
     public final AppWidgetHostView createView(Context context, int appWidgetId,
             AppWidgetProviderInfo appWidget) {
         AppWidgetHostView view = onCreateView(context, appWidgetId, appWidget);
+        view.setOnClickHandler(mOnClickHandler);
         view.setAppWidget(appWidgetId, appWidget);
         synchronized (mViews) {
             mViews.put(appWidgetId, view);
@@ -236,6 +257,7 @@
             throw new RuntimeException("system server dead?", e);
         }
         view.updateAppWidget(views);
+
         return view;
     }
 
@@ -245,7 +267,7 @@
      */
     protected AppWidgetHostView onCreateView(Context context, int appWidgetId,
             AppWidgetProviderInfo appWidget) {
-        return new AppWidgetHostView(context);
+        return new AppWidgetHostView(context, mOnClickHandler);
     }
 
     /**
@@ -255,7 +277,7 @@
         AppWidgetHostView v;
 
         // Convert complex to dp -- we are getting the AppWidgetProviderInfo from the
-        // AppWidgetService, which doesn't have our context, hence we need to do the 
+        // AppWidgetService, which doesn't have our context, hence we need to do the
         // conversion here.
         appWidget.minWidth =
             TypedValue.complexToDimensionPixelSize(appWidget.minWidth, mDisplayMetrics);
@@ -274,6 +296,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..603ceb7 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -44,6 +44,7 @@
 import android.widget.BaseAdapter;
 import android.widget.FrameLayout;
 import android.widget.RemoteViews;
+import android.widget.RemoteViews.OnClickHandler;
 import android.widget.RemoteViewsAdapter.RemoteAdapterConnectionCallback;
 import android.widget.TextView;
 
@@ -83,7 +84,8 @@
     long mFadeStartTime = -1;
     Bitmap mOld;
     Paint mOldPaint = new Paint();
-    
+    private OnClickHandler mOnClickHandler;
+
     /**
      * Create a host view.  Uses default fade animations.
      */
@@ -92,9 +94,17 @@
     }
 
     /**
+     * @hide
+     */
+    public AppWidgetHostView(Context context, OnClickHandler handler) {
+        this(context, android.R.anim.fade_in, android.R.anim.fade_out);
+        mOnClickHandler = handler;
+    }
+
+    /**
      * Create a host view. Uses specified animations when pushing
      * {@link #updateAppWidget(RemoteViews)}.
-     * 
+     *
      * @param animationIn Resource ID of in animation to use
      * @param animationOut Resource ID of out animation to use
      */
@@ -109,6 +119,17 @@
     }
 
     /**
+     * Pass the given handler to RemoteViews when updating this widget. Unless this
+     * is done immediatly after construction, a call to {@link #updateAppWidget(RemoteViews)}
+     * should be made.
+     * @param handler
+     * @hide
+     */
+    public void setOnClickHandler(OnClickHandler handler) {
+        mOnClickHandler = handler;
+    }
+
+    /**
      * Set the AppWidget that will be displayed by this view. This method also adds default padding
      * to widgets, as described in {@link #getDefaultPaddingForWidget(Context, ComponentName, Rect)}
      * and can be overridden in order to add custom padding.
@@ -177,7 +198,7 @@
     public int getAppWidgetId() {
         return mAppWidgetId;
     }
-    
+
     public AppWidgetProviderInfo getAppWidgetInfo() {
         return mInfo;
     }
@@ -281,12 +302,13 @@
      * AppWidget provider. Will animate into these new views as needed
      */
     public void updateAppWidget(RemoteViews remoteViews) {
+
         if (LOGD) Log.d(TAG, "updateAppWidget called mOld=" + mOld);
 
         boolean recycled = false;
         View content = null;
         Exception exception = null;
-        
+
         // Capture the old view into a bitmap so we can do the crossfade.
         if (CROSSFADE) {
             if (mFadeStartTime < 0) {
@@ -305,7 +327,7 @@
                 }
             }
         }
-        
+
         if (remoteViews == null) {
             if (mViewMode == VIEW_MODE_DEFAULT) {
                 // We've already done this -- nothing to do.
@@ -324,7 +346,7 @@
             // layout matches, try recycling it
             if (content == null && layoutId == mLayoutId) {
                 try {
-                    remoteViews.reapply(mContext, mView);
+                    remoteViews.reapply(mContext, mView, mOnClickHandler);
                     content = mView;
                     recycled = true;
                     if (LOGD) Log.d(TAG, "was able to recycled existing layout");
@@ -332,11 +354,11 @@
                     exception = e;
                 }
             }
-            
+
             // Try normal RemoteView inflation
             if (content == null) {
                 try {
-                    content = remoteViews.apply(mContext, this);
+                    content = remoteViews.apply(mContext, this, mOnClickHandler);
                     if (LOGD) Log.d(TAG, "had to inflate new layout");
                 } catch (RuntimeException e) {
                     exception = e;
@@ -346,7 +368,7 @@
             mLayoutId = layoutId;
             mViewMode = VIEW_MODE_CONTENT;
         }
-        
+
         if (content == null) {
             if (mViewMode == VIEW_MODE_ERROR) {
                 // We've already done this -- nothing to do.
@@ -356,7 +378,7 @@
             content = getErrorView();
             mViewMode = VIEW_MODE_ERROR;
         }
-        
+
         if (!recycled) {
             prepareView(content);
             addView(content);
@@ -455,7 +477,7 @@
             return super.drawChild(canvas, child, drawingTime);
         }
     }
-    
+
     /**
      * Prepare the given view to be shown. This might include adjusting
      * {@link FrameLayout.LayoutParams} before inserting.
@@ -471,7 +493,7 @@
         requested.gravity = Gravity.CENTER;
         view.setLayoutParams(requested);
     }
-    
+
     /**
      * Inflate and return the default layout requested by AppWidget provider.
      */
@@ -481,7 +503,7 @@
         }
         View defaultView = null;
         Exception exception = null;
-        
+
         try {
             if (mInfo != null) {
                 Context theirContext = mContext.createPackageContext(
@@ -500,19 +522,19 @@
         } catch (RuntimeException e) {
             exception = e;
         }
-        
+
         if (exception != null) {
             Log.w(TAG, "Error inflating AppWidget " + mInfo + ": " + exception.toString());
         }
-        
+
         if (defaultView == null) {
             if (LOGD) Log.d(TAG, "getDefaultView couldn't find any view, so inflating error");
             defaultView = getErrorView();
         }
-        
+
         return defaultView;
     }
-    
+
     /**
      * Inflate and return a view that represents an error state.
      */
diff --git a/core/java/android/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/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/ContentService.java b/core/java/android/content/ContentService.java
index 1a07504..472fe94 100644
--- a/core/java/android/content/ContentService.java
+++ b/core/java/android/content/ContentService.java
@@ -26,7 +26,7 @@
 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;
@@ -168,7 +168,7 @@
                     + ", syncToNetwork " + syncToNetwork);
         }
 
-        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.
         long identityToken = clearCallingIdentity();
@@ -236,7 +236,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 +259,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 +294,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 +312,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 +330,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 +344,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 +358,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 +372,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 +390,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 +407,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 +424,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 +440,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 +458,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 +471,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 +489,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 {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index ffff9be..dc6d93f 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,9 @@
 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 java.io.File;
 import java.io.FileInputStream;
@@ -851,6 +854,18 @@
     public abstract void startActivity(Intent intent);
 
     /**
+     * Same as {@link #startActivity(Intent)}, but for a specific user. It requires holding
+     * the {@link android.Manifest.permission#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 +893,22 @@
     public abstract void startActivity(Intent intent, Bundle options);
 
     /**
+     * Same as {@link #startActivity(Intent, Bundle)}, but for a specific user. It requires holding
+     * the {@link android.Manifest.permission#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 +1019,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 +1116,48 @@
             Bundle initialExtras);
 
     /**
+     * Same as {@link #sendBroadcast(Intent)}, but for a specific user.  This broadcast
+     * can only be sent to receivers that are part of the calling application.  It
+     * requires holding the {@link android.Manifest.permission#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);
+
+    /**
+     * Same as
+     * {@link #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)},
+     * but for a specific user.  This broadcast
+     * can only be sent to receivers that are part of the calling application.  It
+     * requires holding the {@link android.Manifest.permission#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 #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
+     */
+    public abstract void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
+            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
@@ -1351,6 +1414,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 +1452,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 +1474,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 +1488,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 +1980,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 +2028,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 +2047,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 +2458,33 @@
             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 Contex 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 for the application.
+     */
+    public abstract Context createConfigurationContext(Configuration overrideConfiguration);
+
+    /**
+     * Gets the compatibility info holder for this context.  This information
+     * is provided on a per-application basis and is used to simulate lower density
+     * display metrics for legacy applications.
+     *
+     * @return The compatibility info holder, or null if not required by the application.
+     * @hide
+     */
+    public abstract CompatibilityInfoHolder getCompatibilityInfo();
+
+    /**
      * Indicates whether this Context is restricted.
      *
      * @return True if this Context is restricted, false otherwise.
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 6b950e0..4bbe44e 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.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.database.DatabaseErrorHandler;
 import android.database.sqlite.SQLiteDatabase;
@@ -29,6 +30,8 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.UserHandle;
+import android.view.CompatibilityInfoHolder;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -276,11 +279,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 +327,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 +349,19 @@
     }
 
     @Override
+    public void sendBroadcastAsUser(Intent intent, UserHandle user) {
+        mBase.sendBroadcastAsUser(intent, user);
+    }
+
+    @Override
+    public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
+            BroadcastReceiver resultReceiver, Handler scheduler,
+            int initialCode, String initialData, Bundle initialExtras) {
+        mBase.sendOrderedBroadcastAsUser(intent, user, resultReceiver,
+                scheduler, initialCode, initialData, initialExtras);
+    }
+
+    @Override
     public void sendStickyBroadcast(Intent intent) {
         mBase.sendStickyBroadcast(intent);
     }
@@ -388,6 +410,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 +430,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 +548,18 @@
     }
 
     @Override
+    public Context createConfigurationContext(Configuration overrideConfiguration) {
+        return mBase.createConfigurationContext(overrideConfiguration);
+    }
+
+    @Override
     public boolean isRestricted() {
         return mBase.isRestricted();
     }
+
+    /** @hide */
+    @Override
+    public CompatibilityInfoHolder getCompatibilityInfo() {
+        return mBase.getCompatibilityInfo();
+    }
 }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 3fdf451..53e0a75 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.
@@ -2261,24 +2278,33 @@
             "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.
+     * Broadcast sent to the system when a user is added. Carries an extra EXTRA_USER_HANDLE that has the
+     * userHandle of the new user.
      * @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 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.
+     * @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.
      * @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.
      * @hide
      */
     public static final String ACTION_USER_SWITCHED =
@@ -2834,12 +2860,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..079241a 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;
 
 
@@ -223,6 +224,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 getTargetUid() {
+        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 getTargetUserHandle() {
+        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..ee075b4 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
@@ -2175,7 +2180,7 @@
                         }
                     }
                     // check if the userid matches
-                    if (userId != UserId.USER_ALL
+                    if (userId != UserHandle.USER_ALL
                             && userId != activeSyncContext.mSyncOperation.userId) {
                         continue;
                     }
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index 226e107..773e0fe 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;
 
@@ -37,7 +36,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..3035729 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,12 @@
     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 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 +397,7 @@
         0x1000, // UI MODE
         0x0200, // SCREEN SIZE
         0x2000, // SMALLEST SCREEN SIZE
+        0x0100, // DENSITY
     };
     /** @hide
      * Convert Java change bits to native.
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index e1434b3..1a82d58 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -298,11 +298,16 @@
      * 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}: Set to true if the application has been
      * installed using the forward lock option.
      *
@@ -335,7 +340,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..0e1fe3e 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;
 
 /**
@@ -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/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..0aa094f 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.
@@ -2166,8 +2208,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 +2269,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 +2319,42 @@
      *            {@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
+     *            {@link android.Manifest.permission#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}.
+     * @param millisecondsToDelay the amount of time requested for the timeout.
+     *            Must be positive and less than
+     *            {@link PackageManager#MAXIMUM_VERIFICATION_TIMEOUT}.
+     * @throws IllegalArgumentException if {@code millisecondsToDelay} is out
+     *            of bounds or {@code verificationCodeAtTimeout} is unknown.
+     * @throws SecurityException if the caller does not have the
+     *            {@link android.Manifest.permission#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 +2383,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 +2490,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 +2501,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 +2585,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 +2752,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..237f5c5 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);
     }
 
     /**
@@ -2040,7 +2059,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 +2185,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 +2462,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 +2519,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 +2545,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 +2761,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 +2787,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 +3477,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 +3507,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 +3553,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 +3616,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 +3653,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 +3698,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 +3715,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..1a71bfb
--- /dev/null
+++ b/core/java/android/content/pm/PackageUserState.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 android.content.pm;
+
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+
+import java.util.HashSet;
+
+/**
+ * Per-user state information about a package.
+ */
+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/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..060a235 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -18,12 +18,17 @@
 
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.Parcelable.Creator;
 
 /**
  * Per-user information.
  * @hide
  */
 public class UserInfo implements Parcelable {
+
+    /** 6 bits for user type */
+    public static final int FLAG_MASK_USER_TYPE = 0x0000003F;
+
     /**
      * Primary user. Only one user can have this flag set. Meaning of this
      * flag TBD.
@@ -41,14 +46,27 @@
      */
     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;
+
     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 +86,10 @@
 
     public UserInfo(UserInfo orig) {
         name = orig.name;
+        iconPath = orig.iconPath;
         id = orig.id;
         flags = orig.flags;
+        serialNumber = orig.serialNumber;
     }
 
     @Override
@@ -84,7 +104,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 +122,8 @@
     private UserInfo(Parcel source) {
         id = source.readInt();
         name = source.readString();
+        iconPath = source.readString();
         flags = source.readInt();
+        serialNumber = source.readInt();
     }
 }
diff --git a/packages/SystemUI/res/values-sw720dp-port/dimens.xml b/core/java/android/content/pm/VerificationParams.aidl
similarity index 68%
rename from packages/SystemUI/res/values-sw720dp-port/dimens.xml
rename to core/java/android/content/pm/VerificationParams.aidl
index 74b266d..5bb7f6962 100644
--- a/packages/SystemUI/res/values-sw720dp-port/dimens.xml
+++ b/core/java/android/content/pm/VerificationParams.aidl
@@ -1,6 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (c) 2011, The Android Open Source Project
+/*
+ * 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.
@@ -13,10 +12,8 @@
  * WITHOUT 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>
+ */
 
+package android.content.pm;
+
+parcelable VerificationParams;
diff --git a/core/java/android/content/pm/VerificationParams.java b/core/java/android/content/pm/VerificationParams.java
new file mode 100644
index 0000000..9bec87e
--- /dev/null
+++ b/core/java/android/content/pm/VerificationParams.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.content.pm.ManifestDigest;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents verification parameters used to verify packages to be installed.
+ *
+ * @hide
+ */
+public class VerificationParams implements Parcelable {
+    /** What we print out first when toString() is called. */
+    private static final String TO_STRING_PREFIX = "VerificationParams{";
+
+    /** The location of the supplementary verification file. */
+    private final Uri mVerificationURI;
+
+    /** URI referencing where the package was downloaded from. */
+    private final Uri mOriginatingURI;
+
+    /** HTTP referrer URI associated with the originatingURI. */
+    private final Uri mReferrer;
+
+    /**
+     * An object that holds the digest of the package which can be used to
+     * verify ownership.
+     */
+    private final ManifestDigest mManifestDigest;
+
+    /**
+     * Creates verification specifications for installing with application verification.
+     *
+     * @param verificationURI The location of the supplementary verification
+     *            file. This can be a 'file:' or a 'content:' URI. May be {@code null}.
+     * @param originatingURI URI referencing where the package was downloaded
+     *            from. May be {@code null}.
+     * @param referrer HTTP referrer URI associated with the originatingURI.
+     *            May be {@code null}.
+     * @param manifestDigest an object that holds the digest of the package
+     *            which can be used to verify ownership. May be {@code null}.
+     */
+    public VerificationParams(Uri verificationURI, Uri originatingURI, Uri referrer,
+            ManifestDigest manifestDigest) {
+        mVerificationURI = verificationURI;
+        mOriginatingURI = originatingURI;
+        mReferrer = referrer;
+        mManifestDigest = manifestDigest;
+    }
+
+    public Uri getVerificationURI() {
+        return mVerificationURI;
+    }
+
+    public Uri getOriginatingURI() {
+        return mOriginatingURI;
+    }
+
+    public Uri getReferrer() {
+        return mReferrer;
+    }
+
+    public ManifestDigest getManifestDigest() {
+        return mManifestDigest;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+
+        if (!(o instanceof VerificationParams)) {
+            return false;
+        }
+
+        final VerificationParams other = (VerificationParams) o;
+
+        if (mVerificationURI == null && other.mVerificationURI != null) {
+            return false;
+        }
+        if (!mVerificationURI.equals(other.mVerificationURI)) {
+            return false;
+        }
+
+        if (mOriginatingURI == null && other.mOriginatingURI != null) {
+            return false;
+        }
+        if (!mOriginatingURI.equals(other.mOriginatingURI)) {
+            return false;
+        }
+
+        if (mReferrer == null && other.mReferrer != null) {
+            return false;
+        }
+        if (!mReferrer.equals(other.mReferrer)) {
+            return false;
+        }
+
+        if (mManifestDigest == null && other.mManifestDigest != null) {
+            return false;
+        }
+        if (mManifestDigest != null && !mManifestDigest.equals(other.mManifestDigest)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 3;
+
+        hash += 5 * (mVerificationURI==null?1:mVerificationURI.hashCode());
+        hash += 7 * (mOriginatingURI==null?1:mOriginatingURI.hashCode());
+        hash += 11 * (mReferrer==null?1:mReferrer.hashCode());
+        hash += 13 * (mManifestDigest==null?1:mManifestDigest.hashCode());
+
+        return hash;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder(TO_STRING_PREFIX);
+
+        sb.append("mVerificationURI=");
+        sb.append(mVerificationURI.toString());
+        sb.append(",mOriginatingURI=");
+        sb.append(mOriginatingURI.toString());
+        sb.append(",mReferrer=");
+        sb.append(mReferrer.toString());
+        sb.append(",mManifestDigest=");
+        sb.append(mManifestDigest.toString());
+        sb.append('}');
+
+        return sb.toString();
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeParcelable(mVerificationURI, 0);
+        dest.writeParcelable(mOriginatingURI, 0);
+        dest.writeParcelable(mReferrer, 0);
+        dest.writeParcelable(mManifestDigest, 0);
+    }
+
+
+    private VerificationParams(Parcel source) {
+        mVerificationURI = source.readParcelable(Uri.class.getClassLoader());
+        mOriginatingURI = source.readParcelable(Uri.class.getClassLoader());
+        mReferrer = source.readParcelable(Uri.class.getClassLoader());
+        mManifestDigest = source.readParcelable(ManifestDigest.class.getClassLoader());
+    }
+
+    public static final Parcelable.Creator<VerificationParams> CREATOR =
+            new Parcelable.Creator<VerificationParams>() {
+        public VerificationParams createFromParcel(Parcel source) {
+                return new VerificationParams(source);
+        }
+
+        public VerificationParams[] newArray(int size) {
+            return new VerificationParams[size];
+        }
+    };
+}
diff --git a/core/java/android/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..52b6498 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.
@@ -369,26 +372,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 +414,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. */
@@ -454,6 +487,7 @@
         screenWidthDp = o.screenWidthDp;
         screenHeightDp = o.screenHeightDp;
         smallestScreenWidthDp = o.smallestScreenWidthDp;
+        densityDpi = o.densityDpi;
         compatScreenWidthDp = o.compatScreenWidthDp;
         compatScreenHeightDp = o.compatScreenHeightDp;
         compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp;
@@ -465,15 +499,23 @@
         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;
@@ -495,6 +537,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;
@@ -601,6 +648,7 @@
         screenWidthDp = compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED;
         screenHeightDp = compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED;
         smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
+        densityDpi = DENSITY_DPI_UNDEFINED;
         layoutDirection = View.LAYOUT_DIRECTION_LTR;
         seq = 0;
     }
@@ -707,8 +755,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;
         }
@@ -818,6 +871,10 @@
                 && 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,6 +959,7 @@
         dest.writeInt(screenWidthDp);
         dest.writeInt(screenHeightDp);
         dest.writeInt(smallestScreenWidthDp);
+        dest.writeInt(densityDpi);
         dest.writeInt(compatScreenWidthDp);
         dest.writeInt(compatScreenHeightDp);
         dest.writeInt(compatSmallestScreenWidthDp);
@@ -930,6 +988,7 @@
         screenWidthDp = source.readInt();
         screenHeightDp = source.readInt();
         smallestScreenWidthDp = source.readInt();
+        densityDpi = source.readInt();
         compatScreenWidthDp = source.readInt();
         compatScreenHeightDp = source.readInt();
         compatSmallestScreenWidthDp = source.readInt();
@@ -1000,6 +1059,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 +1097,7 @@
         result = 31 * result + screenWidthDp;
         result = 31 * result + screenHeightDp;
         result = 31 * result + smallestScreenWidthDp;
+        result = 31 * result + densityDpi;
         return result;
     }
 }
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index ab2fe1c..7559f1e 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,8 +1435,12 @@
             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();
@@ -1446,6 +1451,10 @@
             if (mConfiguration.locale == null) {
                 mConfiguration.locale = Locale.getDefault();
             }
+            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;
 
             String locale = null;
@@ -1474,7 +1483,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 +1845,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 +1866,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 {
 
@@ -1878,8 +1907,10 @@
             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 +1978,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 +2048,9 @@
 
             csl = ColorStateList.valueOf(value.data);
             if (mPreloading) {
-                sPreloadedColorStateLists.put(key, csl);
+                if (verifyPreloadConfig(value, "color")) {
+                    sPreloadedColorStateLists.put(key, csl);
+                }
             }
 
             return csl;
@@ -2059,7 +2094,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/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..74996da
--- /dev/null
+++ b/core/java/android/hardware/display/DisplayManager.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 android.hardware.display;
+
+import android.content.Context;
+import android.os.Handler;
+import android.util.SparseArray;
+import android.view.CompatibilityInfoHolder;
+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>();
+
+    /** @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,
+                    getCompatibilityInfoForDisplayLocked(displayId));
+            if (display != null) {
+                mDisplays.put(displayId, display);
+            }
+        } else if (!assumeValid && !display.isValid()) {
+            display = null;
+        }
+        return display;
+    }
+
+    private CompatibilityInfoHolder getCompatibilityInfoForDisplayLocked(int displayId) {
+        CompatibilityInfoHolder cih = null;
+        if (displayId == Display.DEFAULT_DISPLAY) {
+            cih = mContext.getCompatibilityInfo();
+        }
+        return cih;
+    }
+
+    /**
+     * 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);
+    }
+
+    /**
+     * 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..69c0319
--- /dev/null
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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;
+
+    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 = mDisplayInfoCache.get(displayId);
+                if (info != null) {
+                    return info;
+                }
+
+                info = mDm.getDisplayInfo(displayId);
+                if (info == null) {
+                    return null;
+                }
+                if (DEBUG) {
+                    Log.d(TAG, "getDisplayInfo: displayId=" + displayId + ", info=" + info);
+                }
+
+                mDisplayInfoCache.put(displayId, info);
+                registerCallbackIfNeededLocked();
+                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 (mDisplayIdCache == null) {
+                    mDisplayIdCache = mDm.getDisplayIds();
+                    registerCallbackIfNeededLocked();
+                }
+                return mDisplayIdCache;
+            }
+        } 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) {
+            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);
+            }
+        }
+    }
+
+    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/cmds/sensorservice/main_sensorservice.cpp b/core/java/android/hardware/display/IDisplayManager.aidl
similarity index 60%
copy from cmds/sensorservice/main_sensorservice.cpp
copy to core/java/android/hardware/display/IDisplayManager.aidl
index 8610627..d802aa1 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,12 +14,15 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+package android.hardware.display;
 
-using namespace android;
+import android.hardware.display.IDisplayManagerCallback;
+import android.view.DisplayInfo;
 
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
+/** @hide */
+interface IDisplayManager {
+    DisplayInfo getDisplayInfo(int displayId);
+    int[] getDisplayIds();
+
+    void registerCallback(in IDisplayManagerCallback callback);
 }
diff --git a/cmds/sensorservice/main_sensorservice.cpp b/core/java/android/hardware/display/IDisplayManagerCallback.aidl
similarity index 70%
rename from cmds/sensorservice/main_sensorservice.cpp
rename to core/java/android/hardware/display/IDisplayManagerCallback.aidl
index 8610627..c50e3fb 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/core/java/android/hardware/display/IDisplayManagerCallback.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,12 +14,9 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+package android.hardware.display;
 
-using namespace android;
-
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
+/** @hide */
+interface IDisplayManagerCallback {
+    oneway void onDisplayEvent(int displayId, int event);
 }
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/IInputMethodSessionWrapper.java b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
index e10f218..ce797d1 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;
 
@@ -91,28 +92,28 @@
                         (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_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 +121,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: {
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..d5b9edc 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.
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 28bd289..c52aa9e 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/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/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/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..5d40456 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -82,7 +82,7 @@
      * @hide
      */
     public static final int getOrigCallingUid() {
-        if (UserId.MU_ENABLED) {
+        if (UserHandle.MU_ENABLED) {
             return getOrigCallingUidNative();
         } else {
             return getCallingUid();
@@ -97,7 +97,7 @@
      * @hide
      */
     public static final int getOrigCallingUser() {
-        return UserId.getUserId(getOrigCallingUid());
+        return UserHandle.getUserId(getOrigCallingUid());
     }
 
     /**
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/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..0f9be9c 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,50 @@
     }
 
     /**
+     * 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.
+     *
+     * @param r The Runnable that will be executed synchronously.
+     *
+     * @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) {
+        if (r == null) {
+            throw new IllegalArgumentException("runnable must not be null");
+        }
+
+        if (Looper.myLooper() == mLooper) {
+            r.run();
+            return true;
+        }
+
+        BlockingRunnable br = new BlockingRunnable(r);
+        return br.postAndWait(this);
+    }
+
+    /**
      * Remove any pending posts of Runnable r that are in the message queue.
      */
     public final void removeCallbacks(Runnable r)
@@ -464,20 +568,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 +591,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 +720,43 @@
     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) {
+            if (!handler.post(this)) {
+                return false;
+            }
+
+            synchronized (this) {
+                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..c7a8493
--- /dev/null
+++ b/core/java/android/os/IUserManager.aidl
@@ -0,0 +1,38 @@
+/*
+**
+** 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;
+
+/**
+ *  {@hide}
+ */
+interface IUserManager {
+    UserInfo createUser(in String name, int flags);
+    boolean removeUser(int userHandle);
+    void setUserName(int userHandle, String name);
+    ParcelFileDescriptor setUserIcon(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..a1901a5 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,169 @@
     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);
+    }
+
+    /**
+     * 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 +398,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 +604,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..d5fca4d 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
      */
@@ -370,12 +376,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 +554,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 +582,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 +647,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..0d11ab4 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);
     }
 
@@ -357,7 +359,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 +367,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/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..d33bd80
--- /dev/null
+++ b/core/java/android/os/UserHandle.java
@@ -0,0 +1,231 @@
+/*
+ * 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 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 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) {
+        uid = getAppId(uid);
+        return uid >= Process.FIRST_ISOLATED_UID && uid <= Process.LAST_ISOLATED_UID;
+    }
+
+    /** @hide */
+    public static boolean isApp(int uid) {
+        if (uid > 0) {
+            uid = UserHandle.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;
+        }
+    }
+
+    /** @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 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..de8e78c
--- /dev/null
+++ b/core/java/android/os/UserManager.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 android.os;
+
+import com.android.internal.R;
+import android.content.Context;
+import android.content.pm.UserInfo;
+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.
+     */
+    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.
+     * Requires {@link android.Manifest.permission#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);
+        }
+    }
+
+    /**
+     * Returns a file descriptor for the user's photo. PNG data can be written into this file.
+     * @param userHandle the user for whom to change the photo.
+     * @return a {@link ParcelFileDescriptor} to which to write the photo.
+     * @hide
+     */
+    public ParcelFileDescriptor setUserIcon(int userHandle) {
+        try {
+            return mService.setUserIcon(userHandle);
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not set 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/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..08621ea 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();
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 79d0144..48d84c1 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,23 @@
     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.
+     *
+     * @hide
+     */
+    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..b4841b1 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;
@@ -1147,6 +1147,7 @@
          * <li>{@code 0} to never stay on while plugged in</li>
          * <li>{@link BatteryManager#BATTERY_PLUGGED_AC} to stay on for AC charger</li>
          * <li>{@link BatteryManager#BATTERY_PLUGGED_USB} to stay on for USB charger</li>
+         * <li>{@link BatteryManager#BATTERY_PLUGGED_WIRELESS} to stay on for wireless charger</li>
          * </ul>
          * These values can be OR-ed together.
          */
@@ -1381,7 +1382,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";
 
         /**
@@ -2334,7 +2337,7 @@
             if (sLockSettings != null && !sIsSystemProcess
                     && MOVED_TO_LOCK_SETTINGS.contains(name)) {
                 try {
-                    return sLockSettings.getString(name, "0", UserId.getCallingUserId());
+                    return sLockSettings.getString(name, "0", UserHandle.getCallingUserId());
                 } catch (RemoteException re) {
                     // Fall through
                 }
@@ -2585,6 +2588,13 @@
         public static final String DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled";
 
         /**
+         * When the user has enable the option to have a "bug report" command
+         * in the power menu.
+         * @hide
+         */
+        public static final String BUGREPORT_IN_POWER_MENU = "bugreport_in_power_menu";
+
+        /**
          * Whether ADB is enabled.
          */
         public static final String ADB_ENABLED = "adb_enabled";
@@ -2794,6 +2804,13 @@
         public static final String DISPLAY_SIZE_FORCED = "display_size_forced";
 
         /**
+         * 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";
+
+        /**
          * Whether assisted GPS should be enabled or not.
          * @hide
          */
@@ -2838,6 +2855,29 @@
          */
         public static final String TETHER_DUN_APN = "tether_dun_apn";
 
+        /** 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";
+
         /**
          * No longer supported.
          */
@@ -3239,13 +3279,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,21 +3307,12 @@
                 "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";
-
-        /**
-         * The URL used for walled garden check upon a new conection. WifiWatchdogService
-         * fetches the URL and checks to see if {@link #WIFI_WATCHDOG_WALLED_GARDEN_PATTERN}
-         * is not part of the title string to notify the user on the presence of a walled garden.
-         * @hide
-         */
-        public static final String WIFI_WATCHDOG_WALLED_GARDEN_URL =
-                "wifi_watchdog_walled_garden_url";
+        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
@@ -3314,6 +3338,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.
          */
@@ -4200,27 +4239,40 @@
                 "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";
 
+        /**
+         * 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";
+
+        /**
+         * 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_ENABLED = "netstats_enabled";
         /** {@hide} */
@@ -4276,6 +4328,9 @@
         /** 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";
+
         /** {@hide} */
         public static final String
                 READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT = "read_external_storage_enforced_default";
@@ -4296,6 +4351,25 @@
         public static final String SMS_SHORT_CODES_PREFIX = "sms_short_codes_";
 
         /**
+         * Overlay display devices setting.
+         * The associated value is a specially formatted string that describes the
+         * size and density of simulated secondary display devices.
+         * <p>
+         * Format: {width}x{height}/{dpi};...
+         * </p><p>
+         * Example:
+         * <ul>
+         * <li><code>1280x720/213</code>: make one overlay that is 1280x720 at 213dpi.</li>
+         * <li><code>1920x1080/320;1280x720/213</code>: make two overlays, the first
+         * at 1080p and the second at 720p.</li>
+         * <li>If the value is empty, then no overlay display devices are created.</li>
+         * </ul></p>
+         *
+         * @hide
+         */
+        public static final String OVERLAY_DISPLAY_DEVICES = "overlay_display_devices";
+
+        /**
          * This are the settings to be backed up.
          *
          * NOTE: Settings are backed up and restored in the order they appear
@@ -4306,6 +4380,7 @@
          */
         public static final String[] SETTINGS_TO_BACKUP = {
             ADB_ENABLED,
+            BUGREPORT_IN_POWER_MENU,
             ALLOW_MOCK_LOCATION,
             PARENTAL_CONTROL_ENABLED,
             PARENTAL_CONTROL_REDIRECT_URL,
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..df85b2f 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,8 +131,12 @@
         }
 
         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);
@@ -132,7 +158,11 @@
 
         @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);
@@ -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..4e00ef9 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,11 @@
 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.Bundle;
+import android.os.RemoteException;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
@@ -38,6 +41,7 @@
 
 /**
  * This class maintains the information about all searchable activities.
+ * This is a hidden class.
  */
 public class Searchables {
 
@@ -65,12 +69,18 @@
     public static String ENHANCED_GOOGLE_SEARCH_COMPONENT_NAME =
             "com.google.android.providers.enhancedgooglesearch/.Launcher";
 
+    // Cache the package manager instance
+    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;
     }
 
     /**
@@ -195,16 +205,14 @@
         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) {
@@ -262,10 +270,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 +307,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 +378,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 +390,22 @@
         return null;
     }
 
+    private List<ResolveInfo> queryIntentActivities(Intent intent, int flags) {
+        if (mPm == null) {
+            mPm = AppGlobals.getPackageManager();
+        }
+        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..2cec6c3 100644
--- a/core/java/android/service/dreams/DreamManagerService.java
+++ b/core/java/android/service/dreams/DreamManagerService.java
@@ -1,12 +1,10 @@
 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.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -16,40 +14,38 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.SystemClock;
 import android.provider.Settings;
-import android.util.Log;
 import android.util.Slog;
 import android.view.IWindowManager;
 import android.view.WindowManager;
+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;
 
     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 +56,10 @@
     }
 
     // IDreamManager method
+    @Override
     public void dream() {
-        ComponentName name = getDreamComponent();
+        ComponentName[] dreams = getDreamComponents();
+        ComponentName name = dreams != null && dreams.length > 0 ? dreams[0] : null;
         if (name != null) {
             synchronized (mLock) {
                 final long ident = Binder.clearCallingIdentity();
@@ -75,26 +73,50 @@
     }
 
     // IDreamManager method
-    public void setDreamComponent(ComponentName name) {
-        Settings.Secure.putString(mContext.getContentResolver(), SCREENSAVER_COMPONENT, name.flattenToString());
+    @Override
+    public void setDreamComponents(ComponentName[] componentNames) {
+        Settings.Secure.putString(mContext.getContentResolver(),
+                SCREENSAVER_COMPONENTS,
+                componentsToString(componentNames));
     }
-    
-    // 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() {
+        // TODO(dsandler) don't load this every time, watch the value
+        String names = Settings.Secure.getString(mContext.getContentResolver(), SCREENSAVER_COMPONENTS);
+        return names == null ? null : componentsFromString(names);
+    }
+
+    // IDreamManager method
+    @Override
+    public ComponentName getDefaultDreamComponent() {
+        String name = Settings.Secure.getString(mContext.getContentResolver(), SCREENSAVER_DEFAULT_COMPONENT);
+        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 +132,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 +163,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 +196,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);
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/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 3e0942c..efa8911 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);
 
@@ -1044,6 +1051,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/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..506594b 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,11 +206,11 @@
     public void setToDefaults() {
         widthPixels = 0;
         heightPixels = 0;
-        density = DENSITY_DEVICE / (float) DENSITY_DEFAULT;
-        densityDpi = DENSITY_DEVICE;
+        density = noncompatDensity = DENSITY_DEVICE / (float) DENSITY_DEFAULT;
+        densityDpi = noncompatDensityDpi = DENSITY_DEVICE;
         scaledDensity = density;
-        xdpi = DENSITY_DEVICE;
-        ydpi = DENSITY_DEVICE;
+        xdpi = noncompatXdpi = DENSITY_DEVICE;
+        ydpi = noncompatYdpi = DENSITY_DEVICE;
         noncompatWidthPixels = 0;
         noncompatHeightPixels = 0;
     }
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/PropertyValueModel.java b/core/java/android/util/PropertyValueModel.java
new file mode 100755
index 0000000..eb9c47d
--- /dev/null
+++ b/core/java/android/util/PropertyValueModel.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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;
+
+/**
+ * A value model for a {@link Property property} of a host object. This class can be used for
+ * both reflective and non-reflective property implementations.
+ *
+ * @param <H> the host type, where the host is the object that holds this property
+ * @param <T> the value type
+ *
+ * @see Property
+ * @see ValueModel
+ */
+public class PropertyValueModel<H, T> extends ValueModel<T> {
+    private final H mHost;
+    private final Property<H, T> mProperty;
+
+    private PropertyValueModel(H host, Property<H, T> property) {
+        mProperty = property;
+        mHost = host;
+    }
+
+    /**
+     * Returns the host.
+     *
+     * @return the host
+     */
+    public H getHost() {
+        return mHost;
+    }
+
+    /**
+     * Returns the property.
+     *
+     * @return the property
+     */
+    public Property<H, T> getProperty() {
+        return mProperty;
+    }
+
+    @Override
+    public Class<T> getType() {
+        return mProperty.getType();
+    }
+
+    @Override
+    public T get() {
+        return mProperty.get(mHost);
+    }
+
+    @Override
+    public void set(T value) {
+        mProperty.set(mHost, value);
+    }
+
+    /**
+     * Return an appropriate PropertyValueModel for this host and property.
+     *
+     * @param host the host
+     * @param property the property
+     * @return the value model
+     */
+    public static <H, T> PropertyValueModel<H, T> of(H host, Property<H, T> property) {
+        return new PropertyValueModel<H, T>(host, property);
+    }
+
+    /**
+     * Return a PropertyValueModel for this {@code host} and a
+     * reflective property, constructed from this {@code propertyType} and {@code propertyName}.
+     *
+     * @param host
+     * @param propertyType the property type
+     * @param propertyName the property name
+     * @return a value model with this host and a reflective property with this type and name
+     *
+     * @see Property#of
+     */
+    public static <H, T> PropertyValueModel<H, T> of(H host, Class<T> propertyType,
+            String propertyName) {
+        return of(host, Property.of((Class<H>) host.getClass(), propertyType, propertyName));
+    }
+
+    private static Class getNullaryMethodReturnType(Class c, String name) {
+        try {
+            return c.getMethod(name).getReturnType();
+        } catch (NoSuchMethodException e) {
+            return null;
+        }
+    }
+
+    private static Class getFieldType(Class c, String name) {
+        try {
+            return c.getField(name).getType();
+        } catch (NoSuchFieldException e) {
+            return null;
+        }
+    }
+
+    private static String capitalize(String name) {
+        if (name.isEmpty()) {
+            return name;
+        }
+        return Character.toUpperCase(name.charAt(0)) + name.substring(1);
+    }
+
+    /**
+     * Return a PropertyValueModel for this {@code host} and and {@code propertyName}.
+     *
+     * @param host the host
+     * @param propertyName the property name
+     * @return a value model with this host and a reflective property with this name
+     */
+    public static PropertyValueModel of(Object host, String propertyName) {
+        Class clazz = host.getClass();
+        String suffix = capitalize(propertyName);
+        Class propertyType = getNullaryMethodReturnType(clazz, "get" + suffix);
+        if (propertyType == null) {
+            propertyType = getNullaryMethodReturnType(clazz, "is" + suffix);
+        } 
+        if (propertyType == null) {
+            propertyType = getFieldType(clazz, propertyName); 
+        }         
+        if (propertyType == null) {
+            throw new NoSuchPropertyException(propertyName); 
+        }
+        return of(host, propertyType, propertyName);
+    }
+}
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/util/ValueModel.java b/core/java/android/util/ValueModel.java
new file mode 100755
index 0000000..4789682
--- /dev/null
+++ b/core/java/android/util/ValueModel.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 android.util;
+
+/**
+ * A ValueModel is an abstraction for a 'slot' or place in memory in which a value
+ * may be stored and retrieved. A common implementation of ValueModel is a regular property of
+ * an object, whose value may be retrieved by calling the appropriate <em>getter</em>
+ * method and set by calling the corresponding <em>setter</em> method.
+ *
+ * @param <T> the value type
+ *
+ * @see PropertyValueModel
+ */
+public abstract class ValueModel<T> {
+    /**
+     * The empty model should be used in place of {@code null} to indicate that a
+     * model has not been set. The empty model has no value and does nothing when it is set.
+     */
+    public static final ValueModel EMPTY = new ValueModel() {
+        @Override
+        public Class getType() {
+            return Object.class;
+        }
+
+        @Override
+        public Object get() {
+            return null;
+        }
+
+        @Override
+        public void set(Object value) {
+
+        }
+    };
+
+    protected ValueModel() {
+    }
+
+    /**
+     * Returns the type of this property.
+     *
+     * @return the property type
+     */
+    public abstract Class<T> getType();
+
+    /**
+     * Returns the value of this property.
+     *
+     * @return the property value
+     */
+    public abstract T get();
+
+    /**
+     * Sets the value of this property.
+     *
+     * @param value the new value for this property
+     */
+    public abstract void set(T value);
+}
\ No newline at end of file
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..ec635a2 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -16,61 +16,155 @@
 
 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 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.
+     * 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
      */
-    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 Display(DisplayManagerGlobal global,
+            int displayId, DisplayInfo displayInfo /*not null*/,
+            CompatibilityInfoHolder compatibilityInfo) {
+        mGlobal = global;
+        mDisplayId = displayId;
+        mDisplayInfo = displayInfo;
+        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 layer stack number.
+     * @hide
+     */
+    public int getLayerStack() {
+        // Note: This is the current convention but there is no requirement that
+        // the display id and layer stack id be the same.
+        return mDisplayId;
+    }
+
+    /**
+     * Gets the compatibility info used by this display instance.
+     *
+     * @return The compatibility info holder, or null if none is required.
+     * @hide
+     */
+    public CompatibilityInfoHolder getCompatibilityInfo() {
+        return mCompatibilityInfo;
+    }
+
     /**
      * Gets the size of the display, in pixels.
      * <p>
@@ -84,7 +178,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 +186,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 +201,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 +239,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 +254,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 +265,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 +276,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 +300,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 +352,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/cmds/sensorservice/main_sensorservice.cpp b/core/java/android/view/DisplayInfo.aidl
similarity index 69%
copy from cmds/sensorservice/main_sensorservice.cpp
copy to core/java/android/view/DisplayInfo.aidl
index 8610627..e679208 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/core/java/android/view/DisplayInfo.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,12 +14,6 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+package android.view;
 
-using namespace android;
-
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
-}
+parcelable DisplayInfo;
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
new file mode 100644
index 0000000..593e8c4
--- /dev/null
+++ b/core/java/android/view/DisplayInfo.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.view;
+
+import android.content.res.CompatibilityInfo;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.DisplayMetrics;
+
+/**
+ * Describes the characteristics of a particular logical display.
+ * @hide
+ */
+public final class DisplayInfo implements Parcelable {
+    /**
+     * 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 int describeContents() {
+        return 0;
+    }
+
+    public void copyFrom(DisplayInfo other) {
+        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) {
+        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(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);
+    }
+
+    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 "app " + appWidth + " x " + appHeight
+                + ", real " + logicalWidth + " x " + logicalHeight
+                + ", largest app " + largestNominalAppWidth + " x " + largestNominalAppHeight
+                + ", smallest app " + smallestNominalAppWidth + " x " + smallestNominalAppHeight
+                + ", " + refreshRate + " fps"
+                + ", rotation " + rotation
+                + ", density " + logicalDensityDpi
+                + ", " + physicalXDpi + " x " + physicalYDpi + " dpi";
+    }
+}
diff --git a/core/java/android/view/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..f4ab133 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -151,12 +151,12 @@
     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 void nSetOpaqueLayer(int layerId, boolean isOpaque);
     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);
diff --git a/core/java/android/view/GLES20Layer.java b/core/java/android/view/GLES20Layer.java
index 4f25792..a0ae379 100644
--- a/core/java/android/view/GLES20Layer.java
+++ b/core/java/android/view/GLES20Layer.java
@@ -46,11 +46,6 @@
     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 +55,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/GLES20RenderLayer.java b/core/java/android/view/GLES20RenderLayer.java
index c727a36..a77425a 100644
--- a/core/java/android/view/GLES20RenderLayer.java
+++ b/core/java/android/view/GLES20RenderLayer.java
@@ -71,6 +71,12 @@
     }
 
     @Override
+    void setOpaque(boolean isOpaque) {
+        mOpaque = isOpaque;
+        GLES20Canvas.nSetOpaqueLayer(mLayer, isOpaque);
+    }
+
+    @Override
     HardwareCanvas getCanvas() {
         return mCanvas;
     }
diff --git a/core/java/android/view/GLES20TextureLayer.java b/core/java/android/view/GLES20TextureLayer.java
index 16a13cf..e198ef6 100644
--- a/core/java/android/view/GLES20TextureLayer.java
+++ b/core/java/android/view/GLES20TextureLayer.java
@@ -42,12 +42,6 @@
         }        
     }
 
-    GLES20TextureLayer(SurfaceTexture surface, boolean isOpaque) {
-        this(isOpaque);
-        mSurface = surface;
-        mSurface.attachToGLContext(mTexture);
-    }
-
     @Override
     boolean isValid() {
         return mLayer != 0 && mTexture != 0;
@@ -93,6 +87,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 0114a41..23337f0 100644
--- a/core/java/android/view/GestureDetector.java
+++ b/core/java/android/view/GestureDetector.java
@@ -226,17 +226,12 @@
      */
     private boolean mIsDoubleTapping;
 
-    private float mLastMotionY;
-    private float mLastMotionX;
+    private float mLastFocusX;
+    private float mLastFocusY;
+    private float mDownFocusX;
+    private float mDownFocusY;
 
     private boolean mIsLongpressEnabled;
-    
-    /**
-     * True if we are at a target API level of >= Froyo or the developer can
-     * explicitly set it. If true, input events with > 1 pointer will be ignored
-     * so we can work side by side with multitouch gesture detectors.
-     */
-    private boolean mIgnoreMultitouch;
 
     /**
      * Determines speed during touch scrolling
@@ -349,8 +344,16 @@
      * @throws NullPointerException if {@code listener} is null.
      */
     public GestureDetector(Context context, OnGestureListener listener, Handler handler) {
-        this(context, listener, handler, context != null &&
-                context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.FROYO);
+        if (handler != null) {
+            mHandler = new GestureHandler(handler);
+        } else {
+            mHandler = new GestureHandler();
+        }
+        mListener = listener;
+        if (listener instanceof OnDoubleTapListener) {
+            setOnDoubleTapListener((OnDoubleTapListener) listener);
+        }
+        init(context);
     }
     
     /**
@@ -362,31 +365,19 @@
      * @param listener the listener invoked for all the callbacks, this must
      * not be null.
      * @param handler the handler to use
-     * @param ignoreMultitouch whether events involving more than one pointer should
-     * be ignored.
      *
      * @throws NullPointerException if {@code listener} is null.
      */
     public GestureDetector(Context context, OnGestureListener listener, Handler handler,
-            boolean ignoreMultitouch) {
-        if (handler != null) {
-            mHandler = new GestureHandler(handler);
-        } else {
-            mHandler = new GestureHandler();
-        }
-        mListener = listener;
-        if (listener instanceof OnDoubleTapListener) {
-            setOnDoubleTapListener((OnDoubleTapListener) listener);
-        }
-        init(context, ignoreMultitouch);
+            boolean unused) {
+        this(context, listener, handler);
     }
 
-    private void init(Context context, boolean ignoreMultitouch) {
+    private void init(Context context) {
         if (mListener == null) {
             throw new NullPointerException("OnGestureListener must not be null");
         }
         mIsLongpressEnabled = true;
-        mIgnoreMultitouch = ignoreMultitouch;
 
         // Fallback to support pre-donuts releases
         int touchSlop, doubleTapSlop, doubleTapTouchSlop;
@@ -456,34 +447,40 @@
         }
 
         final int action = ev.getAction();
-        final float y = ev.getY();
-        final float x = ev.getX();
 
         if (mVelocityTracker == null) {
             mVelocityTracker = VelocityTracker.obtain();
         }
         mVelocityTracker.addMovement(ev);
 
+        final boolean pointerUp = action == MotionEvent.ACTION_POINTER_UP;
+        final int skipIndex = pointerUp ? ev.getActionIndex() : -1;
+
+        // Determine focal point
+        float sumX = 0, sumY = 0;
+        final int count = ev.getPointerCount();
+        for (int i = 0; i < count; i++) {
+            if (skipIndex == i) continue;
+            sumX += ev.getX(i);
+            sumY += ev.getY(i);
+        }
+        final int div = pointerUp ? count - 1 : count;
+        final float focusX = sumX / div;
+        final float focusY = sumY / div;
+
         boolean handled = false;
 
         switch (action & MotionEvent.ACTION_MASK) {
         case MotionEvent.ACTION_POINTER_DOWN:
-            if (mIgnoreMultitouch) {
-                // Multitouch event - abort.
-                cancel();
-            }
+            mDownFocusX = mLastFocusX = focusX;
+            mDownFocusY = mLastFocusY = focusY;
+            // Cancel long press and taps
+            cancelTaps();
             break;
 
         case MotionEvent.ACTION_POINTER_UP:
-            // Ending a multitouch gesture and going back to 1 finger
-            if (mIgnoreMultitouch && ev.getPointerCount() == 2) {
-                int index = (((action & MotionEvent.ACTION_POINTER_INDEX_MASK)
-                        >> MotionEvent.ACTION_POINTER_INDEX_SHIFT) == 0) ? 1 : 0;
-                mLastMotionX = ev.getX(index);
-                mLastMotionY = ev.getY(index);
-                mVelocityTracker.recycle();
-                mVelocityTracker = VelocityTracker.obtain();
-            }
+            mDownFocusX = mLastFocusX = focusX;
+            mDownFocusY = mLastFocusY = focusY;
             break;
 
         case MotionEvent.ACTION_DOWN:
@@ -504,8 +501,8 @@
                 }
             }
 
-            mLastMotionX = x;
-            mLastMotionY = y;
+            mDownFocusX = mLastFocusX = focusX;
+            mDownFocusY = mLastFocusY = focusY;
             if (mCurrentDownEvent != null) {
                 mCurrentDownEvent.recycle();
             }
@@ -525,22 +522,22 @@
             break;
 
         case MotionEvent.ACTION_MOVE:
-            if (mInLongPress || (mIgnoreMultitouch && ev.getPointerCount() > 1)) {
+            if (mInLongPress) {
                 break;
             }
-            final float scrollX = mLastMotionX - x;
-            final float scrollY = mLastMotionY - y;
+            final float scrollX = mLastFocusX - focusX;
+            final float scrollY = mLastFocusY - focusY;
             if (mIsDoubleTapping) {
                 // Give the move events of the double-tap
                 handled |= mDoubleTapListener.onDoubleTapEvent(ev);
             } else if (mAlwaysInTapRegion) {
-                final int deltaX = (int) (x - mCurrentDownEvent.getX());
-                final int deltaY = (int) (y - mCurrentDownEvent.getY());
+                final int deltaX = (int) (focusX - mDownFocusX);
+                final int deltaY = (int) (focusY - mDownFocusY);
                 int distance = (deltaX * deltaX) + (deltaY * deltaY);
                 if (distance > mTouchSlopSquare) {
                     handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY);
-                    mLastMotionX = x;
-                    mLastMotionY = y;
+                    mLastFocusX = focusX;
+                    mLastFocusY = focusY;
                     mAlwaysInTapRegion = false;
                     mHandler.removeMessages(TAP);
                     mHandler.removeMessages(SHOW_PRESS);
@@ -551,8 +548,8 @@
                 }
             } else if ((Math.abs(scrollX) >= 1) || (Math.abs(scrollY) >= 1)) {
                 handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY);
-                mLastMotionX = x;
-                mLastMotionY = y;
+                mLastFocusX = focusX;
+                mLastFocusY = focusY;
             }
             break;
 
@@ -571,9 +568,10 @@
 
                 // A fling must travel the minimum tap distance
                 final VelocityTracker velocityTracker = mVelocityTracker;
+                final int pointerId = ev.getPointerId(0);
                 velocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity);
-                final float velocityY = velocityTracker.getYVelocity();
-                final float velocityX = velocityTracker.getXVelocity();
+                final float velocityY = velocityTracker.getYVelocity(pointerId);
+                final float velocityX = velocityTracker.getXVelocity(pointerId);
 
                 if ((Math.abs(velocityY) > mMinimumFlingVelocity)
                         || (Math.abs(velocityX) > mMinimumFlingVelocity)){
@@ -622,6 +620,18 @@
         }
     }
 
+    private void cancelTaps() {
+        mHandler.removeMessages(SHOW_PRESS);
+        mHandler.removeMessages(LONG_PRESS);
+        mHandler.removeMessages(TAP);
+        mIsDoubleTapping = false;
+        mAlwaysInTapRegion = false;
+        mAlwaysInBiggerTapRegion = false;
+        if (mInLongPress) {
+            mInLongPress = false;
+        }
+    }
+
     private boolean isConsideredDoubleTap(MotionEvent firstDown, MotionEvent firstUp,
             MotionEvent secondDown) {
         if (!mAlwaysInBiggerTapRegion) {
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..06c6e7c 100644
--- a/core/java/android/view/HardwareLayer.java
+++ b/core/java/android/view/HardwareLayer.java
@@ -107,6 +107,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
@@ -136,11 +143,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..f906e24 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);
                 }
             }
@@ -742,10 +754,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 +783,9 @@
         }
         
         @Override
-        void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException {
+        void updateSurface(Surface surface) throws Surface.OutOfResourcesException {
             if (isRequested() && isEnabled()) {
-                createEglSurface(holder);
+                createEglSurface(surface);
             }
         }
 
@@ -888,7 +900,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 +920,7 @@
             destroySurface();
 
             // Create an EGL surface we can render into.
-            if (!createSurface(holder)) {
+            if (!createSurface(surface)) {
                 return null;
             }
 
@@ -982,7 +994,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 +1005,8 @@
                 setEnabled(false);
             }
 
-            if (holder.getSurface().isValid()) {
-                if (!createSurface(holder)) {
+            if (surface.isValid()) {
+                if (!createSurface(surface)) {
                     return;
                 }
 
@@ -1006,8 +1018,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 +1101,7 @@
                 attachInfo.mIgnoreDirtyState = true;
                 attachInfo.mDrawingTime = SystemClock.uptimeMillis();
 
-                view.mPrivateFlags |= View.DRAWN;
+                view.mPrivateFlags |= View.PFLAG_DRAWN;
 
                 final int surfaceState = checkCurrent();
                 if (surfaceState != SURFACE_STATE_ERROR) {
@@ -1123,9 +1135,9 @@
                     callbacks.onHardwarePreDraw(canvas);
 
                     try {
-                        view.mRecreateDisplayList =
-                                (view.mPrivateFlags & View.INVALIDATED) == View.INVALIDATED;
-                        view.mPrivateFlags &= ~View.INVALIDATED;
+                        view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
+                                == View.PFLAG_INVALIDATED;
+                        view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
 
                         long getDisplayListStartTime = 0;
                         if (mProfileEnabled) {
diff --git a/core/java/android/view/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/packages/SystemUI/res/values-sw720dp-port/dimens.xml b/core/java/android/view/IInputFilterHost.aidl
similarity index 64%
copy from packages/SystemUI/res/values-sw720dp-port/dimens.xml
copy to core/java/android/view/IInputFilterHost.aidl
index 74b266d..93b8239 100644
--- a/packages/SystemUI/res/values-sw720dp-port/dimens.xml
+++ b/core/java/android/view/IInputFilterHost.aidl
@@ -1,6 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (c) 2011, 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.
@@ -13,10 +12,17 @@
  * WITHOUT 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>
+ */
 
+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..7f2de50 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -23,6 +23,7 @@
 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.IOnKeyguardExitResult;
@@ -33,6 +34,7 @@
 import android.view.MotionEvent;
 import android.view.InputChannel;
 import android.view.InputDevice;
+import  android.view.IInputFilter;
 
 /**
  * System private interface to the window manager.
@@ -54,14 +56,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 longDimen, int shortDimen);
+    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 +84,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,
@@ -187,7 +186,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 +207,24 @@
      * Lock the device immediately.
      */
     void lockNow();
+
+    /**
+     * Gets the token for the focused window.
+     */
+    IBinder getFocusedWindowToken();
+
+    /**
+     * Gets the frame on the screen of the window given its token.
+     */
+    boolean getWindowFrame(IBinder token, out Rect outBounds);
+
+    /**
+     * 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);
 }
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index d4a03ce..c5d9255 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,7 @@
             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);
 }
diff --git a/core/java/android/view/InputEventReceiver.java b/core/java/android/view/InputEventReceiver.java
index 9c56782..117c101 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/services/java/com/android/server/input/InputFilter.java b/core/java/android/view/InputFilter.java
similarity index 94%
rename from services/java/com/android/server/input/InputFilter.java
rename to core/java/android/view/InputFilter.java
index 2ce0a02..c25b87b 100644
--- a/services/java/com/android/server/input/InputFilter.java
+++ b/core/java/android/view/InputFilter.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.server.input;
-
-import com.android.server.wm.WindowManagerService;
+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;
@@ -94,15 +94,14 @@
  * 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 {
+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;
 
-    private final H mH;
-    private Host mHost;
-
     // Consistency verifiers for debugging purposes.
     private final InputEventConsistencyVerifier mInboundInputEventConsistencyVerifier =
             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
@@ -115,6 +114,10 @@
                             InputEventConsistencyVerifier.FLAG_RAW_DEVICE_INPUT,
                             "InputFilter#OutboundInputEventConsistencyVerifier") : null;
 
+    private final H mH;
+
+    private IInputFilterHost mHost;
+
     /**
      * Creates the input filter.
      *
@@ -130,7 +133,7 @@
      *
      * @param host The input filter host environment.
      */
-    final void install(Host host) {
+    public final void install(IInputFilterHost host) {
         mH.obtainMessage(MSG_INSTALL, host).sendToTarget();
     }
 
@@ -138,7 +141,7 @@
      * Called when the input filter is uninstalled.
      * This method is guaranteed to be non-reentrant.
      */
-    final void uninstall() {
+    public final void uninstall() {
         mH.obtainMessage(MSG_UNINSTALL).sendToTarget();
     }
 
@@ -149,7 +152,7 @@
      *
      * @param event The input event to enqueue.
      */
-    final void filterInputEvent(InputEvent event, int policyFlags) {
+    final public void filterInputEvent(InputEvent event, int policyFlags) {
         mH.obtainMessage(MSG_INPUT_EVENT, policyFlags, 0, event).sendToTarget();
     }
 
@@ -170,7 +173,11 @@
         if (mOutboundInputEventConsistencyVerifier != null) {
             mOutboundInputEventConsistencyVerifier.onInputEvent(event, 0);
         }
-        mHost.sendInputEvent(event, policyFlags);
+        try {
+            mHost.sendInputEvent(event, policyFlags);
+        } catch (RemoteException re) {
+            /* ignore */
+        }
     }
 
     /**
@@ -218,7 +225,7 @@
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case MSG_INSTALL:
-                    mHost = (Host)msg.obj;
+                    mHost = (IInputFilterHost) msg.obj;
                     if (mInboundInputEventConsistencyVerifier != null) {
                         mInboundInputEventConsistencyVerifier.reset();
                     }
@@ -251,8 +258,4 @@
             }
         }
     }
-
-    interface Host {
-        public void sendInputEvent(InputEvent event, int policyFlags);
-    }
 }
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 73f94bc..dc36088 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -17,14 +17,13 @@
 package android.view;
 
 import android.content.Context;
-import android.util.DisplayMetrics;
 import android.util.FloatMath;
-import android.util.Log;
 
 /**
- * Detects transformation gestures involving more than one pointer ("multitouch")
- * using the supplied {@link MotionEvent}s. The {@link OnScaleGestureListener}
- * callback will notify users when a particular gesture event has occurred.
+ * Detects scaling transformation gestures using the supplied {@link MotionEvent}s.
+ * The {@link OnScaleGestureListener} callback will notify users when a particular
+ * gesture event has occurred.
+ *
  * This class should only be used with {@link MotionEvent}s reported via touch.
  *
  * To use this class:
@@ -121,43 +120,21 @@
         }
     }
 
-    /**
-     * This value is the threshold ratio between our previous combined pressure
-     * and the current combined pressure. We will only fire an onScale event if
-     * the computed ratio between the current and previous event pressures is
-     * greater than this value. When pressure decreases rapidly between events
-     * the position values can often be imprecise, as it usually indicates
-     * that the user is in the process of lifting a pointer off of the device.
-     * Its value was tuned experimentally.
-     */
-    private static final float PRESSURE_THRESHOLD = 0.67f;
-
     private final Context mContext;
     private final OnScaleGestureListener mListener;
-    private boolean mGestureInProgress;
-
-    private MotionEvent mPrevEvent;
-    private MotionEvent mCurrEvent;
 
     private float mFocusX;
     private float mFocusY;
-    private float mPrevFingerDiffX;
-    private float mPrevFingerDiffY;
-    private float mCurrFingerDiffX;
-    private float mCurrFingerDiffY;
-    private float mCurrLen;
-    private float mPrevLen;
-    private float mScaleFactor;
-    private float mCurrPressure;
-    private float mPrevPressure;
-    private long mTimeDelta;
 
-    private boolean mInvalidGesture;
-
-    // Pointer IDs currently responsible for the two fingers controlling the gesture
-    private int mActiveId0;
-    private int mActiveId1;
-    private boolean mActive0MostRecent;
+    private float mCurrSpan;
+    private float mPrevSpan;
+    private float mCurrSpanX;
+    private float mCurrSpanY;
+    private float mPrevSpanX;
+    private float mPrevSpanY;
+    private long mCurrTime;
+    private long mPrevTime;
+    private boolean mInProgress;
 
     /**
      * Consistency verifier for debugging purposes.
@@ -171,6 +148,18 @@
         mListener = listener;
     }
 
+    /**
+     * Accepts MotionEvents and dispatches events to a {@link OnScaleGestureListener}
+     * when appropriate.
+     *
+     * <p>Applications should pass a complete and consistent event stream to this method.
+     * A complete and consistent event stream involves all MotionEvents from the initial
+     * ACTION_DOWN to the final ACTION_UP or ACTION_CANCEL.</p>
+     *
+     * @param event The event to process
+     * @return true if the event was processed and the detector wants to receive the
+     *         rest of the MotionEvents in this event stream.
+     */
     public boolean onTouchEvent(MotionEvent event) {
         if (mInputEventConsistencyVerifier != null) {
             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
@@ -178,265 +167,110 @@
 
         final int action = event.getActionMasked();
 
-        if (action == MotionEvent.ACTION_DOWN) {
-            reset(); // Start fresh
-        }
-
-        boolean handled = true;
-        if (mInvalidGesture) {
-            handled = false;
-        } else if (!mGestureInProgress) {
-            switch (action) {
-                case MotionEvent.ACTION_DOWN: {
-                    mActiveId0 = event.getPointerId(0);
-                    mActive0MostRecent = true;
-                }
-                break;
-
-                case MotionEvent.ACTION_UP:
-                    reset();
-                    break;
-
-                case MotionEvent.ACTION_POINTER_DOWN: {
-                    // We have a new multi-finger gesture
-                    if (mPrevEvent != null) mPrevEvent.recycle();
-                    mPrevEvent = MotionEvent.obtain(event);
-                    mTimeDelta = 0;
-
-                    int index1 = event.getActionIndex();
-                    int index0 = event.findPointerIndex(mActiveId0);
-                    mActiveId1 = event.getPointerId(index1);
-                    if (index0 < 0 || index0 == index1) {
-                        // Probably someone sending us a broken event stream.
-                        index0 = findNewActiveIndex(event, mActiveId1, -1);
-                        mActiveId0 = event.getPointerId(index0);
-                    }
-                    mActive0MostRecent = false;
-
-                    setContext(event);
-
-                    mGestureInProgress = mListener.onScaleBegin(this);
-                    break;
-                }
-            }
-        } else {
-            // Transform gesture in progress - attempt to handle it
-            switch (action) {
-                case MotionEvent.ACTION_POINTER_DOWN: {
-                    // End the old gesture and begin a new one with the most recent two fingers.
-                    mListener.onScaleEnd(this);
-                    final int oldActive0 = mActiveId0;
-                    final int oldActive1 = mActiveId1;
-                    reset();
-
-                    mPrevEvent = MotionEvent.obtain(event);
-                    mActiveId0 = mActive0MostRecent ? oldActive0 : oldActive1;
-                    mActiveId1 = event.getPointerId(event.getActionIndex());
-                    mActive0MostRecent = false;
-
-                    int index0 = event.findPointerIndex(mActiveId0);
-                    if (index0 < 0 || mActiveId0 == mActiveId1) {
-                        // Probably someone sending us a broken event stream.
-                        Log.e(TAG, "Got " + MotionEvent.actionToString(action) +
-                                " with bad state while a gesture was in progress. " +
-                                "Did you forget to pass an event to " +
-                                "ScaleGestureDetector#onTouchEvent?");
-                        index0 = findNewActiveIndex(event, mActiveId1, -1);
-                        mActiveId0 = event.getPointerId(index0);
-                    }
-
-                    setContext(event);
-
-                    mGestureInProgress = mListener.onScaleBegin(this);
-                }
-                break;
-
-                case MotionEvent.ACTION_POINTER_UP: {
-                    final int pointerCount = event.getPointerCount();
-                    final int actionIndex = event.getActionIndex();
-                    final int actionId = event.getPointerId(actionIndex);
-
-                    boolean gestureEnded = false;
-                    if (pointerCount > 2) {
-                        if (actionId == mActiveId0) {
-                            final int newIndex = findNewActiveIndex(event, mActiveId1, actionIndex);
-                            if (newIndex >= 0) {
-                                mListener.onScaleEnd(this);
-                                mActiveId0 = event.getPointerId(newIndex);
-                                mActive0MostRecent = true;
-                                mPrevEvent = MotionEvent.obtain(event);
-                                setContext(event);
-                                mGestureInProgress = mListener.onScaleBegin(this);
-                            } else {
-                                gestureEnded = true;
-                            }
-                        } else if (actionId == mActiveId1) {
-                            final int newIndex = findNewActiveIndex(event, mActiveId0, actionIndex);
-                            if (newIndex >= 0) {
-                                mListener.onScaleEnd(this);
-                                mActiveId1 = event.getPointerId(newIndex);
-                                mActive0MostRecent = false;
-                                mPrevEvent = MotionEvent.obtain(event);
-                                setContext(event);
-                                mGestureInProgress = mListener.onScaleBegin(this);
-                            } else {
-                                gestureEnded = true;
-                            }
-                        }
-                        mPrevEvent.recycle();
-                        mPrevEvent = MotionEvent.obtain(event);
-                        setContext(event);
-                    } else {
-                        gestureEnded = true;
-                    }
-
-                    if (gestureEnded) {
-                        // Gesture ended
-                        setContext(event);
-
-                        // Set focus point to the remaining finger
-                        final int activeId = actionId == mActiveId0 ? mActiveId1 : mActiveId0;
-                        final int index = event.findPointerIndex(activeId);
-                        mFocusX = event.getX(index);
-                        mFocusY = event.getY(index);
-
-                        mListener.onScaleEnd(this);
-                        reset();
-                        mActiveId0 = activeId;
-                        mActive0MostRecent = true;
-                    }
-                }
-                break;
-
-                case MotionEvent.ACTION_CANCEL:
-                    mListener.onScaleEnd(this);
-                    reset();
-                    break;
-
-                case MotionEvent.ACTION_UP:
-                    reset();
-                    break;
-
-                case MotionEvent.ACTION_MOVE: {
-                    setContext(event);
-
-                    // Only accept the event if our relative pressure is within
-                    // a certain limit - this can help filter shaky data as a
-                    // finger is lifted.
-                    if (mCurrPressure / mPrevPressure > PRESSURE_THRESHOLD) {
-                        final boolean updatePrevious = mListener.onScale(this);
-
-                        if (updatePrevious) {
-                            mPrevEvent.recycle();
-                            mPrevEvent = MotionEvent.obtain(event);
-                        }
-                    }
-                }
-                break;
-            }
-        }
-
-        if (!handled && mInputEventConsistencyVerifier != null) {
-            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
-        }
-        return handled;
-    }
-
-    private int findNewActiveIndex(MotionEvent ev, int otherActiveId, int removedPointerIndex) {
-        final int pointerCount = ev.getPointerCount();
-
-        // It's ok if this isn't found and returns -1, it simply won't match.
-        final int otherActiveIndex = ev.findPointerIndex(otherActiveId);
-
-        // Pick a new id and update tracking state.
-        for (int i = 0; i < pointerCount; i++) {
-            if (i != removedPointerIndex && i != otherActiveIndex) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-    private void setContext(MotionEvent curr) {
-        if (mCurrEvent != null) {
-            mCurrEvent.recycle();
-        }
-        mCurrEvent = MotionEvent.obtain(curr);
-
-        mCurrLen = -1;
-        mPrevLen = -1;
-        mScaleFactor = -1;
-
-        final MotionEvent prev = mPrevEvent;
-
-        final int prevIndex0 = prev.findPointerIndex(mActiveId0);
-        final int prevIndex1 = prev.findPointerIndex(mActiveId1);
-        final int currIndex0 = curr.findPointerIndex(mActiveId0);
-        final int currIndex1 = curr.findPointerIndex(mActiveId1);
-
-        if (prevIndex0 < 0 || prevIndex1 < 0 || currIndex0 < 0 || currIndex1 < 0) {
-            mInvalidGesture = true;
-            Log.e(TAG, "Invalid MotionEvent stream detected.", new Throwable());
-            if (mGestureInProgress) {
+        final boolean streamComplete = action == MotionEvent.ACTION_UP ||
+                action == MotionEvent.ACTION_CANCEL;
+        if (action == MotionEvent.ACTION_DOWN || streamComplete) {
+            // Reset any scale in progress with the listener.
+            // If it's an ACTION_DOWN we're beginning a new event stream.
+            // This means the app probably didn't give us all the events. Shame on it.
+            if (mInProgress) {
                 mListener.onScaleEnd(this);
+                mInProgress = false;
             }
-            return;
+
+            if (streamComplete) {
+                return true;
+            }
         }
 
-        final float px0 = prev.getX(prevIndex0);
-        final float py0 = prev.getY(prevIndex0);
-        final float px1 = prev.getX(prevIndex1);
-        final float py1 = prev.getY(prevIndex1);
-        final float cx0 = curr.getX(currIndex0);
-        final float cy0 = curr.getY(currIndex0);
-        final float cx1 = curr.getX(currIndex1);
-        final float cy1 = curr.getY(currIndex1);
+        final boolean configChanged =
+                action == MotionEvent.ACTION_POINTER_UP ||
+                action == MotionEvent.ACTION_POINTER_DOWN;
+        final boolean pointerUp = action == MotionEvent.ACTION_POINTER_UP;
+        final int skipIndex = pointerUp ? event.getActionIndex() : -1;
 
-        final float pvx = px1 - px0;
-        final float pvy = py1 - py0;
-        final float cvx = cx1 - cx0;
-        final float cvy = cy1 - cy0;
-        mPrevFingerDiffX = pvx;
-        mPrevFingerDiffY = pvy;
-        mCurrFingerDiffX = cvx;
-        mCurrFingerDiffY = cvy;
-
-        mFocusX = cx0 + cvx * 0.5f;
-        mFocusY = cy0 + cvy * 0.5f;
-        mTimeDelta = curr.getEventTime() - prev.getEventTime();
-        mCurrPressure = curr.getPressure(currIndex0) + curr.getPressure(currIndex1);
-        mPrevPressure = prev.getPressure(prevIndex0) + prev.getPressure(prevIndex1);
-    }
-
-    private void reset() {
-        if (mPrevEvent != null) {
-            mPrevEvent.recycle();
-            mPrevEvent = null;
+        // Determine focal point
+        float sumX = 0, sumY = 0;
+        final int count = event.getPointerCount();
+        for (int i = 0; i < count; i++) {
+            if (skipIndex == i) continue;
+            sumX += event.getX(i);
+            sumY += event.getY(i);
         }
-        if (mCurrEvent != null) {
-            mCurrEvent.recycle();
-            mCurrEvent = null;
+        final int div = pointerUp ? count - 1 : count;
+        final float focusX = sumX / div;
+        final float focusY = sumY / div;
+
+        // Determine average deviation from focal point
+        float devSumX = 0, devSumY = 0;
+        for (int i = 0; i < count; i++) {
+            if (skipIndex == i) continue;
+            devSumX += Math.abs(event.getX(i) - focusX);
+            devSumY += Math.abs(event.getY(i) - focusY);
         }
-        mGestureInProgress = false;
-        mActiveId0 = -1;
-        mActiveId1 = -1;
-        mInvalidGesture = false;
+        final float devX = devSumX / div;
+        final float devY = devSumY / div;
+
+        // Span is the average distance between touch points through the focal point;
+        // i.e. the diameter of the circle with a radius of the average deviation from
+        // the focal point.
+        final float spanX = devX * 2;
+        final float spanY = devY * 2;
+        final float span = FloatMath.sqrt(spanX * spanX + spanY * spanY);
+
+        // Dispatch begin/end events as needed.
+        // If the configuration changes, notify the app to reset its current state by beginning
+        // a fresh scale event stream.
+        if (mInProgress && (span == 0 || configChanged)) {
+            mListener.onScaleEnd(this);
+            mInProgress = false;
+        }
+        if (configChanged) {
+            mPrevSpanX = mCurrSpanX = spanX;
+            mPrevSpanY = mCurrSpanY = spanY;
+            mPrevSpan = mCurrSpan = span;
+        }
+        if (!mInProgress && span != 0) {
+            mFocusX = focusX;
+            mFocusY = focusY;
+            mInProgress = mListener.onScaleBegin(this);
+        }
+
+        // Handle motion; focal point and span/scale factor are changing.
+        if (action == MotionEvent.ACTION_MOVE) {
+            mCurrSpanX = spanX;
+            mCurrSpanY = spanY;
+            mCurrSpan = span;
+            mFocusX = focusX;
+            mFocusY = focusY;
+
+            boolean updatePrev = true;
+            if (mInProgress) {
+                updatePrev = mListener.onScale(this);
+            }
+
+            if (updatePrev) {
+                mPrevSpanX = mCurrSpanX;
+                mPrevSpanY = mCurrSpanY;
+                mPrevSpan = mCurrSpan;
+            }
+        }
+
+        return true;
     }
 
     /**
-     * Returns {@code true} if a two-finger scale gesture is in progress.
-     * @return {@code true} if a scale gesture is in progress, {@code false} otherwise.
+     * Returns {@code true} if a scale gesture is in progress.
      */
     public boolean isInProgress() {
-        return mGestureInProgress;
+        return mInProgress;
     }
 
     /**
      * Get the X coordinate of the current gesture's focal point.
-     * If a gesture is in progress, the focal point is directly between
-     * the two pointers forming the gesture.
-     * If a gesture is ending, the focal point is the location of the
-     * remaining pointer on the screen.
+     * If a gesture is in progress, the focal point is between
+     * each of the pointers forming the gesture.
+     *
      * If {@link #isInProgress()} would return false, the result of this
      * function is undefined.
      *
@@ -448,10 +282,9 @@
 
     /**
      * Get the Y coordinate of the current gesture's focal point.
-     * If a gesture is in progress, the focal point is directly between
-     * the two pointers forming the gesture.
-     * If a gesture is ending, the focal point is the location of the
-     * remaining pointer on the screen.
+     * If a gesture is in progress, the focal point is between
+     * each of the pointers forming the gesture.
+     *
      * If {@link #isInProgress()} would return false, the result of this
      * function is undefined.
      *
@@ -462,73 +295,63 @@
     }
 
     /**
-     * Return the current distance between the two pointers forming the
-     * gesture in progress.
+     * Return the average distance between each of the pointers forming the
+     * gesture in progress through the focal point.
      *
      * @return Distance between pointers in pixels.
      */
     public float getCurrentSpan() {
-        if (mCurrLen == -1) {
-            final float cvx = mCurrFingerDiffX;
-            final float cvy = mCurrFingerDiffY;
-            mCurrLen = FloatMath.sqrt(cvx*cvx + cvy*cvy);
-        }
-        return mCurrLen;
+        return mCurrSpan;
     }
 
     /**
-     * Return the current x distance between the two pointers forming the
-     * gesture in progress.
+     * Return the average X distance between each of the pointers forming the
+     * gesture in progress through the focal point.
      *
      * @return Distance between pointers in pixels.
      */
     public float getCurrentSpanX() {
-        return mCurrFingerDiffX;
+        return mCurrSpanX;
     }
 
     /**
-     * Return the current y distance between the two pointers forming the
-     * gesture in progress.
+     * Return the average Y distance between each of the pointers forming the
+     * gesture in progress through the focal point.
      *
      * @return Distance between pointers in pixels.
      */
     public float getCurrentSpanY() {
-        return mCurrFingerDiffY;
+        return mCurrSpanY;
     }
 
     /**
-     * Return the previous distance between the two pointers forming the
-     * gesture in progress.
+     * Return the previous average distance between each of the pointers forming the
+     * gesture in progress through the focal point.
      *
      * @return Previous distance between pointers in pixels.
      */
     public float getPreviousSpan() {
-        if (mPrevLen == -1) {
-            final float pvx = mPrevFingerDiffX;
-            final float pvy = mPrevFingerDiffY;
-            mPrevLen = FloatMath.sqrt(pvx*pvx + pvy*pvy);
-        }
-        return mPrevLen;
+        return mPrevSpan;
     }
 
     /**
-     * Return the previous x distance between the two pointers forming the
-     * gesture in progress.
+     * Return the previous average X distance between each of the pointers forming the
+     * gesture in progress through the focal point.
      *
      * @return Previous distance between pointers in pixels.
      */
     public float getPreviousSpanX() {
-        return mPrevFingerDiffX;
+        return mPrevSpanX;
     }
 
     /**
-     * Return the previous y distance between the two pointers forming the
-     * gesture in progress.
+     * Return the previous average Y distance between each of the pointers forming the
+     * gesture in progress through the focal point.
      *
      * @return Previous distance between pointers in pixels.
      */
     public float getPreviousSpanY() {
-        return mPrevFingerDiffY;
+        return mPrevSpanY;
     }
 
     /**
@@ -539,10 +362,7 @@
      * @return The current scaling factor.
      */
     public float getScaleFactor() {
-        if (mScaleFactor == -1) {
-            mScaleFactor = getCurrentSpan() / getPreviousSpan();
-        }
-        return mScaleFactor;
+        return mPrevSpan > 0 ? mCurrSpan / mPrevSpan : 1;
     }
 
     /**
@@ -552,7 +372,7 @@
      * @return Time difference since the last scaling event in milliseconds.
      */
     public long getTimeDelta() {
-        return mTimeDelta;
+        return mCurrTime - mPrevTime;
     }
 
     /**
@@ -561,6 +381,6 @@
      * @return Current event time in milliseconds.
      */
     public long getEventTime() {
-        return mCurrEvent.getEventTime();
+        return mCurrTime;
     }
 }
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index a968768..cf1767d7 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,436 @@
     // 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, SurfaceTexture surfaceTexture);
+    private static native void nativeSetDisplayLayerStack(
+            IBinder displayToken, int layerStack);
+    private static native void nativeSetDisplayOrientation(
+            IBinder displayToken, int orientation);
+    private static native void nativeSetDisplayViewport(
+            IBinder displayToken, Rect viewport);
+    private static native void nativeSetDisplayFrame(
+            IBinder displayToken, Rect frame);
+    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, SurfaceTexture surfaceTexture) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        nativeSetDisplaySurface(displayToken, surfaceTexture);
+    }
+
+    /** @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 setDisplayOrientation(IBinder displayToken, int orientation) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        nativeSetDisplayOrientation(displayToken, orientation);
+    }
+
+    /** @hide */
+    public static void setDisplayViewport(IBinder displayToken, Rect viewport) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        if (viewport == null) {
+            throw new IllegalArgumentException("viewport must not be null");
+        }
+        nativeSetDisplayViewport(displayToken, viewport);
+    }
+
+    /** @hide */
+    public static void setDisplayFrame(IBinder displayToken, Rect frame) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        if (frame == null) {
+            throw new IllegalArgumentException("frame must not be null");
+        }
+        nativeSetDisplayFrame(displayToken, frame);
+    }
+
+    /** @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 +666,99 @@
      * 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.
      * @hide
      */
-    public native boolean isConsumerRunningBehind();
+    public static final class PhysicalDisplayInfo {
+        // TODO: redesign this
+        public int width;
+        public int height;
+        public float refreshRate;
+        public float density;
+        public float xDpi;
+        public float yDpi;
+    }
 
     /**
-     * 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 +771,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 +815,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..fdf1c22 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -296,7 +296,7 @@
         }
         
         boolean opaque = true;
-        if ((mPrivateFlags & SKIP_DRAW) == 0) {
+        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) {
             // this view draws, remove it from the transparent region
             opaque = super.gatherTransparentRegion(region);
         } else if (region != null) {
@@ -320,7 +320,7 @@
     public void draw(Canvas canvas) {
         if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
             // draw() is not called when SKIP_DRAW is set
-            if ((mPrivateFlags & SKIP_DRAW) == 0) {
+            if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) {
                 // punch a whole in the view-hierarchy below us
                 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
             }
@@ -332,7 +332,7 @@
     protected void dispatchDraw(Canvas canvas) {
         if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
             // if SKIP_DRAW is cleared, draw() has already punched a hole
-            if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
+            if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
                 // punch a whole in the view-hierarchy below us
                 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
             }
@@ -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()) {
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index a719a01..fe14c88 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -534,7 +534,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..745e1b8 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -39,6 +39,8 @@
 import android.graphics.Shader;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerGlobal;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -90,6 +92,7 @@
 import java.util.Arrays;
 import java.util.Locale;
 import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * <p>
@@ -343,9 +346,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 +631,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 +654,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 +663,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 +1010,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 +1041,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 +1570,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 +1588,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 +1647,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 +1685,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 +1713,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 +1726,7 @@
      *
      * @hide
      */
-    static final int INVALIDATED                  = 0x80000000;
+    static final int PFLAG_INVALIDATED                 = 0x80000000;
 
     /* Masks for mPrivateFlags2 */
 
@@ -1788,7 +1735,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 +1743,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 +1773,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 +1826,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 +1838,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 +1845,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 +1933,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 +1940,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 +1947,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 +1954,6 @@
      * Center the paragraph, e.g. ALIGN_CENTER.
      *
      * Use with {@link #setTextAlignment(int)}
-     * @hide
      */
     public static final int TEXT_ALIGNMENT_CENTER = 4;
 
@@ -2027,7 +1962,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 +1970,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 +2036,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 +2062,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 +2104,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 +2483,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;
@@ -2905,13 +2784,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 +2798,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 +3109,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 +3121,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 +3194,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 +3217,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 +3231,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 +3354,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);
@@ -3490,12 +3388,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 +3504,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 +3525,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 +3548,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 +3557,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 +3589,6 @@
         computeOpaqueFlags();
     }
 
-    private void updateUserPaddingRelative() {
-        mUserPaddingRelative = (mUserPaddingStart >= 0 || mUserPaddingEnd >= 0);
-    }
-
     /**
      * Non-public constructor for use in testing
      */
@@ -3699,6 +3596,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 +3853,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 +4228,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);
@@ -4332,8 +4313,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 +4348,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 +4368,7 @@
      */
     @ViewDebug.ExportedProperty(category = "focus")
     public boolean hasFocus() {
-        return (mPrivateFlags & FOCUSED) != 0;
+        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
     }
 
     /**
@@ -4502,11 +4483,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 +4809,7 @@
      */
     void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         Rect bounds = mAttachInfo.mTmpInvalRect;
+
         getDrawingRect(bounds);
         info.setBoundsInParent(bounds);
 
@@ -4866,10 +4850,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);
         }
@@ -4892,30 +4873,6 @@
     }
 
     /**
-     * Returns the delta between the actual and last reported window left.
-     *
-     * @hide
-     */
-    public int getActualAndReportedWindowLeftDelta() {
-        if (mAttachInfo != null) {
-            return mAttachInfo.mActualWindowLeft - mAttachInfo.mWindowLeft; 
-        }
-        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;
-    }
-
-    /**
      * Computes whether this view is visible to the user. Such a view is
      * attached, visible, all its predecessors are visible, it is not clipped
      * entirely by its predecessors, and has an alpha greater than zero.
@@ -4929,9 +4886,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 +4903,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;
     }
 
     /**
@@ -5106,7 +5080,7 @@
      */
     @ViewDebug.ExportedProperty(category = "focus")
     public boolean isFocused() {
-        return (mPrivateFlags & FOCUSED) != 0;
+        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
     }
 
     /**
@@ -5117,7 +5091,7 @@
      *         be found.
      */
     public View findFocus() {
-        return (mPrivateFlags & FOCUSED) != 0 ? this : null;
+        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
     }
 
     /**
@@ -5130,7 +5104,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 +5118,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 +5377,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 +5625,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 +5634,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 +5647,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 +5670,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 +5694,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 +5714,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 +5741,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 +5865,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 +5901,7 @@
      * @return true if the view is currently pressed, false otherwise
      */
     public boolean isPressed() {
-        return (mPrivateFlags & PRESSED) == PRESSED;
+        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
     }
 
     /**
@@ -6177,12 +6154,6 @@
         if (views == null) {
             return;
         }
-        if ((focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
-            if (isAccessibilityFocusable()) {
-                views.add(this);
-                return;
-            }
-        }
         if (!isFocusable()) {
             return;
         }
@@ -6257,7 +6228,7 @@
      * @return True if this View is accessibility focused.
      */
     boolean isAccessibilityFocused() {
-        return (mPrivateFlags2 & ACCESSIBILITY_FOCUSED) != 0;
+        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
     }
 
     /**
@@ -6282,8 +6253,8 @@
         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
             return false;
         }
-        if ((mPrivateFlags2 & ACCESSIBILITY_FOCUSED) == 0) {
-            mPrivateFlags2 |= ACCESSIBILITY_FOCUSED;
+        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
+            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
             ViewRootImpl viewRootImpl = getViewRootImpl();
             if (viewRootImpl != null) {
                 viewRootImpl.setAccessibilityFocus(this, null);
@@ -6305,8 +6276,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 +6318,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 +6325,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 +6483,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 +6502,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 +6517,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 +6534,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 +6578,7 @@
      */
     public boolean includeForAccessibility() {
         if (mAttachInfo != null) {
-            if (!mAttachInfo.mIncludeNotImportantViews) {
-                return isImportantForAccessibility();
-            }
-            return true;
+            return mAttachInfo.mIncludeNotImportantViews || isImportantForAccessibility();
         }
         return false;
     }
@@ -6748,8 +6627,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 +6642,7 @@
      * @hide
      */
     public void resetAccessibilityStateChanged() {
-        mPrivateFlags2 &= ~ACCESSIBILITY_STATE_CHANGED;
+        mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_STATE_CHANGED;
     }
 
     /**
@@ -6832,10 +6711,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;
@@ -7018,7 +6894,7 @@
      */
     public void onStartTemporaryDetach() {
         removeUnsetPressCallback();
-        mPrivateFlags |= CANCEL_NEXT_UP_EVENT;
+        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
     }
 
     /**
@@ -7337,13 +7213,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 +7259,7 @@
             if (mAttachInfo != null) {
                 initialAwakenScrollBars();
             } else {
-                mPrivateFlags |= AWAKEN_SCROLL_BARS_ON_ATTACH;
+                mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
             }
         }
     }
@@ -7484,7 +7360,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);
     }
 
@@ -7983,7 +7861,7 @@
      */
     @ViewDebug.ExportedProperty
     public boolean isHovered() {
-        return (mPrivateFlags & HOVERED) != 0;
+        return (mPrivateFlags & PFLAG_HOVERED) != 0;
     }
 
     /**
@@ -8003,14 +7881,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 +7920,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 +7939,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 +8002,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 +8027,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 +8078,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 +8089,7 @@
      */
     private void removeTapCallback() {
         if (mPendingCheckForTap != null) {
-            mPrivateFlags &= ~PREPRESSED;
+            mPrivateFlags &= ~PFLAG_PREPRESSED;
             removeCallbacks(mPendingCheckForTap);
         }
     }
@@ -8276,13 +8154,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 +8179,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 +8209,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 +8223,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 +8254,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 +8580,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 +8724,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 +8770,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 +8821,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 +8872,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 +8915,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 +8958,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 +8999,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 +9009,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 +9049,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 +9059,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 +9119,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 +9149,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 +9212,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 +9244,7 @@
      * @return The dirty state of this view.
      */
     public boolean isDirty() {
-        return (mPrivateFlags & DIRTY_MASK) != 0;
+        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
     }
 
     /**
@@ -9407,16 +9285,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 +9352,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 +9416,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 +9513,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 +9554,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 +9788,7 @@
             throw new NullPointerException("Layout parameters cannot be null");
         }
         mLayoutParams = params;
+        resolveLayoutParams();
         if (mParent instanceof ViewGroup) {
             ((ViewGroup) mParent).onSetLayoutParams(this, params);
         }
@@ -9917,6 +9796,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 +10025,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 +10068,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 +10120,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 +10169,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 +10218,7 @@
      */
     protected void invalidateParentCaches() {
         if (mParent instanceof View) {
-            ((View) mParent).mPrivateFlags |= INVALIDATED;
+            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
         }
     }
 
@@ -10362,9 +10250,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 +10264,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 +10282,7 @@
      * @hide
      */
     protected boolean hasOpaqueScrollbars() {
-        return (mPrivateFlags & OPAQUE_SCROLLBARS) == OPAQUE_SCROLLBARS;
+        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
     }
 
     /**
@@ -10923,7 +10810,7 @@
      * @hide
      */
     protected void recomputePadding() {
-        setPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
+        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
     }
 
     /**
@@ -11331,9 +11218,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 +11327,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 +11351,16 @@
         }
     }
 
+    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();
+    }
+
     /**
      * @see #onScreenStateChanged(int)
      */
@@ -11495,33 +11391,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 +11428,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 +11512,6 @@
      *
      * @see {@link #LAYOUT_DIRECTION_LTR}
      * @see {@link #LAYOUT_DIRECTION_RTL}
-     * @hide
      */
     public void onPaddingChanged(int layoutDirection) {
     }
@@ -11616,7 +11520,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 +11533,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 +11549,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 +11558,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 +11570,7 @@
      * @see #onAttachedToWindow()
      */
     protected void onDetachedFromWindow() {
-        mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
+        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
 
         removeUnsetPressCallback();
         removeLongPressCallback();
@@ -11696,6 +11596,7 @@
         resetResolvedLayoutDirection();
         resetResolvedTextAlignment();
         resetAccessibilityStateChanged();
+        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
     }
 
     /**
@@ -11737,6 +11638,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 +11664,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,7 +11693,7 @@
         if (vis != GONE) {
             onWindowVisibilityChanged(vis);
         }
-        if ((mPrivateFlags&DRAWABLE_STATE_DIRTY) != 0) {
+        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
             // If nobody has evaluated the drawable state yet, then do it now.
             refreshDrawableState();
         }
@@ -11813,9 +11723,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 +11757,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 +11793,7 @@
      * @see #setSaveEnabled(boolean)
      */
     protected Parcelable onSaveInstanceState() {
-        mPrivateFlags |= SAVE_STATE_CALLED;
+        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
         return BaseSavedState.EMPTY_STATE;
     }
 
@@ -11918,9 +11828,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 +11851,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 "
@@ -12135,13 +12045,6 @@
         }
     }
 
-    // Make sure the HardwareRenderer.validate() was invoked before calling this method
-    void flushLayer() {
-        if (mLayerType == LAYER_TYPE_HARDWARE && mHardwareLayer != null) {
-            mHardwareLayer.flush();
-        }
-    }
-
     /**
      * <p>Returns a hardware layer that can be used to draw this view again
      * without executing its draw method.</p>
@@ -12163,14 +12066,29 @@
             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) {
+                    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.isOpaque() != opaque) {
+                    mHardwareLayer.setOpaque(opaque);
+                    mLocalDirtyRect.set(0, 0, width, height);
+                }
             }
 
             // The layer is not valid if the underlying GPU resources cannot be allocated
@@ -12278,10 +12196,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 +12263,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 +12300,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 +12326,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 +12349,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 +12472,7 @@
     public void setDrawingCacheBackgroundColor(int color) {
         if (color != mDrawingCacheBackgroundColor) {
             mDrawingCacheBackgroundColor = color;
-            mPrivateFlags &= ~DRAWING_CACHE_VALID;
+            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
         }
     }
 
@@ -12602,7 +12518,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;
 
@@ -12662,7 +12578,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 +12634,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 +12671,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 +12710,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 +12897,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 +12916,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 +12978,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 +13009,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 +13026,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 +13053,23 @@
 
         // 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) == 0 &&
+                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 +13116,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 +13151,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 +13191,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 +13216,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 +13269,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 +13321,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 +13343,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 +13600,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 +13613,7 @@
             numFlags++;
         }
 
-        if ((privateFlags & SELECTED) == SELECTED) {
+        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
             if (numFlags > 0) {
                 output += " ";
             }
@@ -13699,7 +13621,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 +13629,7 @@
             numFlags++;
         }
 
-        if ((privateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
+        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
             if (numFlags > 0) {
                 output += " ";
             }
@@ -13715,7 +13637,7 @@
             numFlags++;
         }
 
-        if ((privateFlags & DRAWN) == DRAWN) {
+        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
             if (numFlags > 0) {
                 output += " ";
             }
@@ -13732,7 +13654,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 +13684,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 +13698,7 @@
                 }
             }
         }
-        mPrivateFlags &= ~FORCE_LAYOUT;
+        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
     }
 
     /**
@@ -13820,7 +13742,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 +13761,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 +13780,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 +13885,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 +13958,7 @@
      * @see #getDrawableState
      */
     public void refreshDrawableState() {
-        mPrivateFlags |= DRAWABLE_STATE_DIRTY;
+        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
         drawableStateChanged();
 
         ViewParent parent = mParent;
@@ -14040,11 +13978,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 +14013,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 +14026,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 +14038,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));
         }
@@ -14168,6 +14106,7 @@
     public void setBackgroundColor(int color) {
         if (mBackground instanceof ColorDrawable) {
             ((ColorDrawable) mBackground).setColor(color);
+            computeOpaqueFlags();
         } else {
             setBackground(new ColorDrawable(color));
         }
@@ -14215,6 +14154,8 @@
      */
     @Deprecated
     public void setBackgroundDrawable(Drawable background) {
+        computeOpaqueFlags();
+
         if (background == mBackground) {
             return;
         }
@@ -14238,14 +14179,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 +14207,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 +14279,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 +14306,7 @@
                         ? 0 : getVerticalScrollbarWidth();
                 switch (mVerticalScrollbarPosition) {
                     case SCROLLBAR_POSITION_DEFAULT:
-                        if (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
+                        if (isLayoutRtl()) {
                             left += offset;
                         } else {
                             right += offset;
@@ -14402,18 +14351,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 +14410,9 @@
      * @return the left padding in pixels
      */
     public int getPaddingLeft() {
+        if (!isPaddingResolved()) {
+            resolvePadding();
+        }
         return mPaddingLeft;
     }
 
@@ -14462,9 +14422,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 +14439,9 @@
      * @return the right padding in pixels
      */
     public int getPaddingRight() {
+        if (!isPaddingResolved()) {
+            resolvePadding();
+        }
         return mPaddingRight;
     }
 
@@ -14486,22 +14451,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 +14498,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 +14527,7 @@
      */
     @ViewDebug.ExportedProperty
     public boolean isSelected() {
-        return (mPrivateFlags & SELECTED) != 0;
+        return (mPrivateFlags & PFLAG_SELECTED) != 0;
     }
 
     /**
@@ -14576,8 +14544,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 +14569,7 @@
      */
     @ViewDebug.ExportedProperty
     public boolean isActivated() {
-        return (mPrivateFlags & ACTIVATED) != 0;
+        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
     }
 
     /**
@@ -14889,9 +14857,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 +14869,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 +15018,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 +15098,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 +15112,8 @@
      * on the parent.
      */
     public void forceLayout() {
-        mPrivateFlags |= FORCE_LAYOUT;
-        mPrivateFlags |= INVALIDATED;
+        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
+        mPrivateFlags |= PFLAG_INVALIDATED;
     }
 
     /**
@@ -15173,25 +15137,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 +15233,7 @@
         mMeasuredWidth = measuredWidth;
         mMeasuredHeight = measuredHeight;
 
-        mPrivateFlags |= MEASURED_DIMENSION_SET;
+        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
     }
 
     /**
@@ -15509,7 +15477,7 @@
      * @see #getAnimation()
      */
     protected void onAnimationStart() {
-        mPrivateFlags |= ANIMATION_STARTED;
+        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
     }
 
     /**
@@ -15521,7 +15489,7 @@
      * @see #getAnimation()
      */
     protected void onAnimationEnd() {
-        mPrivateFlags &= ~ANIMATION_STARTED;
+        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
     }
 
     /**
@@ -15558,14 +15526,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 +16010,7 @@
     }
 
     boolean canAcceptDrag() {
-        return (mPrivateFlags2 & DRAG_CAN_ACCEPT) != 0;
+        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
     }
 
     /**
@@ -16297,7 +16265,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 +16275,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 +16289,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 +16318,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 +16352,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 +16369,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 +16390,6 @@
      * resolution should override this method.
      *
      * The default implementation does nothing.
-     * @hide
      */
     public void onResolvedTextDirectionChanged() {
     }
@@ -16435,7 +16398,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 +16412,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 +16422,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 +16439,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 +16450,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 +16467,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 +16496,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 +16508,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 +16542,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 +16561,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 +16581,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 +16596,6 @@
      * resolution should override this method.
      *
      * The default implementation does nothing.
-     * @hide
      */
     public void onResolvedTextAlignmentChanged() {
     }
@@ -16650,11 +16604,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 +16615,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 +16937,7 @@
 
     private final class CheckForTap implements Runnable {
         public void run() {
-            mPrivateFlags &= ~PREPRESSED;
+            mPrivateFlags &= ~PFLAG_PREPRESSED;
             setPressed(true);
             checkForLongClick(ViewConfiguration.getTapTimeout());
         }
@@ -17315,6 +17285,8 @@
 
         final IBinder mWindowToken;
 
+        final Display mDisplay;
+
         final Callbacks mRootCallbacks;
 
         HardwareCanvas mHardwareCanvas;
@@ -17359,20 +17331,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 +17500,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 +17546,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 +17625,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));
+                }
             }
         }
 
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..3ab0e94 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);
@@ -3902,9 +3870,10 @@
         addInArray(child, index);
 
         child.mParent = this;
-        child.mPrivateFlags = (child.mPrivateFlags & ~DIRTY_MASK & ~DRAWING_CACHE_VALID) |
-                DRAWN | INVALIDATED;
-        this.mPrivateFlags |= INVALIDATED;
+        child.mPrivateFlags = (child.mPrivateFlags & ~PFLAG_DIRTY_MASK
+                        & ~PFLAG_DRAWING_CACHE_VALID)
+                | PFLAG_DRAWN | PFLAG_INVALIDATED;
+        this.mPrivateFlags |= PFLAG_INVALIDATED;
 
         if (child.hasFocus()) {
             requestChildFocus(child, child.findFocus());
@@ -4005,7 +3974,8 @@
             // If the child is drawing an animation, we want to copy this flag onto
             // ourselves and the parent to make sure the invalidate request goes
             // through
-            final boolean drawAnimation = (child.mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION;
+            final boolean drawAnimation = (child.mPrivateFlags & PFLAG_DRAW_ANIMATION)
+                    == PFLAG_DRAW_ANIMATION;
 
             // Check whether the child that requests the invalidate is fully opaque
             // Views being animated or transformed are not considered opaque because we may
@@ -4015,22 +3985,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 +4031,7 @@
 
                 if (drawAnimation) {
                     if (view != null) {
-                        view.mPrivateFlags |= DRAW_ANIMATION;
+                        view.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
                     } else if (parent instanceof ViewRootImpl) {
                         ((ViewRootImpl) parent).mIsAnimating = true;
                     }
@@ -4056,10 +4042,10 @@
                 if (view != null) {
                     if ((view.mViewFlags & FADING_EDGE_MASK) != 0 &&
                             view.getSolidColor() == 0) {
-                        opaqueFlag = DIRTY;
+                        opaqueFlag = PFLAG_DIRTY;
                     }
-                    if ((view.mPrivateFlags & DIRTY_MASK) != DIRTY) {
-                        view.mPrivateFlags = (view.mPrivateFlags & ~DIRTY_MASK) | opaqueFlag;
+                    if ((view.mPrivateFlags & PFLAG_DIRTY_MASK) != PFLAG_DIRTY) {
+                        view.mPrivateFlags = (view.mPrivateFlags & ~PFLAG_DIRTY_MASK) | opaqueFlag;
                     }
                 }
 
@@ -4090,8 +4076,8 @@
      * does not intersect with this ViewGroup's bounds.
      */
     public ViewParent invalidateChildInParent(final int[] location, final Rect dirty) {
-        if ((mPrivateFlags & DRAWN) == DRAWN ||
-                (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {
+        if ((mPrivateFlags & PFLAG_DRAWN) == PFLAG_DRAWN ||
+                (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) {
             if ((mGroupFlags & (FLAG_OPTIMIZE_INVALIDATE | FLAG_ANIMATION_DONE)) !=
                         FLAG_OPTIMIZE_INVALIDATE) {
                 dirty.offset(location[CHILD_LEFT_INDEX] - mScrollX,
@@ -4105,20 +4091,20 @@
                         dirty.setEmpty();
                     }
                 }
-                mPrivateFlags &= ~DRAWING_CACHE_VALID;
+                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
 
                 location[CHILD_LEFT_INDEX] = left;
                 location[CHILD_TOP_INDEX] = top;
 
                 if (mLayerType != LAYER_TYPE_NONE) {
-                    mPrivateFlags |= INVALIDATED;
+                    mPrivateFlags |= PFLAG_INVALIDATED;
                     mLocalDirtyRect.union(dirty);
                 }
 
                 return mParent;
 
             } else {
-                mPrivateFlags &= ~DRAWN & ~DRAWING_CACHE_VALID;
+                mPrivateFlags &= ~PFLAG_DRAWN & ~PFLAG_DRAWING_CACHE_VALID;
 
                 location[CHILD_LEFT_INDEX] = mLeft;
                 location[CHILD_TOP_INDEX] = mTop;
@@ -4130,7 +4116,7 @@
                 }
 
                 if (mLayerType != LAYER_TYPE_NONE) {
-                    mPrivateFlags |= INVALIDATED;
+                    mPrivateFlags |= PFLAG_INVALIDATED;
                     mLocalDirtyRect.union(dirty);
                 }
 
@@ -4192,8 +4178,8 @@
      * coordinate system, pruning the invalidation if the parent has already been invalidated.
      */
     private ViewParent invalidateChildInParentFast(int left, int top, final Rect dirty) {
-        if ((mPrivateFlags & DRAWN) == DRAWN ||
-                (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {
+        if ((mPrivateFlags & PFLAG_DRAWN) == PFLAG_DRAWN ||
+                (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) {
             dirty.offset(left - mScrollX, top - mScrollY);
 
             if ((mGroupFlags & FLAG_CLIP_CHILDREN) == 0 ||
@@ -4956,11 +4942,11 @@
             view.clearAnimation();
         }
 
-        if ((view.mPrivateFlags & ANIMATION_STARTED) == ANIMATION_STARTED) {
+        if ((view.mPrivateFlags & PFLAG_ANIMATION_STARTED) == PFLAG_ANIMATION_STARTED) {
             view.onAnimationEnd();
             // Should be performed by onAnimationEnd() but this avoid an infinite loop,
             // so we'd rather be safe than sorry
-            view.mPrivateFlags &= ~ANIMATION_STARTED;
+            view.mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
             // Draw one more frame after the animation is done
             mGroupFlags |= FLAG_INVALIDATE_REQUIRED;
         }
@@ -5059,7 +5045,7 @@
     @Override
     public boolean gatherTransparentRegion(Region region) {
         // If no transparent regions requested, we are always opaque.
-        final boolean meOpaque = (mPrivateFlags & View.REQUEST_TRANSPARENT_REGIONS) == 0;
+        final boolean meOpaque = (mPrivateFlags & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0;
         if (meOpaque && region == null) {
             // The caller doesn't care about the region, so stop now.
             return true;
@@ -5084,7 +5070,7 @@
      */
     public void requestTransparentRegion(View child) {
         if (child != null) {
-            child.mPrivateFlags |= View.REQUEST_TRANSPARENT_REGIONS;
+            child.mPrivateFlags |= View.PFLAG_REQUEST_TRANSPARENT_REGIONS;
             if (mParent != null) {
                 mParent.requestTransparentRegion(this);
             }
@@ -5245,9 +5231,6 @@
         }
     }
 
-    /**
-     * @hide
-     */
     @Override
     public void onResolvedLayoutDirectionReset() {
         // Take care of resetting the children resolution too
@@ -5260,9 +5243,6 @@
         }
     }
 
-    /**
-     * @hide
-     */
     @Override
     public void onResolvedTextDirectionReset() {
         // Take care of resetting the children resolution too
@@ -5275,9 +5255,6 @@
         }
     }
 
-    /**
-     * @hide
-     */
     @Override
     public void onResolvedTextAlignmentReset() {
         // Take care of resetting the children resolution too
@@ -5448,15 +5425,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 +5449,6 @@
          *
          * {@link View#LAYOUT_DIRECTION_LTR}
          * {@link View#LAYOUT_DIRECTION_RTL}
-         * @hide
          */
         public void onResolveLayoutDirection(int layoutDirection) {
         }
@@ -5560,7 +5540,6 @@
          * 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;
@@ -5569,15 +5548,23 @@
          * 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;
 
         /**
          * 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 +5604,9 @@
                         R.styleable.ViewGroup_MarginLayout_layout_marginEnd, DEFAULT_RELATIVE);
             }
 
+            initialLeftMargin = leftMargin;
+            initialRightMargin = rightMargin;
+
             a.recycle();
         }
 
@@ -5642,6 +5632,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 +5666,8 @@
             topMargin = top;
             rightMargin = right;
             bottomMargin = bottom;
+            initialLeftMargin = left;
+            initialRightMargin = right;
         }
 
         /**
@@ -5688,6 +5685,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 +5693,8 @@
             topMargin = top;
             endMargin = end;
             bottomMargin = bottom;
+            initialLeftMargin = 0;
+            initialRightMargin = 0;
         }
 
         /**
@@ -5703,10 +5703,16 @@
          * @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;
+            }
         }
 
         /**
@@ -5715,10 +5721,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 +5739,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..ffd495e 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();
@@ -1127,6 +1107,7 @@
         if (host == null || !mAdded)
             return;
 
+        mIsInTraversal = true;
         mWillDrawSoon = true;
         boolean windowSizeMayChange = false;
         boolean newSurface = false;
@@ -1171,9 +1152,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 +1238,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 +1289,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;
             }
@@ -1504,11 +1483,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 +1517,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 +1608,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 +1660,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 +1695,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 +1712,7 @@
                     mPreviousTransparentRegion.set(mTransparentRegion);
                     // reconfigure window manager
                     try {
-                        sWindowSession.setTransparentRegion(mWindow, mTransparentRegion);
+                        mWindowSession.setTransparentRegion(mWindow, mTransparentRegion);
                     } catch (RemoteException e) {
                     }
                 }
@@ -1757,7 +1761,7 @@
                 }
 
                 try {
-                    sWindowSession.setInsets(mWindow, insets.mTouchableInsets,
+                    mWindowSession.setInsets(mWindow, insets.mTouchableInsets,
                             contentInsets, visibleInsets, touchableRegion);
                 } catch (RemoteException e) {
                 }
@@ -1782,7 +1786,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 +1817,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 +1846,8 @@
                 mPendingTransitions.clear();
             }
         }
+
+        mIsInTraversal = false;
     }
 
     private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {
@@ -1875,7 +1881,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 +2049,7 @@
                 }
             }
             try {
-                sWindowSession.finishDrawing(mWindow);
+                mWindowSession.finishDrawing(mWindow);
             } catch (RemoteException e) {
             }
         }
@@ -2199,7 +2205,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 +2244,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 +2257,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 +2286,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 +2634,7 @@
             mInputEventReceiver = null;
         }
         try {
-            sWindowSession.remove(mWindow);
+            mWindowSession.remove(mWindow);
         } catch (RemoteException e) {
         }
         
@@ -2660,7 +2657,7 @@
         CompatibilityInfo ci = mCompatibilityInfo.getIfNeeded();
         if (ci != null) {
             config = new Configuration(config);
-            ci.applyToConfiguration(config);
+            ci.applyToConfiguration(mNoncompatDensity, config);
         }
 
         synchronized (sConfigCallbacks) {
@@ -2671,7 +2668,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 +2724,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 +2776,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 +2806,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 +2838,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 +2875,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());
                                     }
@@ -3003,7 +3024,7 @@
 
         // tell the window manager
         try {
-            sWindowSession.setInTouchMode(inTouchMode);
+            mWindowSession.setInTouchMode(inTouchMode);
         } catch (RemoteException e) {
             throw new RuntimeException(e);
         }
@@ -3717,10 +3738,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 +3753,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 +3855,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 +3916,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 +3962,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 +3997,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 +4057,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);
     }
 
@@ -4664,41 +4698,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 +4819,7 @@
                 boolean sync) {
             if (sync) {
                 try {
-                    sWindowSession.wallpaperOffsetsComplete(asBinder());
+                    mWindowSession.wallpaperOffsetsComplete(asBinder());
                 } catch (RemoteException e) {
                 }
             }
@@ -4788,7 +4829,7 @@
                 int z, Bundle extras, boolean sync) {
             if (sync) {
                 try {
-                    sWindowSession.wallpaperCommandComplete(asBinder(), null);
+                    mWindowSession.wallpaperCommandComplete(asBinder(), null);
                 } catch (RemoteException e) {
                 }
             }
@@ -5186,15 +5227,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 +5266,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 +5285,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 +5303,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 +5322,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..4d4e985c 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -104,6 +104,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 */
@@ -282,6 +285,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();
     }
 
@@ -790,7 +800,16 @@
      * 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 {
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/WindowManager.java b/core/java/android/view/WindowManager.java
index d94275b..f30952c 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -64,15 +64,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 +154,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 +163,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 +176,11 @@
             @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")
         })
         public int type;
     
@@ -435,6 +430,18 @@
         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;
+
+        /**
          * End of types of system windows.
          */
         public static final int LAST_SYSTEM_WINDOW      = 2999;
@@ -530,7 +537,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 +727,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..aa9179f 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -16,36 +16,20 @@
 
 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);
-    }
-}
+import android.content.Context;
+import android.hardware.display.DisplayManager;
 
 /**
- * Low-level communication with the global system window manager.  It implements
- * the ViewManager interface, allowing you to add any View subclass as a
- * top-level window on the screen. Additional window manager specific layout
- * parameters are defined for control over how windows are displayed.
- * It also 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 +37,59 @@
  * 
  * <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 Context mContext;
+    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(Context context, int displayId) {
+        DisplayManager dm = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
+        mContext = context;
+        mDisplay = dm.getDisplay(displayId);
+        mParentWindow = null;
     }
 
-    public static WindowManagerImpl getDefault() {
-        return sWindowManager;
+    private WindowManagerImpl(Context context, Display display, Window parentWindow) {
+        mContext = context;
+        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(mContext, 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));
-    }
-
+    @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..7173d1d 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,11 +114,11 @@
     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)
@@ -391,8 +390,8 @@
          */
         public void switchKeyboardLayout(int deviceId, int direction);
 
-        public void shutdown();
-        public void rebootSafeMode();
+        public void shutdown(boolean confirm);
+        public void rebootSafeMode(boolean confirm);
     }
 
     /**
@@ -473,26 +472,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 +550,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 +662,7 @@
      * @param win The window being added.
      * @param attrs The window's LayoutParams. 
      *  
-     * @return {@link WindowManagerImpl#ADD_OKAY} if the add can proceed, else an 
+     * @return {@link WindowManagerGlobal#ADD_OKAY} if the add can proceed, else an
      *         error code to abort the add.
      */
     public int prepareAddWindowLw(WindowState win,
@@ -1086,31 +1090,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
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 3ad3a55..768744b 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -382,10 +382,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 +428,6 @@
         final int rootAccessibilityViewId =
             (root != null) ? root.getAccessibilityViewId() : UNDEFINED;
         mSourceNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
-        if (root != null) {
-            mActualAndReportedWindowLeftDelta = root.getActualAndReportedWindowLeftDelta();
-            mActualAndReportedWindowTopDelta = root.getActualAndReportedWindowTopDelta();
-        }
     }
 
     /**
@@ -833,7 +825,6 @@
     public void setBoundsInScreen(Rect bounds) {
         enforceNotSealed();
         mBoundsInScreen.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
-        mBoundsInScreen.offset(mActualAndReportedWindowLeftDelta, mActualAndReportedWindowTopDelta);
     }
 
     /**
@@ -1343,12 +1334,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);
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/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index d2cc2d8..e754adc 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,160 @@
      * @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) {
+            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) {
-                }
-                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);
-                try {
-                    callback.finishedEvent(seq, false);
-                } catch (RemoteException ex) {
+                    Log.w(TAG, "IME died: " + mCurId + " dropping trackball: " + 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 +1909,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/webkit/AccessibilityInjector.java b/core/java/android/webkit/AccessibilityInjector.java
index 7dfb5bb..fd73fda 100644
--- a/core/java/android/webkit/AccessibilityInjector.java
+++ b/core/java/android/webkit/AccessibilityInjector.java
@@ -279,6 +279,7 @@
         }
 
         if (!shouldInjectJavaScript(url)) {
+            mAccessibilityScriptInjected = false;
             toggleFallbackAccessibilityInjector(true);
             return;
         }
@@ -292,6 +293,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
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..1b23b18 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;
@@ -242,6 +243,7 @@
         mSettings = settings;
         mContext = context;
         mCallbackProxy = proxy;
+        mDatabase = WebViewDatabaseClassic.getInstance(appContext);
         mWebViewCore = w;
 
         mSearchBox = new SearchBoxImpl(mWebViewCore, mCallbackProxy);
@@ -424,8 +426,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 +498,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]);
                         }
@@ -800,10 +800,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 +811,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 +1137,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 +1157,7 @@
             mKeyStoreHandler = new KeyStoreHandler(mimeType);
         } else {
             mCallbackProxy.onDownloadStart(url, userAgent,
-                contentDisposition, mimeType, contentLength);
+                contentDisposition, mimeType, referer, contentLength);
         }
     }
 
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index 2d9f60d..b47cba8 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,7 +117,6 @@
     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;
@@ -188,7 +187,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 +248,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 +402,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 +452,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 +742,14 @@
                                                 res.cancel();
                                             }
                                         })
+                                .setOnCancelListener(
+                                        new DialogInterface.OnCancelListener() {
+                                            @Override
+                                            public void onCancel(
+                                                    DialogInterface dialog) {
+                                                res.cancel();
+                                            }
+                                        })
                                 .show();
                     }
                     receiver.setReady();
@@ -857,11 +871,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();
 
@@ -1081,7 +1090,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 +1101,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 +1185,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 +1199,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 +1312,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 +1327,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 +1619,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.
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/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..76ec374 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,7 +90,7 @@
     // ratio is correct.
     private int mVideoWidth;
     private int mVideoHeight;
-
+    private boolean mPlayingWhenDestroyed = false;
     SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback()
     {
         public void surfaceChanged(SurfaceHolder holder, int format,
@@ -101,12 +116,11 @@
 
         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 +208,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,6 +221,16 @@
             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);
+
     }
 
     public boolean fullScreenExited() {
@@ -232,7 +244,6 @@
                 // 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 +253,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;
             }
         };
 
diff --git a/core/java/android/webkit/HTML5VideoInline.java b/core/java/android/webkit/HTML5VideoInline.java
index 2c7ea5d..96240ef 100644
--- a/core/java/android/webkit/HTML5VideoInline.java
+++ b/core/java/android/webkit/HTML5VideoInline.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;
 
@@ -34,8 +49,8 @@
         }
     }
 
-    HTML5VideoInline(int videoLayerId, int position) {
-        init(videoLayerId, position, false);
+    HTML5VideoInline(int videoLayerId, int position, boolean skipPrepare) {
+        init(videoLayerId, position, skipPrepare);
     }
 
     @Override
@@ -84,7 +99,7 @@
         return mSurfaceTexture;
     }
 
-    public boolean surfaceTextureDeleted() {
+    public static boolean surfaceTextureDeleted() {
         return (mSurfaceTexture == null);
     }
 
@@ -110,7 +125,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..8f9f8eb 100644
--- a/core/java/android/webkit/HTML5VideoView.java
+++ b/core/java/android/webkit/HTML5VideoView.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;
 
@@ -35,6 +50,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 +142,7 @@
     }
 
     public void reset() {
-        if (mCurrentState != STATE_RESETTED) {
+        if (mCurrentState < STATE_RESETTED) {
             mPlayer.reset();
         }
         mCurrentState = STATE_RESETTED;
@@ -138,6 +154,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 +365,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..701ef35 100644
--- a/core/java/android/webkit/HTML5VideoViewProxy.java
+++ b/core/java/android/webkit/HTML5VideoViewProxy.java
@@ -59,6 +59,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;
@@ -105,12 +106,11 @@
         // When we found the Video layer, then we set the Surface Texture to it.
         // Otherwise, we may want to delete the Surface Texture to save memory.
         public static void setBaseLayer(int layer) {
+            mBaseLayer = layer;
             // 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 +126,6 @@
                     if (playerState >= HTML5VideoView.STATE_PREPARED
                             && !foundInTree) {
                         mHTML5VideoView.pauseAndDispatch(mCurrentProxy);
-                        mHTML5VideoView.deleteSurfaceTexture();
                     }
                 }
             }
@@ -136,9 +135,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 +213,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 +234,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 +287,6 @@
             if (!mHTML5VideoView.isFullScreenMode()) {
                 mHTML5VideoView.start();
             }
-            if (mBaseLayer != 0) {
-                setBaseLayer(mBaseLayer);
-            }
         }
 
         public static void end() {
@@ -333,8 +339,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 +376,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;
@@ -613,7 +629,7 @@
                         nativeOnTimeupdate(msg.arg1, mNativePointer);
                         break;
                     case STOPFULLSCREEN:
-                        nativeOnStopFullscreen(mNativePointer);
+                        nativeOnStopFullscreen(msg.arg1, mNativePointer);
                         break;
                     case RESTORESTATE:
                         nativeOnRestoreState(mNativePointer);
@@ -664,6 +680,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 +779,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,
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/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/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..cc9afe0 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() {
     }
 
     /**
@@ -100,7 +41,7 @@
      */
     @Deprecated
     public int getId() {
-        return mId;
+        throw new MustOverrideException();
     }
 
     /**
@@ -112,8 +53,7 @@
      * to synchronize this method.
      */
     public String getUrl() {
-        if (mNativeBridge == 0) return null;
-        return nativeGetUrl(mNativeBridge);
+        throw new MustOverrideException();
     }
 
     /**
@@ -123,8 +63,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 +73,7 @@
      * to synchronize this method.
      */
     public String getTitle() {
-        if (mNativeBridge == 0) return null;
-        return nativeGetTitle(mNativeBridge);
+        throw new MustOverrideException();
     }
 
     /**
@@ -145,119 +83,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..e8ff01f 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,33 @@
     }
 
     /**
-     * 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}.
      */
     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,7 +155,8 @@
     }
 
     /**
-     * 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.
      */
@@ -165,6 +168,8 @@
     /**
      * Gets whether dumping the navigation cache is enabled.
      *
+     * @return whether dumping the navigation cache is enabled
+     * @see #setNavDump
      * @deprecated This method is now obsolete.
      */
     @Deprecated
@@ -196,6 +201,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 +310,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();
@@ -344,38 +373,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 +420,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 +486,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 +494,9 @@
 
     /**
      * Gets whether light touches are enabled.
+     *
+     * @return whether light touches are enabled
+     * @see #setLightTouchEnabled
      */
     public boolean getLightTouchEnabled() {
         throw new MustOverrideException();
@@ -474,11 +526,16 @@
     }
 
     /**
-     * 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.
      */
     @Deprecated
     public synchronized void setUserAgent(int ua) {
@@ -486,12 +543,17 @@
     }
 
     /**
-     * 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.
      */
     @Deprecated
     public synchronized int getUserAgent() {
@@ -499,7 +561,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 +573,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 +602,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 +613,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 +659,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 +671,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 +947,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 +962,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 +986,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 +1014,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 +1026,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 +1053,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 +1064,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 +1076,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 +1095,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 +1147,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 +1156,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 +1220,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 +1229,30 @@
 
     /**
      * 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#setUserAgent(int)} or
+     * {@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 +1262,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 +1273,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..82635d7 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);
@@ -585,12 +579,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 +596,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 +615,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();
@@ -723,9 +730,9 @@
     }
 
     /**
-     * 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
@@ -791,11 +798,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 +995,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();
@@ -1004,6 +1018,7 @@
      *
      * @return the current scale
      */
+    @ViewDebug.ExportedProperty(category = "webview")
     public float getScale() {
         checkThread();
         return mProvider.getScale();
@@ -1094,6 +1109,7 @@
      *
      * @return the URL for the current page
      */
+    @ViewDebug.ExportedProperty(category = "webview")
     public String getUrl() {
         checkThread();
         return mProvider.getUrl();
@@ -1108,6 +1124,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 +1136,7 @@
      *
      * @return the title for the current page
      */
+    @ViewDebug.ExportedProperty(category = "webview")
     public String getTitle() {
         checkThread();
         return mProvider.getTitle();
@@ -1161,6 +1179,7 @@
      *
      * @return the height of the HTML content
      */
+    @ViewDebug.ExportedProperty(category = "webview")
     public int getContentHeight() {
         checkThread();
         return mProvider.getContentHeight();
@@ -1172,6 +1191,7 @@
      * @return the width of the HTML content
      * @hide
      */
+    @ViewDebug.ExportedProperty(category = "webview")
     public int getContentWidth() {
         return mProvider.getContentWidth();
     }
@@ -1246,8 +1266,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();
@@ -1381,7 +1403,6 @@
      * @return the address, or if no address is found, null
      */
     public static String findAddress(String addr) {
-        checkThread();
         return getFactory().getStatics().findAddress(addr);
     }
 
@@ -1543,7 +1564,6 @@
     @Deprecated
     public void emulateShiftHeld() {
         checkThread();
-        mProvider.emulateShiftHeld();
     }
 
     /**
@@ -1649,7 +1669,24 @@
     @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 34c08ef..591b87f 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;
@@ -117,6 +118,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,9 +132,11 @@
 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.concurrent.CountDownLatch;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -275,7 +280,6 @@
             super.setComposingText(limitedText, newCursorPosition);
             updateSelection();
             if (limitedText != text) {
-                restartInput();
                 int lastCaret = start + limitedText.length();
                 finishComposingText();
                 setSelection(lastCaret, lastCaret);
@@ -376,28 +380,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 +407,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 +678,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 +743,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 +950,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 +1037,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 +1052,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 +1313,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) {
@@ -1368,7 +1374,7 @@
         if (action == MotionEvent.ACTION_POINTER_DOWN) {
             cancelTouch();
             action = MotionEvent.ACTION_DOWN;
-        } else if (action == MotionEvent.ACTION_POINTER_UP && ev.getPointerCount() >= 2) {
+        } else if (action == MotionEvent.ACTION_POINTER_UP) {
             // set mLastTouchX/Y to the remaining points for multi-touch.
             mLastTouchX = Math.round(x);
             mLastTouchY = Math.round(y);
@@ -1631,6 +1637,12 @@
         mZoomManager.updateMultiTouchSupport(context);
     }
 
+    void updateJavaScriptEnabled(boolean enabled) {
+        if (isAccessibilityInjectionEnabled()) {
+            getAccessibilityInjector().updateJavaScriptEnabled(enabled);
+        }
+    }
+
     private void init() {
         OnTrimMemoryListener.init(mContext);
         mWebView.setWillNotDraw(false);
@@ -1744,8 +1756,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() {
@@ -2208,7 +2233,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
@@ -2222,7 +2247,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
@@ -2421,7 +2446,7 @@
      */
     @Override
     public WebBackForwardList restoreState(Bundle inState) {
-        WebBackForwardList returnList = null;
+        WebBackForwardListClassic returnList = null;
         if (inState == null) {
             return returnList;
         }
@@ -2429,7 +2454,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
@@ -2450,7 +2475,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.
@@ -2623,7 +2648,7 @@
      */
     @Override
     public boolean canGoBack() {
-        WebBackForwardList l = mCallbackProxy.getBackForwardList();
+        WebBackForwardListClassic l = mCallbackProxy.getBackForwardList();
         synchronized (l) {
             if (l.getClearPending()) {
                 return false;
@@ -2646,7 +2671,7 @@
      */
     @Override
     public boolean canGoForward() {
-        WebBackForwardList l = mCallbackProxy.getBackForwardList();
+        WebBackForwardListClassic l = mCallbackProxy.getBackForwardList();
         synchronized (l) {
             if (l.getClearPending()) {
                 return false;
@@ -2669,7 +2694,7 @@
      */
     @Override
     public boolean canGoBackOrForward(int steps) {
-        WebBackForwardList l = mCallbackProxy.getBackForwardList();
+        WebBackForwardListClassic l = mCallbackProxy.getBackForwardList();
         synchronized (l) {
             if (l.getClearPending()) {
                 return false;
@@ -3317,6 +3342,7 @@
         }
         if (mTouchMode == TOUCH_DRAG_LAYER_MODE) {
             scrollLayerTo(scrollX, scrollY);
+            animateHandles();
             return;
         }
         mInOverScrollMode = false;
@@ -3337,6 +3363,8 @@
 
         mWebViewPrivate.super_scrollTo(scrollX, scrollY);
 
+        animateHandles();
+
         if (mOverScrollGlow != null) {
             mOverScrollGlow.pullGlow(getScrollX(), getScrollY(), oldX, oldY, maxX, maxY);
         }
@@ -3383,7 +3411,7 @@
      */
     @Override
     public String getTouchIconUrl() {
-        WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
+        WebHistoryItemClassic h = mCallbackProxy.getBackForwardList().getCurrentItem();
         return h != null ? h.getTouchIconUrl() : null;
     }
 
@@ -3547,7 +3575,7 @@
      * See {@link WebView#copyBackForwardList()}
      */
     @Override
-    public WebBackForwardList copyBackForwardList() {
+    public WebBackForwardListClassic copyBackForwardList() {
         return mCallbackProxy.getBackForwardList().clone();
     }
 
@@ -3555,7 +3583,8 @@
      * See {@link WebView#setFindListener(WebView.FindListener)}.
      * @hide
      */
-     public void setFindListener(WebView.FindListener listener) {
+     @Override
+    public void setFindListener(WebView.FindListener listener) {
          mFindListener = listener;
      }
 
@@ -3578,6 +3607,7 @@
         return findAllBody(find, false);
     }
 
+    @Override
     public void findAllAsync(String find) {
         findAllBody(find, true);
     }
@@ -3616,6 +3646,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) {
@@ -3831,17 +3862,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) {
@@ -3936,7 +3964,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);
         }
 
@@ -3951,7 +3979,7 @@
     /* package */ void onPageFinished(String url) {
         mZoomManager.onPageFinished(url);
 
-        if (isAccessibilityEnabled()) {
+        if (isAccessibilityInjectionEnabled()) {
             getAccessibilityInjector().onPageFinished(url);
         }
     }
@@ -4457,9 +4485,6 @@
     }
 
     private void onZoomAnimationStart() {
-        if (!mSelectingText && mHandleAlpha.getAlpha() > 0) {
-            mHandleAlphaAnimator.end();
-        }
     }
 
     private void onZoomAnimationEnd() {
@@ -4492,34 +4517,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() {
@@ -4530,66 +4584,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
@@ -4824,6 +4899,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
@@ -4908,7 +5020,7 @@
         }
 
         // See if the accessibility injector needs to handle this event.
-        if (isAccessibilityEnabled()
+        if (isAccessibilityInjectionEnabled()
                 && getAccessibilityInjector().handleKeyEventIfNecessary(event)) {
             return true;
         }
@@ -5015,7 +5127,7 @@
         }
 
         // See if the accessibility injector needs to handle this event.
-        if (isAccessibilityEnabled()
+        if (isAccessibilityInjectionEnabled()
                 && getAccessibilityInjector().handleKeyEventIfNecessary(event)) {
             return true;
         }
@@ -5056,8 +5168,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));
@@ -5107,12 +5219,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);
     }
 
@@ -5123,50 +5235,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() {
@@ -5181,18 +5255,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() {
@@ -5204,14 +5271,6 @@
     }
 
     /**
-     * See {@link WebView#emulateShiftHeld()}
-     */
-    @Override
-    @Deprecated
-    public void emulateShiftHeld() {
-    }
-
-    /**
      * Select all of the text in this WebView.
      *
      * This is an implementation detail.
@@ -5319,7 +5378,7 @@
     public void onAttachedToWindow() {
         if (mWebView.hasWindowFocus()) setActive(true);
 
-        if (isAccessibilityEnabled()) {
+        if (isAccessibilityInjectionEnabled()) {
             getAccessibilityInjector().addAccessibilityApisIfNecessary();
         }
 
@@ -5332,7 +5391,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
@@ -5555,21 +5614,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;
             }
         }
@@ -5813,28 +5872,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();
                         }
@@ -5879,9 +5929,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);
@@ -6018,12 +6068,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) {
@@ -6130,6 +6183,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() -
@@ -6138,10 +6195,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);
@@ -6157,10 +6241,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) {
@@ -6170,24 +6254,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);
                 }
             }
         }
@@ -6243,10 +6330,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
@@ -6347,10 +6434,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);
     }
@@ -6379,9 +6466,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;
                     }
                 }
             }
@@ -6413,9 +6504,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
@@ -6425,6 +6519,7 @@
     private DrawData mDelaySetPicture;
     private DrawData mLoadedPicture;
 
+    @Override
     public void setMapTrackballToArrowKeys(boolean setMap) {
         mMapTrackballToArrowKeys = setMap;
     }
@@ -6651,6 +6746,7 @@
         }
     }
 
+    @Override
     public void flingScroll(int vx, int vy) {
         mScroller.fling(getScrollX(), getScrollY(), vx, vy, 0, computeMaxScrollX(), 0,
                 computeMaxScrollY(), mOverflingDistance, mOverflingDistance);
@@ -6903,6 +6999,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;
@@ -7212,11 +7310,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;
@@ -7302,15 +7396,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();
@@ -7390,7 +7475,7 @@
                     break;
 
                 case SELECTION_STRING_CHANGED:
-                    if (isAccessibilityEnabled()) {
+                    if (isAccessibilityInjectionEnabled()) {
                         getAccessibilityInjector()
                                 .handleSelectionChangedIfNecessary((String) msg.obj);
                     }
@@ -7449,7 +7534,7 @@
                         mEditTextLayerId = initData.mNodeLayerId;
                         nativeMapLayerRect(mNativeClass, mEditTextLayerId,
                                 mEditTextContentBounds);
-                        mEditTextContent.set(initData.mContentRect);
+                        mEditTextContent.set(initData.mClientRect);
                         relocateAutoCompletePopup();
                     }
                     break;
@@ -7530,6 +7615,10 @@
                     scrollEditWithCursor();
                     break;
 
+                case SCROLL_HANDLE_INTO_VIEW:
+                    scrollDraggedSelectionHandleIntoView();
+                    break;
+
                 default:
                     super.handleMessage(msg);
                     break;
@@ -7565,8 +7654,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;
         }
@@ -7854,7 +7943,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
@@ -7913,8 +8004,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)) {
@@ -7923,11 +8016,10 @@
             } else {
                 if (!mSelectingText) {
                     setupWebkitSelect();
-                } else if (!mSelectionStarted) {
-                    syncSelectionCursors();
                 } else {
-                    adjustSelectionCursors();
+                    syncSelectionCursors();
                 }
+                animateHandles();
                 if (mIsCaretSelection) {
                     resetCaretTimer();
                 }
@@ -7943,8 +8035,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() {
@@ -8389,14 +8483,6 @@
     }
 
     /**
-     * See {@link WebView#debugDump()}
-     */
-    @Override
-    @Deprecated
-    public void debugDump() {
-    }
-
-    /**
      * Enable the communication b/t the webView and VideoViewProxy
      *
      * only used by the Browser
@@ -8530,6 +8616,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);
@@ -8550,6 +8684,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();
@@ -8593,4 +8729,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..59036e7 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);
@@ -960,7 +945,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 +1184,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 +1292,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: {
@@ -1660,6 +1641,10 @@
                                     (Set<String>) msg.obj);
                             break;
 
+                        case SET_USE_MOCK_GEOLOCATION:
+                            setUseMockGeolocation();
+                            break;
+
                         case SET_USE_MOCK_DEVICE_ORIENTATION:
                             setUseMockDeviceOrientation();
                             break;
@@ -1708,13 +1693,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 +2120,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 +2173,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 +2197,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 +2235,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 +2317,6 @@
                     Log.w(LOGTAG, "Cannot pauseUpdatePicture, core destroyed or not initialized!");
                     return;
                 }
-                core.nativeSetIsPaused(core.mNativeClass, true);
                 core.mDrawIsPaused = true;
             }
         }
@@ -2348,7 +2334,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 +2348,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 +2772,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 +2837,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 +3045,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 +3087,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 +3132,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..1987f53 100644
--- a/core/java/android/webkit/WebViewDatabase.java
+++ b/core/java/android/webkit/WebViewDatabase.java
@@ -23,7 +23,7 @@
  * 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>
@@ -43,50 +43,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/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/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 30dd17d..41e8452 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -904,8 +904,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 +1076,7 @@
             mPopup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NEEDED);
             mPopup.setListItemExpandMax(EXPAND_MAX);
         }
+        mPopup.setLayoutDirection(getResolvedLayoutDirection());
         mPopup.show();
         mPopup.getListView().setOverScrollMode(View.OVER_SCROLL_ALWAYS);
     }
diff --git a/core/java/android/widget/CheckBox.java b/core/java/android/widget/CheckBox.java
index f1804f8..41ab5f2 100644
--- a/core/java/android/widget/CheckBox.java
+++ b/core/java/android/widget/CheckBox.java
@@ -20,6 +20,7 @@
 import android.util.AttributeSet;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.util.ValueModel;
 
 
 /**
@@ -55,7 +56,9 @@
  * {@link android.R.styleable#View View Attributes}
  * </p>
  */
-public class CheckBox extends CompoundButton {
+public class CheckBox extends CompoundButton implements ValueEditor<Boolean> {
+    private ValueModel<Boolean> mValueModel = ValueModel.EMPTY;
+
     public CheckBox(Context context) {
         this(context, null);
     }
@@ -79,4 +82,22 @@
         super.onInitializeAccessibilityNodeInfo(info);
         info.setClassName(CheckBox.class.getName());
     }
+
+    @Override
+    public ValueModel<Boolean> getValueModel() {
+        return mValueModel;
+    }
+
+    @Override
+    public void setValueModel(ValueModel<Boolean> valueModel) {
+        mValueModel = valueModel;
+        setChecked(mValueModel.get());
+    }
+
+    @Override
+    public boolean performClick() {
+        boolean handled = super.performClick();
+        mValueModel.set(isChecked());
+        return handled;
+    }
 }
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/EditText.java b/core/java/android/widget/EditText.java
index 57e51c2..ec81214 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.content.Context;
+import android.graphics.Rect;
 import android.text.Editable;
 import android.text.Selection;
 import android.text.Spannable;
@@ -24,6 +25,7 @@
 import android.text.method.ArrowKeyMovementMethod;
 import android.text.method.MovementMethod;
 import android.util.AttributeSet;
+import android.util.ValueModel;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 
@@ -47,7 +49,9 @@
  * {@link android.R.styleable#TextView TextView Attributes},
  * {@link android.R.styleable#View View Attributes}
  */
-public class EditText extends TextView {
+public class EditText extends TextView implements ValueEditor<CharSequence> {
+    private ValueModel<CharSequence> mValueModel = ValueModel.EMPTY;
+
     public EditText(Context context) {
         this(context, null);
     }
@@ -128,4 +132,21 @@
         super.onInitializeAccessibilityNodeInfo(info);
         info.setClassName(EditText.class.getName());
     }
+
+    @Override
+    public ValueModel<CharSequence> getValueModel() {
+        return mValueModel;
+    }
+
+    @Override
+    public void setValueModel(ValueModel<CharSequence> valueModel) {
+        mValueModel = valueModel;
+        setText(mValueModel.get());
+    }
+
+    @Override
+    void sendAfterTextChanged(Editable text) {
+        super.sendAfterTextChanged(text);
+        mValueModel.set(text);
+    }
 }
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index c29dd58..7f9dab9 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();
         }
     }
 
@@ -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/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index a458f57..eabcb80 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: {
@@ -2506,14 +2421,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..860e583 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) {
+            mIndeterminateDrawable.setLayoutDirection(getLayoutDirection());
+        }
         if (mIndeterminate) {
             mCurrentDrawable = d;
             postInvalidate();
@@ -517,6 +520,7 @@
 
         if (d != null) {
             d.setCallback(this);
+            d.setLayoutDirection(getLayoutDirection());
 
             // Make sure the ProgressBar is always tall enough
             int drawableHeight = d.getMinimumHeight();
@@ -975,24 +979,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..dcf90e9 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -61,9 +61,9 @@
  * the content of the inflated hierarchy.
  */
 public class RemoteViews implements Parcelable, Filter {
-    
+
     private static final String LOG_TAG = "RemoteViews";
-    
+
     /**
      * The intent extra that contains the appWidgetId.
      * @hide
@@ -71,11 +71,11 @@
     static final String EXTRA_REMOTEADAPTER_APPWIDGET_ID = "remoteAdapterAppWidgetId";
 
     /**
-     * The package name of the package containing the layout 
+     * The package name of the package containing the layout
      * resource. (Added to the parcel)
      */
     private final String mPackage;
-    
+
     /**
      * The resource ID of the layout file. (Added to the parcel)
      */
@@ -86,7 +86,7 @@
      * inflated
      */
     private ArrayList<Action> mActions;
-    
+
     /**
      * A class to keep track of memory usage by this RemoteViews
      */
@@ -522,13 +522,13 @@
                                     .getCompatibilityInfo().applicationScale;
                             final int[] pos = new int[2];
                             v.getLocationOnScreen(pos);
-    
+
                             final Rect rect = new Rect();
                             rect.left = (int) (pos[0] * appScale + 0.5f);
                             rect.top = (int) (pos[1] * appScale + 0.5f);
                             rect.right = (int) ((pos[0] + v.getWidth()) * appScale + 0.5f);
                             rect.bottom = (int) ((pos[1] + v.getHeight()) * appScale + 0.5f);
-    
+
                             final Intent intent = new Intent();
                             intent.setSourceBounds(rect);
                             handler.onClickHandler(v, pendingIntent, intent);
@@ -567,7 +567,7 @@
             this.filterMode = mode;
             this.level = level;
         }
-        
+
         public SetDrawableParameters(Parcel parcel) {
             viewId = parcel.readInt();
             targetBackground = parcel.readInt() != 0;
@@ -581,7 +581,7 @@
             }
             level = parcel.readInt();
         }
-        
+
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeInt(TAG);
             dest.writeInt(viewId);
@@ -596,12 +596,12 @@
             }
             dest.writeInt(level);
         }
-        
+
         @Override
         public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
             final View target = root.findViewById(viewId);
             if (target == null) return;
-            
+
             // Pick the correct drawable to modify for this view
             Drawable targetDrawable = null;
             if (targetBackground) {
@@ -610,7 +610,7 @@
                 ImageView imageView = (ImageView) target;
                 targetDrawable = imageView.getDrawable();
             }
-            
+
             if (targetDrawable != null) {
                 // Perform modifications only if values are set correctly
                 if (alpha != -1) {
@@ -634,7 +634,7 @@
 
         public final static int TAG = 3;
     }
-    
+
     private class ReflectionActionWithoutParams extends Action {
         int viewId;
         String methodName;
@@ -938,7 +938,7 @@
                     out.writeString((String)this.value);
                     break;
                 case CHAR_SEQUENCE:
-                    TextUtils.writeToParcel((CharSequence)this.value, out, flags);   
+                    TextUtils.writeToParcel((CharSequence)this.value, out, flags);
                     break;
                 case URI:
                     out.writeInt(this.value != null ? 1 : 0);
@@ -1314,7 +1314,7 @@
     /**
      * Create a new RemoteViews object that will display the views contained
      * in the specified layout file.
-     * 
+     *
      * @param packageName Name of the package that contains the layout resource
      * @param layoutId The id of the layout resource
      */
@@ -1364,7 +1364,7 @@
 
     /**
      * Reads a RemoteViews object from a parcel.
-     * 
+     *
      * @param parcel
      */
     public RemoteViews(Parcel parcel) {
@@ -1547,7 +1547,7 @@
 
     /**
      * Add an action to be executed on the remote side when apply is called.
-     * 
+     *
      * @param a The action to add
      */
     private void addAction(Action a) {
@@ -1619,7 +1619,7 @@
 
     /**
      * Equivalent to calling View.setVisibility
-     * 
+     *
      * @param viewId The id of the view whose visibility should change
      * @param visibility The new visibility for the view
      */
@@ -1629,7 +1629,7 @@
 
     /**
      * Equivalent to calling TextView.setText
-     * 
+     *
      * @param viewId The id of the view whose text should change
      * @param text The new text for the view
      */
@@ -1639,7 +1639,7 @@
 
     /**
      * Equivalent to calling {@link TextView#setTextSize(int, float)}
-     * 
+     *
      * @param viewId The id of the view whose text size should change
      * @param units The units of size (e.g. COMPLEX_UNIT_SP)
      * @param size The size of the text
@@ -1649,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.
@@ -2098,16 +2101,16 @@
     /**
      * Inflates the view hierarchy represented by this object and applies
      * all of the actions.
-     * 
+     *
      * <p><strong>Caller beware: this may throw</strong>
-     * 
+     *
      * @param context Default context to use
      * @param parent Parent that the resulting view hierarchy will be attached to. This method
      * does <strong>not</strong> attach the hierarchy. The caller should do so when appropriate.
      * @return The inflated view hierarchy
      */
     public View apply(Context context, ViewGroup parent) {
-        return apply(context, parent, DEFAULT_ON_CLICK_HANDLER);
+        return apply(context, parent, null);
     }
 
     /** @hide */
@@ -2135,12 +2138,12 @@
      * Applies all of the actions to the provided view.
      *
      * <p><strong>Caller beware: this may throw</strong>
-     * 
+     *
      * @param v The view to apply the actions to.  This should be the result of
      * the {@link #apply(Context,ViewGroup)} call.
      */
     public void reapply(Context context, View v) {
-        reapply(context, v, DEFAULT_ON_CLICK_HANDLER);
+        reapply(context, v, null);
     }
 
     /** @hide */
@@ -2163,6 +2166,7 @@
 
     private void performApply(View v, ViewGroup parent, OnClickHandler handler) {
         if (mActions != null) {
+            handler = handler == null ? DEFAULT_ON_CLICK_HANDLER : handler;
             final int count = mActions.size();
             for (int i = 0; i < count; i++) {
                 Action a = mActions.get(i);
@@ -2191,7 +2195,7 @@
 
     /* (non-Javadoc)
      * Used to restrict the views which can be inflated
-     * 
+     *
      * @see android.view.LayoutInflater.Filter#onLoadClass(java.lang.Class)
      */
     public boolean onLoadClass(Class clazz) {
diff --git a/core/java/android/widget/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 c44ce8a..a30567f 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/SeekBar.java b/core/java/android/widget/SeekBar.java
index 2737f94..a6486a8 100644
--- a/core/java/android/widget/SeekBar.java
+++ b/core/java/android/widget/SeekBar.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
+import android.util.ValueModel;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 
@@ -33,7 +34,7 @@
  *
  * @attr ref android.R.styleable#SeekBar_thumb
  */
-public class SeekBar extends AbsSeekBar {
+public class SeekBar extends AbsSeekBar implements ValueEditor<Integer> {
 
     /**
      * A callback that notifies clients when the progress level has been
@@ -69,8 +70,9 @@
         void onStopTrackingTouch(SeekBar seekBar);
     }
 
+    private ValueModel<Integer> mValueModel = ValueModel.EMPTY;
     private OnSeekBarChangeListener mOnSeekBarChangeListener;
-    
+
     public SeekBar(Context context) {
         this(context, null);
     }
@@ -89,9 +91,23 @@
 
         if (mOnSeekBarChangeListener != null) {
             mOnSeekBarChangeListener.onProgressChanged(this, getProgress(), fromUser);
+            if (fromUser) {
+                mValueModel.set(getProgress());
+            }
         }
     }
 
+    @Override
+    public ValueModel<Integer> getValueModel() {
+        return mValueModel;
+    }
+
+    @Override
+    public void setValueModel(ValueModel<Integer> valueModel) {
+        mValueModel = valueModel;
+        setProgress(mValueModel.get());
+    }
+
     /**
      * Sets a listener to receive notifications of changes to the SeekBar's progress level. Also
      * provides notifications of when the user starts and stops a touch gesture within the SeekBar.
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..1f713d4 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;
 
@@ -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) {
@@ -772,7 +759,22 @@
     }
 
     @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..f502de4 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1542,7 +1542,6 @@
     /**
      * Returns the start padding of the view, plus space for the start
      * Drawable if any.
-     * @hide
      */
     public int getCompoundPaddingStart() {
         resolveDrawables();
@@ -1558,7 +1557,6 @@
     /**
      * Returns the end padding of the view, plus space for the end
      * Drawable if any.
-     * @hide
      */
     public int getCompoundPaddingEnd() {
         resolveDrawables();
@@ -1656,7 +1654,6 @@
     /**
      * Returns the total start padding of the view, including the start
      * Drawable if any.
-     * @hide
      */
     public int getTotalPaddingStart() {
         return getCompoundPaddingStart();
@@ -1665,7 +1662,6 @@
     /**
      * Returns the total end padding of the view, including the end
      * Drawable if any.
-     * @hide
      */
     public int getTotalPaddingEnd() {
         return getCompoundPaddingEnd();
@@ -1868,7 +1864,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 +1985,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 +2008,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 +2054,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 +2203,27 @@
     }
 
     /**
+     * Get the default {@link Locale} of the text in this TextView.
+     * @return the default {@link Locale} of the text in this TextView.
+     */
+    public Locale getTextLocale() {
+        return mTextPaint.getTextLocale();
+    }
+
+    /**
+     * Set the default {@link Locale} of the text in this TextView to the given value. This value
+     * is used to choose appropriate typefaces for ambiguous characters. Typically used for CJK
+     * locales to disambiguate Hanzi/Kanji/Hanja characters.
+     *
+     * @param locale the {@link Locale} for drawing text, must not be null.
+     *
+     * @see Paint#setTextLocale
+     */
+    public void setTextLocale(Locale locale) {
+        mTextPaint.setTextLocale(locale);
+    }
+
+    /**
      * @return the size (in pixels) of the default text size in this TextView.
      */
     @ViewDebug.ExportedProperty(category = "text")
@@ -4586,23 +4599,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 +4858,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 +4888,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,7 +5636,6 @@
                       physicalWidth, false);
     }
 
-    /** @hide */
     @Override
     public void onResolvedLayoutDirectionReset() {
         if (mLayoutAlignment != null) {
@@ -7481,7 +7482,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 +7511,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 +8184,6 @@
         return mEditor.mInBatchEditControllers;
     }
 
-    /** @hide */
     @Override
     public void onResolvedTextDirectionChanged() {
         if (hasPasswordTransformationMethod()) {
@@ -8216,13 +8219,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 +8236,7 @@
         }
 
         Drawables dr = mDrawables;
-        switch(getResolvedLayoutDirection()) {
+        switch(layoutDirection) {
             case LAYOUT_DIRECTION_RTL:
                 if (dr.mDrawableStart != null) {
                     dr.mDrawableRight = dr.mDrawableStart;
@@ -8270,9 +8268,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;
     }
@@ -8593,13 +8607,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 +8705,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..e8bf9d9 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.layoutDirection);
                 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/ValueEditor.java b/core/java/android/widget/ValueEditor.java
new file mode 100755
index 0000000..2b91abf
--- /dev/null
+++ b/core/java/android/widget/ValueEditor.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.widget;
+
+import android.util.ValueModel;
+
+/**
+ * An interface for editors of simple values. Classes implementing this interface are normally
+ * UI controls (subclasses of {@link android.view.View View}) that can provide a suitable
+ * user interface to display and edit values of the specified type. This interface is
+ * intended to describe editors for simple types, like {@code boolean}, {@code int} or
+ * {@code String}, where the values themselves are immutable.
+ * <p>
+ * For example, {@link android.widget.CheckBox CheckBox} implements
+ * this interface for the Boolean type as it is capable of providing an appropriate
+ * mechanism for displaying and changing the value of a Boolean property.
+ *
+ * @param <T> the value type that this editor supports
+ */
+public interface ValueEditor<T> {
+    /**
+     * Return the last value model that was set. If no value model has been set, the editor
+     * should return the value {@link android.util.ValueModel#EMPTY}.
+     *
+     * @return the value model
+     */
+    public ValueModel<T> getValueModel();
+
+    /**
+     * Sets the value model for this editor. When the value model is set, the editor should
+     * retrieve the value from the value model, using {@link android.util.ValueModel#get()},
+     * and set its internal state accordingly. Likewise, when the editor's internal state changes
+     * it should update the value model by calling  {@link android.util.ValueModel#set(T)}
+     * with the appropriate value.
+     *
+     * @param valueModel the new value model for this editor.
+     */
+    public void setValueModel(ValueModel<T> valueModel);
+}
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..7d1231e 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) {
@@ -230,4 +255,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/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/cmds/sensorservice/main_sensorservice.cpp b/core/java/com/android/internal/net/VpnProfile.aidl
similarity index 69%
copy from cmds/sensorservice/main_sensorservice.cpp
copy to core/java/com/android/internal/net/VpnProfile.aidl
index 8610627..a072160 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/core/java/com/android/internal/net/VpnProfile.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,12 +14,6 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+package com.android.internal.net;
 
-using namespace android;
-
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
-}
+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..d24513a 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/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/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/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..dc4ee3a 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);
@@ -489,8 +494,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 +573,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..4777c16 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -34,7 +34,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;
@@ -246,7 +246,7 @@
         if (callingUid == android.os.Process.SYSTEM_UID) {
             return mCurrentUserId;
         } else {
-            return UserId.getUserId(callingUid);
+            return UserHandle.getUserId(callingUid);
         }
     }
 
diff --git a/core/java/com/android/internal/widget/LockSettingsService.java b/core/java/com/android/internal/widget/LockSettingsService.java
index 24c7161..350e006 100644
--- a/core/java/com/android/internal/widget/LockSettingsService.java
+++ b/core/java/com/android/internal/widget/LockSettingsService.java
@@ -24,7 +24,8 @@
 import android.database.sqlite.SQLiteOpenHelper;
 import android.os.Binder;
 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 +97,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 +105,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 +113,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);
         }
@@ -303,12 +304,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 +363,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..9d45479 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 \
@@ -136,14 +137,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 +162,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 +227,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..55563a8 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);
@@ -1092,7 +1087,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 +1095,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),
@@ -1168,12 +1164,6 @@
     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 a65262c..edc9732 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/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 35f82a8..7abfcf1 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -19,6 +19,7 @@
 #include "TextLayoutCache.h"
 #include "TextLayout.h"
 #include "SkFontHost.h"
+#include "SkTypeface_android.h"
 #include <unicode/unistr.h>
 #include <unicode/normlzr.h>
 #include <unicode/uchar.h>
@@ -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);
 
@@ -232,7 +225,7 @@
  */
 TextLayoutCacheKey::TextLayoutCacheKey(): text(NULL), start(0), count(0), contextCount(0),
         dirFlags(0), typeface(NULL), textSize(0), textSkewX(0), textScaleX(0), flags(0),
-        hinting(SkPaint::kNo_Hinting)  {
+        hinting(SkPaint::kNo_Hinting), variant(SkPaint::kDefault_Variant), language()  {
 }
 
 TextLayoutCacheKey::TextLayoutCacheKey(const SkPaint* paint, const UChar* text,
@@ -245,6 +238,8 @@
     textScaleX = paint->getTextScaleX();
     flags = paint->getFlags();
     hinting = paint->getHinting();
+    variant = paint->getFontVariant();
+    language = paint->getLanguage();
 }
 
 TextLayoutCacheKey::TextLayoutCacheKey(const TextLayoutCacheKey& other) :
@@ -259,7 +254,9 @@
         textSkewX(other.textSkewX),
         textScaleX(other.textScaleX),
         flags(other.flags),
-        hinting(other.hinting) {
+        hinting(other.hinting),
+        variant(other.variant),
+        language(other.language) {
     if (other.text) {
         textCopy.setTo(other.text, other.contextCount);
     }
@@ -296,6 +293,12 @@
     deltaInt = lhs.dirFlags - rhs.dirFlags;
     if (deltaInt) return (deltaInt);
 
+    deltaInt = lhs.variant - rhs.variant;
+    if (deltaInt) return (deltaInt);
+
+    if (lhs.language < rhs.language) return -1;
+    if (lhs.language > rhs.language) return +1;
+
     return memcmp(lhs.getText(), rhs.getText(), lhs.contextCount * sizeof(UChar));
 }
 
@@ -316,11 +319,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 +341,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 +353,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 +368,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 +378,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 +445,7 @@
                                 ALOGW("Visual run is not valid");
                                 outGlyphs->clear();
                                 outAdvances->clear();
+                                outPos->clear();
                                 *outTotalAdvance = 0;
                                 isRTL = (paraDir == 1);
                                 useSingleRun = true;
@@ -483,15 +468,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 +497,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 +519,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 +621,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 +701,6 @@
             currentAdvance = HBFixedToFloat(mShaperItem.advances[i]);
             totalFontRunAdvance += currentAdvance;
         }
-        totalAdvance += totalFontRunAdvance;
 
 #if DEBUG_ADVANCES
         ALOGD("Returned advances");
@@ -741,6 +725,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 +766,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 +807,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 +905,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);
diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h
index cb15a2a..64b33a0 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
 
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_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_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_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..9fc73a4 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -528,8 +528,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 +559,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,
@@ -769,6 +775,13 @@
     env->ReleaseIntArrayElements(layerInfo, storage, 0);
 }
 
+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,
         Layer* layer, jint width, jint height, jboolean isOpaque, jobject surface) {
     float transform[16];
@@ -803,10 +816,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);
@@ -969,13 +978,13 @@
     { "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 },
+    { "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..4d5e680 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,50 @@
 #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;
+} 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 +97,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 +149,311 @@
     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 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 +480,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 +550,197 @@
     }
 
     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);
+    // TODO: pass the name to SF.
+    sp<IBinder> token(SurfaceComposerClient::createDisplay());
+    return javaObjectForIBinder(env, token);
+}
+
+static void nativeSetDisplaySurface(JNIEnv* env, jclass clazz,
+        jobject tokenObj, jobject surfaceTextureObj) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return;
+
+    if (!surfaceTextureObj) {
+        SurfaceComposerClient::setDisplaySurface(token, NULL);
+        return;
+    }
+
+    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();
+    SurfaceComposerClient::setDisplaySurface(token, bq);
+}
+
+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 nativeSetDisplayOrientation(JNIEnv* env, jclass clazz,
+        jobject tokenObj, jint orientation) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return;
+
+    SurfaceComposerClient::setDisplayOrientation(token, orientation);
+}
+
+static void nativeSetDisplayViewport(JNIEnv* env, jclass clazz,
+        jobject tokenObj, jobject rectObj) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return;
+
+    Rect rect;
+    rect.left = env->GetIntField(rectObj, gRectClassInfo.left);
+    rect.top = env->GetIntField(rectObj, gRectClassInfo.top);
+    rect.right = env->GetIntField(rectObj, gRectClassInfo.right);
+    rect.bottom = env->GetIntField(rectObj, gRectClassInfo.bottom);
+    SurfaceComposerClient::setDisplayViewport(token, rect);
+}
+
+static void nativeSetDisplayFrame(JNIEnv* env, jclass clazz,
+        jobject tokenObj, jobject rectObj) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return;
+
+    Rect rect;
+    rect.left = env->GetIntField(rectObj, gRectClassInfo.left);
+    rect.top = env->GetIntField(rectObj, gRectClassInfo.top);
+    rect.right = env->GetIntField(rectObj, gRectClassInfo.right);
+    rect.bottom = env->GetIntField(rectObj, gRectClassInfo.bottom);
+    SurfaceComposerClient::setDisplayFrame(token, rect);
+}
+
+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 +752,125 @@
     // 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/graphics/SurfaceTexture;)V",
+            (void*)nativeSetDisplaySurface },
+    {"nativeSetDisplayLayerStack", "(Landroid/os/IBinder;I)V",
+            (void*)nativeSetDisplayLayerStack },
+    {"nativeSetDisplayOrientation", "(Landroid/os/IBinder;I)V",
+            (void*)nativeSetDisplayOrientation },
+    {"nativeSetDisplayViewport", "(Landroid/os/IBinder;Landroid/graphics/Rect;)V",
+            (void*)nativeSetDisplayViewport },
+    {"nativeSetDisplayFrame", "(Landroid/os/IBinder;Landroid/graphics/Rect;)V",
+            (void*)nativeSetDisplayFrame },
+    {"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");
+
+    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..abb9c0f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -62,6 +62,7 @@
     <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_SWITCHED" />
 
     <protected-broadcast android:name="android.app.action.ENTER_CAR_MODE" />
@@ -121,6 +122,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" />
@@ -277,6 +279,13 @@
         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"
@@ -508,6 +517,11 @@
         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 -->
     <!-- ================================== -->
@@ -711,6 +725,13 @@
         android:description="@string/permdesc_mediaStorageWrite"
         android:protectionLevel="signature|system" />
 
+    <!-- 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" />
+
     <!-- ============================================ -->
     <!-- Permissions for low-level system interaction -->
     <!-- ============================================ -->
@@ -753,7 +774,34 @@
         android:protectionLevel="dangerous"
         android:label="@string/permlab_getTasks"
         android:description="@string/permdesc_getTasks" />
+    <!-- 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" />
+
+    <!-- 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 -->
@@ -1223,6 +1271,19 @@
         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" />
+
     <!-- Allows an application to watch and control how activities are
          started globally in the system.  Only for is in debugging
          (usually the monkey command). -->
@@ -1396,6 +1457,11 @@
         android:description="@string/permdesc_devicePower"
         android:protectionLevel="signature" />
 
+   <!-- 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"
@@ -1604,7 +1670,6 @@
 
     <!-- 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"
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..6e1e17a
--- /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/flip_duration"
+        android:startOffset="@integer/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..5d65cd0
--- /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/flip_duration" />
+
+</set>
+
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-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-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-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/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/layout-land/keyguard_host_view.xml b/core/res/res/layout-land/keyguard_host_view.xml
new file mode 100644
index 0000000..b404155
--- /dev/null
+++ b/core/res/res/layout-land/keyguard_host_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 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"/>
+    </com.android.internal.policy.impl.keyguard.KeyguardWidgetPager>
+
+
+    <ViewFlipper
+        android:id="@+id/view_flipper"
+        android:layout_width="0dip"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:gravity="center">
+
+        <include layout="@layout/keyguard_selector_view"/>
+        <include layout="@layout/keyguard_account_view"/>
+        <include layout="@layout/keyguard_pattern_view"/>
+        <include layout="@layout/keyguard_password_view"/>
+        <include layout="@layout/keyguard_sim_pin_view"/>
+        <include layout="@layout/keyguard_sim_puk_view"/>
+        <include layout="@layout/keyguard_face_unlock_view"/>
+
+    </ViewFlipper>
+
+</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..5dc2225
--- /dev/null
+++ b/core/res/res/layout-port/keyguard_host_view.xml
@@ -0,0 +1,47 @@
+<?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">
+
+    <ViewFlipper
+        android:id="@+id/view_flipper"
+        android:layout_height="match_parent"
+        android:gravity="center">
+
+        <include layout="@layout/keyguard_selector_view"/>
+        <include layout="@layout/keyguard_account_view"/>
+        <include layout="@layout/keyguard_pattern_view"/>
+        <include layout="@layout/keyguard_password_view"/>
+        <include layout="@layout/keyguard_sim_pin_view"/>
+        <include layout="@layout/keyguard_sim_puk_view"/>
+        <include layout="@layout/keyguard_face_unlock_view"/>
+
+    </ViewFlipper>
+
+</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..e77f584
--- /dev/null
+++ b/core/res/res/layout-sw600dp-land/keyguard_host_view.xml
@@ -0,0 +1,67 @@
+<?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"/>
+
+    </com.android.internal.policy.impl.keyguard.KeyguardWidgetPager>
+
+    <FrameLayout
+        android:layout_width="0dip"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:gravity="center">
+
+        <ViewFlipper
+            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">
+
+            <include layout="@layout/keyguard_selector_view"/>
+            <include layout="@layout/keyguard_account_view"/>
+            <include layout="@layout/keyguard_pattern_view"/>
+            <include layout="@layout/keyguard_password_view"/>
+            <include layout="@layout/keyguard_sim_pin_view"/>
+            <include layout="@layout/keyguard_sim_puk_view"/>
+            <include layout="@layout/keyguard_face_unlock_view"/>
+
+        </ViewFlipper>
+
+    </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..50636f1
--- /dev/null
+++ b/core/res/res/layout-sw600dp-port/keyguard_host_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 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.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 once supported as a widget -->
+        <include layout="@layout/keyguard_status_view"/>
+
+    </com.android.internal.policy.impl.keyguard.KeyguardWidgetPager>
+
+    <ViewFlipper
+        android:id="@+id/view_flipper"
+        android:layout_width="@dimen/kg_security_view_width"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:layout_gravity="center">
+
+        <include layout="@layout/keyguard_selector_view"/>
+        <include layout="@layout/keyguard_account_view"/>
+        <include layout="@layout/keyguard_pattern_view"/>
+        <include layout="@layout/keyguard_password_view"/>
+        <include layout="@layout/keyguard_sim_pin_view"/>
+        <include layout="@layout/keyguard_sim_puk_view"/>
+        <include layout="@layout/keyguard_face_unlock_view"/>
+
+    </ViewFlipper>
+
+</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..4ceb907 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"
@@ -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..da627b5 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"
@@ -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..df999f0 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"/>
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..565785b 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"/>
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..51b946a 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"
@@ -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..1d6b6a9 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">
@@ -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..7fc31d8 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"
@@ -76,8 +76,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>
@@ -109,7 +109,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 +127,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..ce0cd42 100644
--- a/core/res/res/layout/app_permission_item.xml
+++ b/core/res/res/layout/app_permission_item.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_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..829d15f 100755
--- a/core/res/res/layout/app_perms_summary.xml
+++ b/core/res/res/layout/app_perms_summary.xml
@@ -26,8 +26,8 @@
         android:id="@+id/no_permissions"
         android:text="@string/no_permissions"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:paddingLeft="16dip"
-        android:paddingRight="12dip"
+        android:paddingStart="16dip"
+        android:paddingEnd="12dip"
         android:visibility="gone"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
@@ -37,8 +37,8 @@
         android:id="@+id/dangerous_perms_list"
         android:orientation="vertical"
         android:layout_width="match_parent"
-        android:paddingLeft="16dip"
-        android:paddingRight="12dip"
+        android:paddingStart="16dip"
+        android:paddingEnd="12dip"
         android:layout_height="wrap_content" />
 
     <!-- Clickable area letting user display additional permissions. -->
@@ -62,7 +62,7 @@
             android:layout_height="wrap_content"
             android:paddingTop="16dip"
             android:paddingBottom="12dip"
-            android:paddingLeft="16dip"
+            android:paddingStart="16dip"
             android:duplicateParentState="true"
             android:background="?android:attr/selectableItemBackground">
 
@@ -72,7 +72,7 @@
                 android:duplicateParentState="true"
                 android:layout_alignTop="@+id/show_more_icon"
                 android:layout_gravity="center_vertical"
-                android:paddingLeft="36dip"
+                android:paddingStart="36dip"
                 android:layout_weight="1"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content" />
@@ -81,7 +81,7 @@
                 android:id="@id/show_more_icon"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginRight="12dip" />
+                android:layout_marginEnd="12dip" />
 
         </LinearLayout>
 
@@ -96,8 +96,8 @@
     <LinearLayout
         android:id="@+id/non_dangerous_perms_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" />
 
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..572c013
--- /dev/null
+++ b/core/res/res/layout/keyguard_face_unlock_view.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This is the 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.KeyguardFaceUnlockView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/keyguard_face_unlock_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <!-- TODO -->
+
+</com.android.internal.policy.impl.keyguard.KeyguardFaceUnlockView>
diff --git a/core/res/res/layout/keyguard_navigation.xml b/core/res/res/layout/keyguard_navigation.xml
new file mode 100644
index 0000000..569f93d
--- /dev/null
+++ b/core/res/res/layout/keyguard_navigation.xml
@@ -0,0 +1,61 @@
+<?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:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+
+        <TextView
+            android:id="@+id/back"
+            android:layout_width="20dip"
+            android:layout_height="wrap_content"
+            android:textSize="28dp"
+            android:text="@string/kg_temp_back_string" />
+
+        <!-- message area for security screen -->
+        <TextView
+            android:id="@+id/message_area"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:singleLine="true"
+            android:ellipsize="marquee"
+            android:layout_marginEnd="6dip"
+            android:layout_marginStart="6dip"
+            android:textAppearance="?android:attr/textAppearanceMedium"/>
+
+    </LinearLayout>
+
+    <!-- This is currently only uses for pattern unlock -->
+    <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"/>
+
+</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..b9a70e5
--- /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"/>
+
+    <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_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>
+
+    <!-- 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..9cba609
--- /dev/null
+++ b/core/res/res/layout/keyguard_pattern_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 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:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <GridLayout
+        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" />
+
+        <!-- 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"
+         />
+
+    </GridLayout>
+
+</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..71fb363 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"
@@ -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..486c7fe 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"
@@ -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..edd74e2 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"/>
 
 
@@ -169,7 +169,7 @@
         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..f20cbcd 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"
      />
 
@@ -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..d516369
--- /dev/null
+++ b/core/res/res/layout/keyguard_selector_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 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 once supported as a widget -->
+            <include layout="@layout/keyguard_status_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..f8d05b7
--- /dev/null
+++ b/core/res/res/layout/keyguard_status_view.xml
@@ -0,0 +1,119 @@
+<?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: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="@*android: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="@*android: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
index 7e2a31c..3e702df 100644
--- a/core/res/res/layout/keyguard_transport_control.xml
+++ b/core/res/res/layout/keyguard_transport_control.xml
@@ -47,8 +47,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/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..25c792a
--- /dev/null
+++ b/core/res/res/layout/overlay_display_window.xml
@@ -0,0 +1,27 @@
+<?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">
+    <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..f2c63ae 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..7a0a494 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"
@@ -37,14 +37,15 @@
             android:layout_height="wrap_content"
             android:layout_gravity="center"
             android:minWidth="48dp"
-            android:paddingRight="@dimen/preference_item_padding_inner" />
+            android:paddingRight="@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">
 
@@ -60,7 +61,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_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/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/strings.xml b/core/res/res/values-af/strings.xml
index 29c23e9..7aa8bf09 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>
@@ -217,6 +220,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 +252,10 @@
     <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>
     <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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"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 +1318,6 @@
     <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" msgid="9042666544146043569">"Ingeboude skerm"</string>
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index f0e96ba..3068fb9 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>
@@ -217,6 +220,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 +252,10 @@
     <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_shutdown" msgid="7185747824038909016">"ከፊል ዝጋ"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"የእንቅስቃሴውን አደራጅ ወደ ዝጋ ሁነታ አስቀምጥ።ሙሉ ለሙሉ ዝጋ አያከናውንም።"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"የትግበራ መቀያየርን ተከላከል"</string>
@@ -930,8 +943,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 +1046,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>
@@ -1139,7 +1159,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 +1167,14 @@
     <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>
+    <!-- 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">"ፋይል ምረጥ"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"ምንም ፋይል አልተመረጠም"</string>
     <string name="reset" msgid="2448168080964209908">"ዳግም አስጀምር"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"ውስጥ የተሰራ ማያ ገጽ"</string>
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 7a9ad77..df3d114 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>
@@ -217,6 +220,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 +252,10 @@
     <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_shutdown" msgid="7185747824038909016">"إيقاف تشغيل جزئي"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"لوضع مدير الأنشطة في حالة إيقاف التشغيل. لا يتم تنفيذ إيقاف تشغيل كامل."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"منع التبديل بين التطبيقات"</string>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"اختيار ملف"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"لم يتم اختيار أي ملف"</string>
     <string name="reset" msgid="2448168080964209908">"إعادة تعيين"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"شاشة مدمجة"</string>
 </resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 21f8896..55621b3 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>
@@ -217,6 +220,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 +252,10 @@
     <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_shutdown" msgid="7185747824038909016">"частковае адключэнне"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Спыняе дзейнасць менеджэра. Не выконвае поўнае адключэнне."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"прадухіляць пераключэнне прыкладанняў"</string>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"Выберыце файл"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Файл не выбраны"</string>
     <string name="reset" msgid="2448168080964209908">"Скінуць"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"Убудаваны экран"</string>
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 8d45aa9..4aea25f 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>
@@ -217,6 +220,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 +252,10 @@
     <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_shutdown" msgid="7185747824038909016">"частично изключване"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Изключва диспечера на дейностите. Не извършва пълно изключване."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"предотвратяване на превключването между приложения"</string>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"Избор на файл"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Няма избран файл"</string>
     <string name="reset" msgid="2448168080964209908">"Повторно задаване"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"Вграден екран"</string>
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 711030c..097e86c 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>
@@ -217,6 +220,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 +252,10 @@
     <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_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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"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 +1318,6 @@
     <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" msgid="9042666544146043569">"Pantalla integrada"</string>
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index c026ecd..c7f3f88 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>
@@ -217,6 +220,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 +252,10 @@
     <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>
     <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>
@@ -831,7 +844,7 @@
     <item quantity="other" msgid="3903706804349556379">"před <xliff:g id="COUNT">%d</xliff:g> s"</item>
   </plurals>
   <plurals name="num_minutes_ago">
-    <item quantity="one" msgid="3306787433088810191">"před 1 minutou"</item>
+    <item quantity="one" msgid="3306787433088810191">"před 1 min"</item>
     <item quantity="other" msgid="2176942008915455116">"před <xliff:g id="COUNT">%d</xliff:g> min"</item>
   </plurals>
   <plurals name="num_hours_ago">
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"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 +1234,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 +1318,6 @@
     <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" msgid="9042666544146043569">"Integrovaná obrazovka"</string>
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 443f828..d390c3f 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>
@@ -217,6 +220,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 +252,10 @@
     <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_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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"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 +1318,6 @@
     <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" msgid="9042666544146043569">"Indbygget skærm"</string>
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 8707f28..1bd213e 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>
@@ -217,6 +220,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 +252,10 @@
     <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_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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"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 +1318,6 @@
     <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" msgid="9042666544146043569">"Integrierter Bildschirm"</string>
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 223e096..75ceaed 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>
@@ -217,6 +220,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 +252,10 @@
     <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_shutdown" msgid="7185747824038909016">"μερικός τερματισμός λειτουργίας"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Θέτει το πρόγραμμα διαχείρισης δραστηριοτήτων σε κατάσταση τερματισμού λειτουργιών. Δεν εκτελεί πλήρη τερματισμό λειτουργιών."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"αποτροπή εναλλαγών εφαρμογών"</string>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"Επιλογή αρχείου"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Δεν έχει επιλεγεί αρχείο"</string>
     <string name="reset" msgid="2448168080964209908">"Επαναφορά"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"Ενσωματωμένη οθόνη"</string>
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index cdacbc4..4fe04fb 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>
@@ -217,6 +220,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 +252,10 @@
     <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_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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"Choose file"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"No file chosen"</string>
     <string name="reset" msgid="2448168080964209908">"Reset"</string>
@@ -1283,11 +1311,13 @@
     <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" msgid="9042666544146043569">"Built-in Screen"</string>
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 3b39f2a..170e2f1 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>
@@ -217,6 +220,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 +252,10 @@
     <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>
     <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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"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 +1318,6 @@
     <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" msgid="9042666544146043569">"Pantalla integrada"</string>
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 0118067..02551e3 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>
@@ -217,6 +220,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 +252,10 @@
     <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_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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"Seleccionar archivo"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Archivo no seleccionado"</string>
     <string name="reset" msgid="2448168080964209908">"Restablecer"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"Pantalla integrada"</string>
 </resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index c887a41..c15fae7 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>
@@ -217,6 +220,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 +252,10 @@
     <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_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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"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 +1318,6 @@
     <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" msgid="9042666544146043569">"Sisseehitatud ekraan"</string>
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index f52ab95..c55eb07 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>
@@ -129,10 +129,10 @@
     <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>
@@ -143,17 +143,20 @@
     <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_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,7 +171,7 @@
     <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="tablet" msgid="6975389054186265786">"دسترسی مستقیم به مخاطبین و تقویم ذخیره شده در رایانهٔ لوحی."</string>
     <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"دسترسی مستقیم به مخاطبین و تقویم ذخیره شده در گوشی."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"موقعیت مکانی شما"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"بر موقعیت مکانی فیزیکی خود نظارت داشته باشید."</string>
@@ -176,8 +179,8 @@
     <string name="permgroupdesc_network" msgid="4478299413241861987">"به ویژگی‎های مختلف شبکه دسترسی داشته باشید."</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>
@@ -208,15 +211,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 +235,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,24 +252,28 @@
     <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_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>
@@ -274,7 +287,7 @@
     <string name="permlab_manageAppTokens" msgid="1286505717050121370">"مدیریت نشانه‎های برنامه"</string>
     <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"به برنامه اجازه می‎دهد با ایجاد کنارگذر از سفارش عادی Z، نشانه‎های خود را ایجاد و مدیریت کند. برای برنامه‎های عادی مورد نیاز است."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"کلیدها و دکمه‌های کنترل را فشار دهید"</string>
-    <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"به برنامه اجازه می‎دهد تا رویدادهای ورودی خود (فشردن کلیدها و غیره) را تحویل دهد. برنامه‎های مخرب می‎توانند از آن استفاده کنند تا کارکرد رایانه لوحی را کنترل کنند."</string>
+    <string name="permdesc_injectEvents" product="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 +309,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 +352,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 +390,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>
@@ -391,14 +404,14 @@
     <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 +436,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 +455,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 +473,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="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>
@@ -493,18 +506,18 @@
     <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>
@@ -534,8 +547,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_cache_filesystem" msgid="5656487264819669824">"دسترسی به سیستم فایل حافظه پنهان"</string>
-    <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"به برنامه اجازه می‎دهد تا سیستم فایل حافظه پنهان را بخواند و بنویسد."</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,19 +560,19 @@
     <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>
@@ -703,7 +716,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 +734,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 +751,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 +771,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 +799,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 +835,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 +943,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,7 +977,7 @@
     <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>
@@ -1033,6 +1046,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>
@@ -1051,17 +1071,17 @@
     <string name="perms_description_app" msgid="5139836143293299417">"ارائه شده توسط <xliff:g id="APP_NAME">%1$s</xliff:g> ."</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"حافظه انبوه USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB متصل شد"</string>
-    <string name="usb_storage_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,7 +1089,7 @@
     <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_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>
@@ -1083,10 +1103,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 +1121,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"انتخاب فایل"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"هیچ فایلی انتخاب نشد"</string>
     <string name="reset" msgid="2448168080964209908">"بازنشانی"</string>
@@ -1272,7 +1300,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 +1310,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 +1318,6 @@
     <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" msgid="9042666544146043569">"صفحه نمایش از خود"</string>
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index bd28a20..ee536a6 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>
@@ -217,6 +220,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 +252,10 @@
     <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_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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"Valitse tiedosto"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Ei valittua tiedostoa"</string>
     <string name="reset" msgid="2448168080964209908">"Palauta"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"Sisäänrakennettu näyttö"</string>
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index e000f93..63a19f4 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>
@@ -217,6 +220,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 +252,10 @@
     <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_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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"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 +1318,6 @@
     <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" msgid="9042666544146043569">"Écran intégré"</string>
 </resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 6a43298..b2ab326 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>
@@ -187,7 +190,7 @@
     <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 +220,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 +239,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 +252,10 @@
     <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_shutdown" msgid="7185747824038909016">"आंशिक शटडाउन"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"गतिविधि प्रबंधक को शटडाउन स्‍थिति में रखता है. पूर्ण शटडाउन निष्‍पादित नहीं करता है."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"एप्‍लिकेशन स्‍विच करने से रोकता है"</string>
@@ -259,7 +272,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,7 +282,7 @@
     <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>
@@ -332,11 +345,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 +360,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 +371,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>
@@ -438,7 +451,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 +468,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,11 +541,11 @@
     <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_cache_filesystem" msgid="5656487264819669824">"कैश फ़ाइल सिस्‍टम में पहंचे"</string>
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"एप्‍लिकेशन को संचय फ़ाइल सिस्‍टम पढ़ने और लिखने देता है."</string>
@@ -542,7 +555,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>
@@ -711,7 +724,7 @@
     <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"आपका सिम कार्ड स्‍थायी रूप से अक्षम कर दिया गया है."\n" दूसरे SIM कार्ड के लिए अपने वायरलेस सेवा प्रदाता से संपर्क करें."</string>
     <string name="lockscreen_transport_prev_description" msgid="201594905152746886">"पिछला ट्रैक बटन"</string>
     <string name="lockscreen_transport_next_description" msgid="6089297650481292363">"अगला ट्रैक बटन"</string>
-    <string name="lockscreen_transport_pause_description" msgid="7659088786780128001">"रोकें बटन"</string>
+    <string name="lockscreen_transport_pause_description" msgid="7659088786780128001">"पॉज़ करें बटन"</string>
     <string name="lockscreen_transport_play_description" msgid="5888422938351019426">"चलाएं बटन"</string>
     <string name="lockscreen_transport_stop_description" msgid="4562318378766987601">"रोकें बटन"</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"केवल आपातकालीन कॉल"</string>
@@ -762,7 +775,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 +805,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 +934,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 +995,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 +1046,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>
@@ -1057,7 +1077,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 +1105,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 +1167,14 @@
     <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>
+    <!-- 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">"फ़ाइल चुनें"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"कोई फ़ाइल चुनी नहीं गई"</string>
     <string name="reset" msgid="2448168080964209908">"रीसेट करें"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"अंतर्निहित स्क्रीन"</string>
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index a33e03e..2dd59e0 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>
@@ -217,6 +220,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 +252,10 @@
     <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_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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"Odaberite datoteku"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nema odabranih datoteka"</string>
     <string name="reset" msgid="2448168080964209908">"Ponovo postavi"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"Ugrađeni zaslon"</string>
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 9b878c2..69dae8a 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>
@@ -217,6 +220,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 +252,10 @@
     <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_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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"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 +1318,6 @@
     <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" msgid="9042666544146043569">"Beépített képernyő"</string>
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index a760e41..f8e8fc1 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>
@@ -217,6 +220,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 +252,10 @@
     <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_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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"Pilih file"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Tidak ada file yang dipilih"</string>
     <string name="reset" msgid="2448168080964209908">"Setel ulang"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"Layar Ada Di Dalamnya"</string>
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index d912688..9a7c439 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>
@@ -217,6 +220,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 +252,10 @@
     <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_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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"Scegli file"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nessun file è stato scelto"</string>
     <string name="reset" msgid="2448168080964209908">"Reimposta"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"Schermo incorporato"</string>
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 416aa4e..2ae5206 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>
@@ -217,6 +220,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 +252,10 @@
     <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_shutdown" msgid="7185747824038909016">"כיבוי חלקי"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"מעביר את מנהל הפעילויות למצב כיבוי. לא מבצע כיבוי מלא."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"מנע החלפת יישומים"</string>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"בחר קובץ"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"לא נבחר קובץ"</string>
     <string name="reset" msgid="2448168080964209908">"איפוס"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"מסך מובנה"</string>
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index af28156..e94ebe7 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>
@@ -217,6 +220,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 +252,10 @@
     <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_shutdown" msgid="7185747824038909016">"部分的にシャットダウンする"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"アクティビティマネージャをシャットダウン状態にします。完全なシャットダウンは実行しません。"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"アプリケーションの切り替えを禁止する"</string>
@@ -760,7 +773,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 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"ファイルを選択"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"ファイルが選択されていません"</string>
     <string name="reset" msgid="2448168080964209908">"リセット"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"内蔵画面"</string>
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 1f2a17f..4609a80 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>
@@ -217,6 +220,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 +252,10 @@
     <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_shutdown" msgid="7185747824038909016">"부분 종료"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"작업 관리자를 종료 상태로 설정합니다. 전체 종료를 수행하지는 않습니다."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"애플리케이션 전환 방지"</string>
@@ -781,7 +794,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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"파일 선택"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"파일을 선택하지 않았습니다."</string>
     <string name="reset" msgid="2448168080964209908">"초기화"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"기본으로 제공되는 화면"</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/strings.xml b/core/res/res/values-lt/strings.xml
index 54badb6..ad2e4cd 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>
@@ -217,6 +220,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 +252,10 @@
     <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_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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"Pasirinkti failą"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nepasirinktas joks failas"</string>
     <string name="reset" msgid="2448168080964209908">"Atstatyti"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"Integruotas ekranas"</string>
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 91d9415..5a5c14b 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>
@@ -217,6 +220,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 +252,10 @@
     <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_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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"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 +1318,6 @@
     <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" msgid="9042666544146043569">"Iebūvēts ekrāns"</string>
 </resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 5a49127..2ac167f 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>
@@ -217,6 +220,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 +252,10 @@
     <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>
     <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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"Pilih fail"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Tiada fail dipilih"</string>
     <string name="reset" msgid="2448168080964209908">"Tetapkan semula"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"Skrin Terbina Dalam"</string>
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index b94f399..7012793 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>
@@ -217,6 +220,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 +252,10 @@
     <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_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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"Velg fil"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Ingen fil er valgt"</string>
     <string name="reset" msgid="2448168080964209908">"Tilbakestill"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"Innebygd skjerm"</string>
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 0af5649..8178980 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>
@@ -217,6 +220,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 +252,10 @@
     <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_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>
@@ -820,7 +833,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 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"Bestand kiezen"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Geen bestand geselecteerd"</string>
     <string name="reset" msgid="2448168080964209908">"Opnieuw instellen"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"Ingebouwd scherm"</string>
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 229012b..c907fe6 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>
@@ -217,6 +220,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 +252,10 @@
     <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_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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"Wybierz plik"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nie wybrano pliku"</string>
     <string name="reset" msgid="2448168080964209908">"Resetuj"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"Wbudowany ekran"</string>
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 6f8616a..7541db8 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>
@@ -217,6 +220,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 +252,10 @@
     <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>
     <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>
@@ -557,7 +570,7 @@
     <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>
@@ -930,8 +943,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 +1046,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>
@@ -1114,7 +1134,7 @@
     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"O armazenamento USB foi removido. Insira um novo suporte de dados."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Cartão SD removido. Insira um novo cartão."</string>
     <string name="activity_list_empty" msgid="1675388330786841066">"Não foi encontrada nenhuma atividade correspondente."</string>
-    <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"actualizar estatísticas de utilização de componentes"</string>
+    <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"atualizar estatísticas de utilização de componentes"</string>
     <string name="permdesc_pkgUsageStats" msgid="1106612424254277630">"Permite que a aplicação modifique as estatísticas de utilização de componentes recolhidas. Não se destina a utilização por aplicações normais."</string>
     <string name="permlab_copyProtectedData" msgid="4341036311211406692">"copiar conteúdo"</string>
     <string name="permdesc_copyProtectedData" msgid="4390697124288317831">"Permite à aplicação invocar o serviço de contentor predefinido para copiar conteúdo. Não se destina a ser utilizado por aplicações normais."</string>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"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 +1318,6 @@
     <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" msgid="9042666544146043569">"Ecrã Integrado"</string>
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 4bd669c..d8a5bba 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>
@@ -217,6 +220,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 +252,10 @@
     <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>
     <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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"Escolher arquivo"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nenhum arquivo escolhido"</string>
     <string name="reset" msgid="2448168080964209908">"Redefinir"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"Tela integrada"</string>
 </resources>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index a00934d..9ffa164 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>
@@ -289,6 +295,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 +357,14 @@
     <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 />
     <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>
@@ -1414,9 +1440,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 +1602,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) -->
@@ -1759,6 +1799,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 +2076,8 @@
     <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 (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 59acfe1..23c1491 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>
@@ -217,6 +220,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 +252,10 @@
     <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>
     <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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"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 +1318,6 @@
     <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" msgid="9042666544146043569">"Ecran încorporat"</string>
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index ea69d45..98dc250 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>
@@ -217,6 +220,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 +252,10 @@
     <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_shutdown" msgid="7185747824038909016">"частичное завершение работы"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Завершает работу диспетчера активности. Не выполняет полное завершение работы."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"запретить переключение приложений"</string>
@@ -695,7 +708,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 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"Выбрать файл"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Не выбран файл"</string>
     <string name="reset" msgid="2448168080964209908">"Сбросить"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"Встроенный экран"</string>
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 165f1ed..37395a8 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>
@@ -217,6 +220,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 +252,10 @@
     <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>
     <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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"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 +1318,6 @@
     <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" msgid="9042666544146043569">"Vstavaná obrazovka"</string>
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 46cbcdb..48fa35d 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>
@@ -217,6 +220,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 +252,10 @@
     <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_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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"Izberi datoteko"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nobena datoteka ni izbrana"</string>
     <string name="reset" msgid="2448168080964209908">"Ponastavi"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"Vgrajen zaslon"</string>
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index fd337a3..259cb15 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>
@@ -217,6 +220,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 +252,10 @@
     <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_shutdown" msgid="7185747824038909016">"делимично искључивање"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Ставља менаџера активности у стање искључивања. Не искључује га у потпуности."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"спречавање пребацивања са једне апликације на другу"</string>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"Одабери датотеку"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Није изабрана ниједна датотека"</string>
     <string name="reset" msgid="2448168080964209908">"Поново постави"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"Уграђени екран"</string>
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index ebe61a2..10bdd18 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>
@@ -217,6 +220,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 +252,10 @@
     <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_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>
@@ -395,7 +408,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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"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 +1310,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 +1318,6 @@
     <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" msgid="9042666544146043569">"Inbyggd skärm"</string>
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index c2bd3ee..5f20617 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>
@@ -217,6 +220,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 +252,10 @@
     <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_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>
@@ -470,8 +483,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>
@@ -737,7 +750,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 +914,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 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"Chagua faili"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Hakuna faili iliyochaguliwa"</string>
     <string name="reset" msgid="2448168080964209908">"Weka upya"</string>
@@ -1159,9 +1187,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">
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"Skrini Iliyojengewa ndani"</string>
 </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/strings.xml b/core/res/res/values-th/strings.xml
index 976ff8a..40d4eb6 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>
@@ -217,6 +220,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 +252,10 @@
     <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_shutdown" msgid="7185747824038909016">"ปิดการทำงานบางส่วน"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"กำหนดให้ตัวจัดการกิจกรรมอยู่ในสถานะปิดระบบ โดยไม่ได้ปิดระบบอย่างสมบูรณ์"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ป้องกันการเปลี่ยนแอปพลิเคชัน"</string>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"เลือกไฟล์"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"ไม่ได้เลือกไฟล์ไว้"</string>
     <string name="reset" msgid="2448168080964209908">"รีเซ็ต"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"หน้าจอในตัว"</string>
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index e9ea129..036a30e 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>
@@ -217,6 +220,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 +252,10 @@
     <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_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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"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 +1318,6 @@
     <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" msgid="9042666544146043569">"Built-in na Screen"</string>
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 1259bd5..2848eea 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>
@@ -217,6 +220,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 +252,10 @@
     <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>
     <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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"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 +1318,6 @@
     <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" msgid="9042666544146043569">"Yerleşik Ekran"</string>
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 8131fd7..ee3f8da5 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>
@@ -217,6 +220,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 +252,10 @@
     <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_shutdown" msgid="7185747824038909016">"частк. заверш. роб."</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Переводить диспетчер дій у стан завершення роботи. Не виконує повне завершення роботи."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"запобіг. зміні програм"</string>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"Виберіть файл"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Не вибрано файл"</string>
     <string name="reset" msgid="2448168080964209908">"Віднов."</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"Вбудований екран"</string>
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index d9de025..b5c17ae 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>
@@ -217,6 +220,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 +252,10 @@
     <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>
     <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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"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 +1318,6 @@
     <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" msgid="9042666544146043569">"Màn hình tích hợp"</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/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index f2f9fde..0caef06 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>
@@ -217,6 +220,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 +252,10 @@
     <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_shutdown" msgid="7185747824038909016">"部分关机"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"使活动管理器进入关闭状态。不执行彻底关机。"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"禁止切换应用"</string>
@@ -930,8 +943,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 +1046,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>
@@ -1050,13 +1070,13 @@
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"新增:"</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"由“<xliff:g id="APP_NAME">%1$s</xliff:g>”提供。"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB 大容量存储设备"</string>
-    <string name="usb_storage_title" msgid="5901459041398751495">"USB 已连接"</string>
+    <string name="usb_storage_title" msgid="5901459041398751495">"已连接 USB"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"您已通过 USB 连接至计算机。如果您要在计算机与 Android 设备的 USB 存储设备之间复制文件,请触摸下面的按钮。"</string>
     <string name="usb_storage_message" product="default" msgid="805351000446037811">"您已通过 USB 连接至计算机。如果您要在计算机和 Android 设备的 SD 卡之间复制文件,请触摸下面的按钮。"</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"打开 USB 存储设备"</string>
     <string name="usb_storage_error_message" product="nosdcard" msgid="3017045217365540658">"使用 USB 存储设备作为 USB 大容量存储设备时出现问题。"</string>
     <string name="usb_storage_error_message" product="default" msgid="2876018512716970313">"使用 SD 卡作为 USB 大容量存储设备时出现问题。"</string>
-    <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB 已连接"</string>
+    <string name="usb_storage_notification_title" msgid="8175892554757216525">"已连接 USB"</string>
     <string name="usb_storage_notification_message" msgid="939822783828183763">"触摸可将文件复制到计算机或从计算机复制到存储设备。"</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"关闭 USB 存储设备"</string>
     <string name="usb_storage_stop_notification_message" msgid="1656852098555623822">"触摸可关闭 USB 存储设备。"</string>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"选择文件"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"未选定任何文件"</string>
     <string name="reset" msgid="2448168080964209908">"重置"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"内置屏幕"</string>
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 8975871..2935256 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/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>
@@ -217,6 +220,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 +252,10 @@
     <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_shutdown" msgid="7185747824038909016">"部分關機"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"讓活動管理員進入關機狀態,而不執行完整的關機程序。"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"防止切換應用程式"</string>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"選擇檔案"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"未選擇任何檔案"</string>
     <string name="reset" msgid="2448168080964209908">"重設"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"內建畫面"</string>
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index a2bc951..8360097 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>
@@ -217,6 +220,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 +252,10 @@
     <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_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>
@@ -930,8 +943,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 +1046,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>
@@ -1147,6 +1167,14 @@
     <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>
+    <!-- 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">"Khetha ifayela"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Ayikho ifayela ekhethiwe"</string>
     <string name="reset" msgid="2448168080964209908">"Setha kabusha"</string>
@@ -1290,4 +1318,6 @@
     <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" msgid="9042666544146043569">"Okwakhelwe ngaphakathi kwesikrini"</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..209fff0 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 -->
         <!-- ============= -->
@@ -2154,40 +2159,6 @@
             <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>
-
     </declare-styleable>
 
     <!-- Attributes that can be used with a {@link android.view.ViewGroup} or any
@@ -3668,6 +3639,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" />
@@ -5513,6 +5502,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 +5706,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..1c3318d 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -284,7 +284,19 @@
          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.  You must hold the
+         permission {@link android.Manifest.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,
@@ -1194,6 +1206,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 +1288,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 +1322,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 +1377,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/config.xml b/core/res/res/values/config.xml
index a2e15e6..86d03ad 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
@@ -528,25 +533,48 @@
     <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:
 
-         Zone 0:        0 <= LUX < array[0]
-         Zone 1:        array[0] <= LUX < array[1]
+         Point 1:        LUX <= 0 (implicit)
+         Point 2:        0 < level[1] == LUX < level[2]
          ...
-         Zone N:        array[N - 1] <= LUX < array[N]
-         Zone N + 1:    array[N] <= LUX < infinity
+         Point N:        level[N - 1] == LUX < level[N]
+         Point N + 1:    level[N] <= LUX < infinity
+
+         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[1] (first 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 +582,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 +590,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 +617,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 +896,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. -->
@@ -868,4 +915,7 @@
 
     <!-- Set to true to add links to Cell Broadcast app from Settings and MMS app. -->
     <bool name="config_cellBroadcastAppLinks">false</bool>
+
+    <!--  Maximum number of supported users -->
+    <integer name="config_multiuserMaximumUsers">10</integer>
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index f30943a..372a1ee 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -237,4 +237,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-sw720dp-land/arrays.xml b/core/res/res/values/integers.xml
similarity index 67%
rename from core/res/res/values-sw720dp-land/arrays.xml
rename to core/res/res/values/integers.xml
index d845875..603fd7e 100644
--- a/core/res/res/values-sw720dp-land/arrays.xml
+++ b/core/res/res/values/integers.xml
@@ -1,7 +1,6 @@
 <?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");
@@ -17,13 +16,6 @@
 ** 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>
+    <integer name="flip_duration">300</integer>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 40768a0..6414df8 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -120,6 +120,8 @@
   <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" />
@@ -261,6 +263,7 @@
   <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" />
@@ -279,6 +282,7 @@
   <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="color" name="tab_indicator_text_v4" />
 
@@ -477,6 +481,9 @@
   <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_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" />
@@ -923,8 +930,6 @@
   <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" />
@@ -1092,6 +1097,7 @@
   <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" />
@@ -1202,6 +1208,8 @@
   <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="array" name="config_keyboardTapVibePattern" />
   <java-symbol type="array" name="config_longPressVibePattern" />
   <java-symbol type="array" name="config_safeModeDisabledVibePattern" />
@@ -1229,6 +1237,7 @@
   <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" />
@@ -1246,6 +1255,8 @@
   <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="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" />
@@ -1298,6 +1309,28 @@
   <java-symbol type="id" name="two" />
   <java-symbol type="id" name="unlock_widget" />
   <java-symbol type="id" name="zero" />
+  <java-symbol type="id" name="message_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="integer" name="config_carDockRotation" />
   <java-symbol type="integer" name="config_defaultUiModeType" />
   <java-symbol type="integer" name="config_deskDockRotation" />
@@ -1327,13 +1360,17 @@
   <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" />
@@ -1377,6 +1414,33 @@
   <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" />
+
 
   <!-- From services -->
   <java-symbol type="anim" name="screen_rotate_0_enter" />
@@ -1413,6 +1477,8 @@
   <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" />
@@ -1436,6 +1502,7 @@
   <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" />
@@ -1465,6 +1532,9 @@
   <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_virtualKeyQuietTimeMillis" />
   <java-symbol type="layout" name="am_compat_mode_dialog" />
@@ -1491,8 +1561,6 @@
   <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" />
@@ -1550,12 +1618,15 @@
   <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="config_defaultDreamComponent" />
   <java-symbol type="string" name="enable_explore_by_touch_warning_title" />
   <java-symbol type="string" name="enable_explore_by_touch_warning_message" />
 
@@ -3660,4 +3731,26 @@
   <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" />
+
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 3582768..3178af0 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>
 
@@ -543,6 +554,24 @@
        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 +659,20 @@
         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_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
@@ -1573,6 +1616,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. -->
@@ -2693,10 +2741,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>
@@ -3229,6 +3277,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 +3649,49 @@
 
     <!-- "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 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">Overlay #<xliff:g id="id">%1$d</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 -->
+    <string name="kg_emergency_call_label">Emergency call</string>
+    <string name="kg_forgot_pattern_button_text">Forgot Pattern</string>
+    <string name="kg_wrong_pattern">Wrong Pattern</string>
+    <string name="kg_wrong_password">Wrong Password</string>
+    <string name="kg_wrong_pin">Wrong PIN</string>
+    <string name="kg_too_many_failed_attempts_countdown">Too many attempts</string>
+    <string name="kg_pattern_instructions">Draw your pattern</string>
+    <string name="kg_sim_pin_instructions">Enter SIM PIN</string>
+    <string name="kg_pin_instructions">Enter PIN</string>
+    <string name="kg_password_instructions">Enter Password</string>
+    <string name="kg_puk_enter_puk_hint">PUK code</string>
+    <string name="kg_puk_enter_pin_hint">New PIN code</string>
+    <string name="kg_sim_unlock_progress_dialog_message">Unlocking SIM card\u2026</string>
+    <string name="kg_password_wrong_pin_code">Incorrect PIN code.</string>
+    <string name="kg_invalid_sim_pin_hint">Type a PIN that is 4 to 8 numbers.</string>
+    <string name="kg_invalid_sim_puk_hint">Type a PUK that is 8 numbers or longer.</string>
+    <string name="kg_sim_puk_recovery_hint">Type PUK and new PIN code</string>
+    <string name="kg_invalid_puk">The PUK you typed isn\'t correct.</string>
+
+    <string name="kg_login_too_many_attempts">Too many pattern attempts</string>
+    <string name="kg_login_instructions">To unlock, sign in with your Google account.</string>
+    <string name="kg_login_username_hint">Username (email)</string>
+    <string name="kg_login_password_hint">Password</string>
+    <string name="kg_login_submit_button">Sign in</string>
+    <string name="kg_login_invalid_input">Invalid username or password.</string>
+    <string name="kg_login_account_recovery_hint">Forgot your username or password\?\nVisit <b>google.com/accounts/recovery</b>.</string>
+    <string name="kg_login_checking_password">Checking\u2026</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/themes.xml b/core/res/res/values/themes.xml
index 481ca7f..2f93335 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>
@@ -637,6 +639,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 +966,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>
@@ -1267,6 +1273,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>
@@ -1576,6 +1584,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
@@ -1684,6 +1694,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
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..216344d 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
@@ -94,7 +94,6 @@
      * Control Wifi States
      */
     public WifiManager mWifiManager;
-    public WifiManager.Channel mChannel;
 
     /*
      * Verify connectivity state
@@ -242,7 +241,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 +500,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 +593,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 +652,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) {
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/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/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/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..a1fd14e 100755
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -864,7 +864,7 @@
 
     public void deleteFromRawResource(int iFlags, int dFlags) {
         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 {
@@ -914,12 +914,12 @@
 
     @LargeTest
     public void testDeleteNormalInternalRetainData() {
-        deleteFromRawResource(0, PackageManager.DONT_DELETE_DATA);
+        deleteFromRawResource(0, PackageManager.DELETE_KEEP_DATA);
     }
 
     @LargeTest
     public void testDeleteFwdLockedInternalRetainData() {
-        deleteFromRawResource(PackageManager.INSTALL_FORWARD_LOCK, PackageManager.DONT_DELETE_DATA);
+        deleteFromRawResource(PackageManager.INSTALL_FORWARD_LOCK, PackageManager.DELETE_KEEP_DATA);
     }
 
     @LargeTest
@@ -929,7 +929,7 @@
             return;
         }
 
-        deleteFromRawResource(PackageManager.INSTALL_EXTERNAL, PackageManager.DONT_DELETE_DATA);
+        deleteFromRawResource(PackageManager.INSTALL_EXTERNAL, PackageManager.DELETE_KEEP_DATA);
     }
 
     /* sdcard mount/unmount tests ******/
@@ -1656,7 +1656,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);
@@ -2532,7 +2532,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);
             }
diff --git a/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java b/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java
new file mode 100644
index 0000000..b814e2d
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.content.pm.ManifestDigest;
+import android.content.pm.VerificationParams;
+import android.net.Uri;
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+
+/**
+ * Tests the android.content.pm.VerificationParams class
+ *
+ * To test run:
+ * ./development/testrunner/runtest.py frameworks-core -c android.content.pm.VerificationParamsTest
+ */
+public class VerificationParamsTest extends AndroidTestCase {
+
+    private final static String VERIFICATION_URI_STRING = "http://verification.uri/path";
+    private final static String ORIGINATING_URI_STRING = "http://originating.uri/path";
+    private final static String REFERRER_STRING = "http://referrer.uri/path";
+    private final static byte[] DIGEST_BYTES = "fake digest".getBytes();
+
+    private final static Uri VERIFICATION_URI = Uri.parse(VERIFICATION_URI_STRING);
+    private final static Uri ORIGINATING_URI = Uri.parse(ORIGINATING_URI_STRING);
+    private final static Uri REFERRER = Uri.parse(REFERRER_STRING);
+
+    private final static ManifestDigest MANIFEST_DIGEST = new ManifestDigest(DIGEST_BYTES);
+
+    public void testParcel() throws Exception {
+        VerificationParams expected = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        Parcel parcel = Parcel.obtain();
+        expected.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+
+        VerificationParams actual = VerificationParams.CREATOR.createFromParcel(parcel);
+
+        assertEquals(VERIFICATION_URI, actual.getVerificationURI());
+
+        assertEquals(ORIGINATING_URI, actual.getOriginatingURI());
+
+        assertEquals(REFERRER, actual.getReferrer());
+
+        assertEquals(MANIFEST_DIGEST, actual.getManifestDigest());
+    }
+
+    public void testEquals_Success() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertEquals(params1, params2);
+    }
+
+    public void testEquals_VerificationUri_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+            REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse("http://a.different.uri/"), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_OriginatingUri_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse("http://a.different.uri/"),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_Referrer_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse("http://a.different.uri/"), new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_ManifestDigest_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest("a different digest".getBytes()));
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testHashCode_Success() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertEquals(params1.hashCode(), params2.hashCode());
+    }
+
+    public void testHashCode_VerificationUri_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(null, Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_OriginatingUri_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse("http://a.different.uri/"),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_Referrer_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING), null,
+                new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_ManifestDigest_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest("a different digest".getBytes()));
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+}
diff --git a/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/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/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/google/gcm/gcm.jd b/docs/html/guide/google/gcm/gcm.jd
index 5515f31..72c3f23 100644
--- a/docs/html/guide/google/gcm/gcm.jd
+++ b/docs/html/guide/google/gcm/gcm.jd
@@ -653,8 +653,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>
@@ -685,8 +687,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>
@@ -698,7 +702,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>
@@ -891,13 +895,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/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/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 87421b1..e82ccd4 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -385,7 +385,7 @@
             Shader shader = state.mPaint.getShader();
             if (shader == null) {
                 if (mApplyGravity) {
-                    final int layoutDirection = getResolvedLayoutDirectionSelf();
+                    final int layoutDirection = getLayoutDirection();
                     Gravity.apply(state.mGravity, mBitmapWidth, mBitmapHeight,
                             getBounds(), mDstRect, layoutDirection);
                     mApplyGravity = false;
diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java
index c41dd07..bade9b4 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) {
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 785582c..4bc5a5a 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 View#LAYOUT_DIRECTION_LTR},
+     *   {@link 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 View#LAYOUT_DIRECTION_LTR},
+     *   {@link 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/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index b68b267..62aea71 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -296,7 +296,7 @@
         if (dither) {
             options.inDither = false;
         }
-        options.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
+        options.inScreenDensity = r.getDisplayMetrics().noncompatDensityDpi;
 
         final Rect padding = new Rect();
         final Rect layoutInsets = new Rect();
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index ccad250..bd2b2f0 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -221,7 +221,7 @@
             final int ih = min ? mScaleState.mDrawable.getIntrinsicHeight() : 0;
             h -= (int) ((h - ih) * (10000 - level) * mScaleState.mScaleHeight / 10000);
         }
-        final int layoutDirection = getResolvedLayoutDirectionSelf();
+        final int layoutDirection = getLayoutDirection();
         Gravity.apply(mScaleState.mGravity, w, h, bounds, r, layoutDirection);
 
         if (w > 0 && h > 0) {
diff --git a/graphics/java/android/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..a85d464 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;
     }
 
     /**
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/cmds/sensorservice/main_sensorservice.cpp b/graphics/java/android/renderscript/ScriptIntrinsic.java
similarity index 63%
copy from cmds/sensorservice/main_sensorservice.cpp
copy to graphics/java/android/renderscript/ScriptIntrinsic.java
index 8610627..f275fee 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/graphics/java/android/renderscript/ScriptIntrinsic.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * 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.
@@ -14,12 +14,18 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+package android.renderscript;
 
-using namespace android;
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
 
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
+
+/**
+ * @hide
+ **/
+public class ScriptIntrinsic extends Script {
+    ScriptIntrinsic(int id, RenderScript rs) {
+        super(id, rs);
+    }
 }
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java b/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java
new file mode 100644
index 0000000..c7465a7
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.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 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;
+
+
+/**
+ * @hide
+ **/
+public class ScriptIntrinsicConvolve3x3 extends ScriptIntrinsic {
+    private float[] mValues = new float[9];
+    private Allocation mInput;
+
+    ScriptIntrinsicConvolve3x3(int id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    /**
+     * Supported elements types are float, float4, uchar, uchar4
+     *
+     *
+     * @param rs
+     * @param e
+     *
+     * @return ScriptIntrinsicConvolve3x3
+     */
+    public static ScriptIntrinsicConvolve3x3 create(RenderScript rs, Element e) {
+        int id = rs.nScriptIntrinsicCreate(1, e.getID(rs));
+        return new ScriptIntrinsicConvolve3x3(id, rs);
+
+    }
+
+    public void setInput(Allocation ain) {
+        mInput = ain;
+        bindAllocation(ain, 1);
+    }
+
+    public void setColorMatrix(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);
+    }
+
+    public void forEach(Allocation aout) {
+        forEach(0, null, aout, null);
+    }
+
+}
+
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicYuvToRGB.java b/graphics/java/android/renderscript/ScriptIntrinsicYuvToRGB.java
new file mode 100644
index 0000000..ee5f938
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicYuvToRGB.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 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_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..e50186d 100644
--- a/include/android_runtime/android_view_Surface.h
+++ b/include/android_runtime/android_view_Surface.h
@@ -25,12 +25,15 @@
 
 class Surface;
 
-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);
 
 } // 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/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/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..311359c
--- /dev/null
+++ b/keystore/java/android/security/AndroidKeyPairGeneratorSpec.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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>.
+ */
+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..7b6e540
--- /dev/null
+++ b/keystore/java/android/security/AndroidKeyStore.java
@@ -0,0 +1,481 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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) {
+        final X509Certificate leaf = (X509Certificate) engineGetCertificate(alias);
+        if (leaf == null) {
+            return null;
+        }
+
+        final Certificate[] caList;
+
+        final byte[] caBytes = mKeyStore.get(Credentials.CA_CERTIFICATE + alias);
+        if (caBytes != null) {
+            final Collection<X509Certificate> caChain = toCertificates(caBytes);
+
+            caList = new Certificate[caChain.size() + 1];
+
+            final Iterator<X509Certificate> it = caChain.iterator();
+            int i = 1;
+            while (it.hasNext()) {
+                caList[i++] = it.next();
+            }
+        } else {
+            caList = new Certificate[1];
+        }
+
+        caList[0] = leaf;
+
+        return caList;
+    }
+
+    @Override
+    public Certificate engineGetCertificate(String alias) {
+        byte[] certificate = mKeyStore.get(Credentials.USER_CERTIFICATE + alias);
+        if (certificate != null) {
+            return toCertificate(certificate);
+        }
+
+        certificate = mKeyStore.get(Credentials.CA_CERTIFICATE + alias);
+        if (certificate != null) {
+            return toCertificate(certificate);
+        }
+
+        return null;
+    }
+
+    private static X509Certificate toCertificate(byte[] bytes) {
+        try {
+            final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+            return (X509Certificate) certFactory
+                    .generateCertificate(new ByteArrayInputStream(bytes));
+        } catch (CertificateException e) {
+            Log.w(NAME, "Couldn't parse certificate in keystore", e);
+            return null;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private static Collection<X509Certificate> toCertificates(byte[] bytes) {
+        try {
+            final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+            return (Collection<X509Certificate>) certFactory
+                    .generateCertificates(new ByteArrayInputStream(bytes));
+        } catch (CertificateException e) {
+            Log.w(NAME, "Couldn't parse certificates in keystore", e);
+            return new ArrayList<X509Certificate>();
+        }
+    }
+
+    private Date getModificationDate(String alias) {
+        final long epochMillis = mKeyStore.getmtime(alias);
+        if (epochMillis == -1L) {
+            return null;
+        }
+
+        return new Date(epochMillis);
+    }
+
+    @Override
+    public Date engineGetCreationDate(String alias) {
+        Date d = getModificationDate(Credentials.USER_PRIVATE_KEY + alias);
+        if (d != null) {
+            return d;
+        }
+
+        d = getModificationDate(Credentials.USER_CERTIFICATE + alias);
+        if (d != null) {
+            return d;
+        }
+
+        return getModificationDate(Credentials.CA_CERTIFICATE + alias);
+    }
+
+    @Override
+    public void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] chain)
+            throws KeyStoreException {
+        if ((password != null) && (password.length > 0)) {
+            throw new KeyStoreException("entries cannot be protected with passwords");
+        }
+
+        if (key instanceof PrivateKey) {
+            setPrivateKeyEntry(alias, (PrivateKey) key, chain);
+        } else {
+            throw new KeyStoreException("Only PrivateKeys are supported");
+        }
+    }
+
+    private void setPrivateKeyEntry(String alias, PrivateKey key, Certificate[] chain)
+            throws KeyStoreException {
+        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 RuntimeException("Operation not supported because key encoding is unknown");
+    }
+
+    @Override
+    public void engineSetCertificateEntry(String alias, Certificate cert) throws KeyStoreException {
+        if (isKeyEntry(alias)) {
+            throw new KeyStoreException("Entry exists and is not a trusted certificate");
+        }
+
+        final byte[] encoded;
+        try {
+            encoded = cert.getEncoded();
+        } catch (CertificateEncodingException e) {
+            throw new KeyStoreException(e);
+        }
+
+        if (!mKeyStore.put(Credentials.CA_CERTIFICATE + alias, encoded)) {
+            throw new KeyStoreException("Couldn't insert certificate; is KeyStore initialized?");
+        }
+    }
+
+    @Override
+    public void engineDeleteEntry(String alias) throws KeyStoreException {
+        if (!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) {
+        return mKeyStore.contains(Credentials.USER_PRIVATE_KEY + alias)
+                || mKeyStore.contains(Credentials.USER_CERTIFICATE + alias)
+                || mKeyStore.contains(Credentials.CA_CERTIFICATE + alias);
+    }
+
+    @Override
+    public int engineSize() {
+        return getUniqueAliases().size();
+    }
+
+    @Override
+    public boolean engineIsKeyEntry(String alias) {
+        return isKeyEntry(alias);
+    }
+
+    private boolean isKeyEntry(String alias) {
+        return mKeyStore.contains(Credentials.USER_PRIVATE_KEY + alias);
+    }
+
+    @Override
+    public boolean engineIsCertificateEntry(String alias) {
+        return !isKeyEntry(alias) && mKeyStore.contains(Credentials.CA_CERTIFICATE + alias);
+    }
+
+    @Override
+    public String engineGetCertificateAlias(Certificate cert) {
+        if (cert == null) {
+            return null;
+        }
+
+        final Set<String> nonCaEntries = new HashSet<String>();
+
+        /*
+         * First scan the PrivateKeyEntry types. The KeyStoreSpi documentation
+         * says to only compare the first certificate in the chain which is
+         * equivalent to the USER_CERTIFICATE prefix for the Android keystore
+         * convention.
+         */
+        final String[] certAliases = mKeyStore.saw(Credentials.USER_CERTIFICATE);
+        for (String alias : certAliases) {
+            final byte[] certBytes = mKeyStore.get(Credentials.USER_CERTIFICATE + alias);
+            if (certBytes == null) {
+                continue;
+            }
+
+            final Certificate c = toCertificate(certBytes);
+            nonCaEntries.add(alias);
+
+            if (cert.equals(c)) {
+                return alias;
+            }
+        }
+
+        /*
+         * Look at all the TrustedCertificateEntry types. Skip all the
+         * PrivateKeyEntry we looked at above.
+         */
+        final String[] caAliases = mKeyStore.saw(Credentials.CA_CERTIFICATE);
+        for (String alias : caAliases) {
+            if (nonCaEntries.contains(alias)) {
+                continue;
+            }
+
+            final byte[] certBytes = mKeyStore.get(Credentials.CA_CERTIFICATE + alias);
+            if (certBytes == null) {
+                continue;
+            }
+
+            final Certificate c = toCertificate(mKeyStore.get(Credentials.CA_CERTIFICATE + alias));
+            if (cert.equals(c)) {
+                return alias;
+            }
+        }
+
+        return null;
+    }
+
+    @Override
+    public void engineStore(OutputStream stream, char[] password) throws IOException,
+            NoSuchAlgorithmException, CertificateException {
+        throw new UnsupportedOperationException("Can not serialize AndroidKeyStore to OutputStream");
+    }
+
+    @Override
+    public void engineLoad(InputStream stream, char[] password) throws IOException,
+            NoSuchAlgorithmException, CertificateException {
+        if (stream != null) {
+            throw new IllegalArgumentException("InputStream not supported");
+        }
+
+        if (password != null) {
+            throw new IllegalArgumentException("password not supported");
+        }
+
+        // Unfortunate name collision.
+        mKeyStore = android.security.KeyStore.getInstance();
+    }
+
+}
diff --git a/keystore/java/android/security/AndroidKeyStoreProvider.java b/keystore/java/android/security/AndroidKeyStoreProvider.java
new file mode 100644
index 0000000..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..b233ff6 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -61,6 +61,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";
 
@@ -185,4 +188,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/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..1947c32 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -11,6 +11,7 @@
 		Caches.cpp \
 		DisplayListLogBuffer.cpp \
 		DisplayListRenderer.cpp \
+		Dither.cpp \
 		FboCache.cpp \
 		GradientCache.cpp \
 		LayerCache.cpp \
@@ -40,12 +41,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..0ed4888 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();
@@ -351,14 +366,45 @@
     }
 }
 
-void Caches::setScissor(GLint x, GLint y, GLint width, GLint height) {
-    if (x != mScissorX || y != mScissorY || width != mScissorWidth || height != mScissorHeight) {
+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;
     }
 }
 
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 58361c9..f4f56d6 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -38,6 +38,7 @@
 #include "TextDropShadowCache.h"
 #include "FboCache.h"
 #include "ResourceCache.h"
+#include "Dither.h"
 
 namespace android {
 namespace uirenderer {
@@ -197,13 +198,17 @@
     /**
      * 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);
+
     /**
      * 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 +226,7 @@
     GLenum lastSrcMode;
     GLenum lastDstMode;
     Program* currentProgram;
+    bool scissorEnabled;
 
     // VBO to draw with
     GLuint meshBuffer;
@@ -230,6 +236,7 @@
 
     // Misc
     GLint maxTextureSize;
+    bool debugLayersUpdates;
 
     TextureCache textureCache;
     LayerCache layerCache;
@@ -244,8 +251,10 @@
     PatchCache patchCache;
     TextDropShadowCache dropShadowCache;
     FboCache fboCache;
-    GammaFontRenderer fontRenderer;
     ResourceCache resourceCache;
+    Dither dither;
+
+    GammaFontRenderer* fontRenderer;
 
     // Debug methods
     PFNGLINSERTEVENTMARKEREXTPROC eventMark;
@@ -256,8 +265,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..2de70d462 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",
@@ -486,7 +486,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 +572,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 +592,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 +855,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 +870,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 +886,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();
@@ -1089,11 +1100,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 +1199,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 +1224,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();
@@ -1570,6 +1586,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 +1597,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 +1689,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 +1743,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..c8b3e47 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,
@@ -599,12 +599,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);
@@ -770,10 +770,10 @@
         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 +785,8 @@
         }
 
         addInt((int) paintCopy);
+
+        return paintCopy;
     }
 
     inline void addDisplayList(DisplayList* 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..fb945a8 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
 ///////////////////////////////////////////////////////////////////////////////
@@ -69,10 +66,6 @@
         mHasDebugMarker = hasExtension("GL_EXT_debug_marker");
         mHasDebugLabel = hasExtension("GL_EXT_debug_label");
 
-        const char* vendor = (const char*) glGetString(GL_VENDOR);
-        EXT_LOGD("Vendor: %s", vendor);
-        mNeedsHighpTexCoords = strcmp(vendor, VENDOR_IMG) == 0;
-
         // 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
@@ -81,7 +74,6 @@
 
     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; }
@@ -101,7 +93,6 @@
     const char* mExtensions;
 
     bool mHasNPot;
-    bool mNeedsHighpTexCoords;
     bool mHasFramebufferFetch;
     bool mHasDiscardFramebuffer;
     bool mHasDebugMarker;
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 5fdbc11..6b08e7f 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -37,27 +37,153 @@
 #define DEFAULT_TEXT_CACHE_WIDTH 1024
 #define DEFAULT_TEXT_CACHE_HEIGHT 256
 #define MAX_TEXT_CACHE_WIDTH 2048
-#define TEXTURE_BORDER_SIZE 2
+#define CACHE_BLOCK_ROUNDING_SIZE 4
 
 #define AUTO_KERN(prev, next) (((next) - (prev) + 32) >> 6 << 16)
 
 ///////////////////////////////////////////////////////////////////////////////
-// CacheTextureLine
+// CacheBlock
 ///////////////////////////////////////////////////////////////////////////////
 
-bool CacheTextureLine::fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY) {
-    if (glyph.fHeight + TEXTURE_BORDER_SIZE > mMaxHeight) {
+/**
+ * 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 > mHeight) {
         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;
+    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;
+#if DEBUG_FONT_RENDERER
+            ALOGD("fitBitmap: current block list:");
+            mCacheBlocks->output();
+#endif
+            ++mNumGlyphs;
+            return true;
+        }
+        cacheBlock = cacheBlock->mNext;
     }
-
+#if DEBUG_FONT_RENDERER
+    ALOGD("fitBitmap: returning false for glyph of size %d, %d", glyphW, glyphH);
+#endif
     return false;
 }
 
@@ -87,10 +213,10 @@
     }
 }
 
-void Font::invalidateTextureCache(CacheTextureLine *cacheLine) {
+void Font::invalidateTextureCache(CacheTexture *cacheTexture) {
     for (uint32_t i = 0; i < mCachedGlyphs.size(); i++) {
         CachedGlyphInfo* cachedGlyph = mCachedGlyphs.valueAt(i);
-        if (cacheLine == NULL || cachedGlyph->mCachedTextureLine == cacheLine) {
+        if (cacheTexture == NULL || cachedGlyph->mCacheTexture == cacheTexture) {
             cachedGlyph->mIsValid = false;
         }
     }
@@ -134,7 +260,7 @@
     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);
+            nPenX, nPenY - height, u1, v1, glyph->mCacheTexture);
 }
 
 void Font::drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y,
@@ -145,7 +271,7 @@
     uint32_t endX = glyph->mStartX + glyph->mBitmapWidth;
     uint32_t endY = glyph->mStartY + glyph->mBitmapHeight;
 
-    CacheTexture *cacheTexture = glyph->mCachedTextureLine->mCacheTexture;
+    CacheTexture *cacheTexture = glyph->mCacheTexture;
     uint32_t cacheWidth = cacheTexture->mWidth;
     const uint8_t* cacheBuffer = cacheTexture->mTexture;
 
@@ -199,22 +325,22 @@
             position->fY + destination[2].fY, u2, v1,
             position->fX + destination[3].fX,
             position->fY + destination[3].fY, u1, v1,
-            glyph->mCachedTextureLine->mCacheTexture);
+            glyph->mCacheTexture);
 }
 
-CachedGlyphInfo* Font::getCachedGlyph(SkPaint* paint, glyph_t textUnit) {
+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);
+        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);
+        updateGlyphCache(paint, skiaGlyph, cachedGlyph, precaching);
     }
 
     return cachedGlyph;
@@ -288,13 +414,34 @@
 }
 
 void Font::measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
-        int numGlyphs, Rect *bounds) {
+        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, NULL);
+    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,
@@ -382,7 +529,8 @@
     }
 }
 
-void Font::updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph) {
+void Font::updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph,
+        bool precaching) {
     glyph->mAdvanceX = skiaGlyph.fAdvanceX;
     glyph->mAdvanceY = skiaGlyph.fAdvanceY;
     glyph->mBitmapLeft = skiaGlyph.fLeft;
@@ -395,7 +543,7 @@
 
     // Get the bitmap for the glyph
     paint->findImage(skiaGlyph);
-    mState->cacheBitmap(skiaGlyph, glyph, &startX, &startY);
+    mState->cacheBitmap(skiaGlyph, glyph, &startX, &startY, precaching);
 
     if (!glyph->mIsValid) {
         return;
@@ -409,18 +557,18 @@
     glyph->mBitmapWidth = skiaGlyph.fWidth;
     glyph->mBitmapHeight = skiaGlyph.fHeight;
 
-    uint32_t cacheWidth = glyph->mCachedTextureLine->mCacheTexture->mWidth;
-    uint32_t cacheHeight = glyph->mCachedTextureLine->mCacheTexture->mHeight;
+    uint32_t cacheWidth = glyph->mCacheTexture->mWidth;
+    uint32_t cacheHeight = glyph->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;
+    glyph->mBitmapMinU = startX / (float) cacheWidth;
+    glyph->mBitmapMinV = startY / (float) cacheHeight;
+    glyph->mBitmapMaxU = endX / (float) cacheWidth;
+    glyph->mBitmapMaxV = endY / (float) cacheHeight;
 
     mState->mUploadTexture = true;
 }
 
-CachedGlyphInfo* Font::cacheGlyph(SkPaint* paint, glyph_t glyph) {
+CachedGlyphInfo* Font::cacheGlyph(SkPaint* paint, glyph_t glyph, bool precaching) {
     CachedGlyphInfo* newGlyph = new CachedGlyphInfo();
     mCachedGlyphs.add(glyph, newGlyph);
 
@@ -428,7 +576,7 @@
     newGlyph->mGlyphIndex = skiaGlyph.fID;
     newGlyph->mIsValid = false;
 
-    updateGlyphCache(paint, skiaGlyph, newGlyph);
+    updateGlyphCache(paint, skiaGlyph, newGlyph, precaching);
 
     return newGlyph;
 }
@@ -473,10 +621,6 @@
     mTextMeshPtr = NULL;
     mCurrentCacheTexture = NULL;
     mLastCacheTexture = NULL;
-    mCacheTextureSmall = NULL;
-    mCacheTexture128 = NULL;
-    mCacheTexture256 = NULL;
-    mCacheTexture512 = NULL;
 
     mLinearFiltering = false;
 
@@ -512,10 +656,10 @@
 }
 
 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
@@ -523,10 +667,6 @@
         glDeleteBuffers(1, &mIndexBufferID);
 
         delete[] mTextMeshPtr;
-        delete mCacheTextureSmall;
-        delete mCacheTexture128;
-        delete mCacheTexture256;
-        delete mCacheTexture512;
     }
 
     Vector<Font*> fontsToDereference = mActiveFonts;
@@ -545,9 +685,22 @@
         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();
     }
+
+    #if DEBUG_FONT_RENDERER
+    uint16_t totalGlyphs = 0;
+    for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
+        totalGlyphs += mCacheTextures[i]->mNumGlyphs;
+        // Erase caches, just as a debugging facility
+        if (mCacheTextures[i]->mTexture) {
+            memset(mCacheTextures[i]->mTexture, 0,
+                    mCacheTextures[i]->mWidth * mCacheTextures[i]->mHeight);
+        }
+    }
+    ALOGD("Flushing caches: glyphs cached = %d", totalGlyphs);
+#endif
 }
 
 void FontRenderer::deallocateTextureMemory(CacheTexture *cacheTexture) {
@@ -560,29 +713,17 @@
 }
 
 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->mTexture != NULL) {
+            cacheTexture->init();
+            for (uint32_t j = 0; j < mActiveFonts.size(); j++) {
+                mActiveFonts[j]->invalidateTextureCache(cacheTexture);
             }
+            deallocateTextureMemory(cacheTexture);
         }
     }
-
-    deallocateTextureMemory(mCacheTexture128);
-    deallocateTextureMemory(mCacheTexture256);
-    deallocateTextureMemory(mCacheTexture512);
 }
 
 void FontRenderer::allocateTextureMemory(CacheTexture* cacheTexture) {
@@ -590,9 +731,6 @@
     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);
@@ -613,12 +751,25 @@
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 }
 
+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];
+        }
+    }
+    // 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 (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]->mHeight) {
+        ALOGE("Font size too large to fit in cache. width, height = %i, %i",
                 (int) glyph.fWidth, (int) glyph.fHeight);
         return;
     }
@@ -627,36 +778,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,9 +802,8 @@
     uint32_t endX = startX + glyph.fWidth;
     uint32_t endY = startY + glyph.fHeight;
 
-    uint32_t cacheWidth = cacheLine->mMaxWidth;
+    uint32_t cacheWidth = cacheTexture->mWidth;
 
-    CacheTexture* cacheTexture = cacheLine->mCacheTexture;
     if (!cacheTexture->mTexture) {
         // Large-glyph texture memory is allocated only as needed
         allocateTextureMemory(cacheTexture);
@@ -677,10 +814,31 @@
     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,8 +846,7 @@
 }
 
 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);
@@ -699,17 +856,10 @@
 }
 
 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;
-    }
+    mCacheTextures.clear();
 
     // Next, use other, separate caches for large glyphs.
     uint16_t maxWidth = 0;
@@ -721,35 +871,12 @@
         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;
-
     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(maxWidth, 256, false));
+    mCacheTextures.push(createCacheTexture(maxWidth, 256, false));
+    mCacheTextures.push(createCacheTexture(maxWidth, 512, false));
+    mCurrentCacheTexture = mCacheTextures[0];
 }
 
 // Avoid having to reallocate memory and render quad by quad
@@ -804,26 +931,28 @@
 
     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->mDirty && cacheTexture->mTexture != NULL) {
             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->mWidth;
+            uint32_t height  = cacheTexture->mHeight;
+            void* textureData = cacheTexture->mTexture;
 
             if (cacheTexture->mTextureId != lastTextureId) {
                 caches.activeTexture(0);
                 glBindTexture(GL_TEXTURE_2D, cacheTexture->mTextureId);
                 lastTextureId = cacheTexture->mTextureId;
             }
-            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->mDirty = false;
         }
     }
 
@@ -943,43 +1072,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 +1088,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 +1109,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 +1123,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 +1154,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) {
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index 2ab680e..8d0d21d 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -53,18 +53,63 @@
     #define IS_END_OF_STRING(glyph) glyph < 0
 #endif
 
+#define TEXTURE_BORDER_SIZE 1
+
 ///////////////////////////////////////////////////////////////////////////////
 // Declarations
 ///////////////////////////////////////////////////////////////////////////////
 
 class FontRenderer;
 
+/**
+ * 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() { }
-    CacheTexture(uint8_t* texture, uint16_t width, uint16_t height) :
-            mTexture(texture), mTextureId(0), mWidth(width), mHeight(height),
-            mLinearFiltering(false) { }
+    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;
@@ -72,35 +117,36 @@
         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);
+    }
+
+    bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
+
     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;
+    uint16_t mNumGlyphs;
+    CacheBlock* mCacheBlocks;
 };
 
 struct CachedGlyphInfo {
@@ -128,7 +174,7 @@
     // Auto-kerning
     SkFixed mLsbDelta;
     SkFixed mRsbDelta;
-    CacheTextureLine* mCachedTextureLine;
+    CacheTexture* mCacheTexture;
 };
 
 
@@ -180,12 +226,14 @@
         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);
+            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);
@@ -193,10 +241,11 @@
     // Cache of glyphs
     DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
 
-    void invalidateTextureCache(CacheTextureLine *cacheLine = NULL);
+    void invalidateTextureCache(CacheTexture *cacheTexture = NULL);
 
-    CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
-    void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph);
+    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,
@@ -210,7 +259,7 @@
     void drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset,
             SkPathMeasure& measure, SkPoint* position, SkVector* tangent);
 
-    CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit);
+    CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit, bool precaching = false);
 
     static glyph_t nextGlyph(const uint16_t** srcPtr) {
         const uint16_t* src = *srcPtr;
@@ -245,6 +294,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,7 +326,7 @@
     // 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();
@@ -294,17 +346,11 @@
 
     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 != NULL && cacheTexture->mTexture != NULL) {
+                size += cacheTexture->mWidth * cacheTexture->mHeight;
+            }
         }
         return size;
     }
@@ -319,7 +365,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 +375,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,
@@ -347,18 +392,13 @@
     uint32_t mSmallCacheWidth;
     uint32_t mSmallCacheHeight;
 
-    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;
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/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 65f8c7c..f81640b 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
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -233,9 +223,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);
 
@@ -431,7 +420,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 +449,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..8da9f66 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)
 
@@ -158,7 +157,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);
@@ -182,6 +180,7 @@
     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 +250,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();
 
@@ -314,6 +314,7 @@
     interrupt();
     detachFunctor(functor);
 
+    mCaches.enableScissor();
     if (mDirtyClip) {
         setScissorFromClip();
     }
@@ -321,13 +322,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 +440,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 +448,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 +508,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 +575,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 +602,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());
@@ -652,6 +646,7 @@
 #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);
@@ -825,7 +820,6 @@
 }
 
 void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
-#if RENDER_LAYERS_AS_REGIONS
     if (layer->region.isRect()) {
         layer->setRegionAsRect();
 
@@ -906,9 +900,6 @@
 
         layer->region.clear();
     }
-#else
-    composeLayerRect(layer, rect);
-#endif
 }
 
 void OpenGLRenderer::drawRegionRects(const Region& region) {
@@ -939,27 +930,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 +953,6 @@
             region->orSelf(dirty);
         }
     }
-#endif
 }
 
 void OpenGLRenderer::clearLayerRegions() {
@@ -982,7 +967,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 +995,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 +1052,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 +1089,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 +1114,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();
@@ -1171,6 +1178,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 +1309,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 +1400,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 +1565,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 +1596,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 +1603,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 +1677,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 +1701,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 +1723,6 @@
                 }
             }
         }
-#endif
 
         if (CC_LIKELY(pureTranslate)) {
             const float x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f);
@@ -1743,6 +1753,7 @@
         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;
@@ -1758,24 +1769,6 @@
         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;
 
@@ -1785,32 +1778,49 @@
     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)) {
+        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;
+
+        int widthSlot;
+        int lengthSlot;
+
+        float width = right - left;
+        float height = bottom - top;
+
+        float boundaryWidthProportion = .5 - ((width != 0) ? (2 * boundarySizeX) / width : 0);
+        float boundaryHeightProportion = .5 - ((height != 0) ? (2 * boundarySizeY) / height : 0);
+        setupDrawAALine((void*) aaVertices, widthCoords, lengthCoords,
+                boundaryWidthProportion, widthSlot, lengthSlot);
+
+        int boundaryLengthSlot = mCaches.currentProgram->getUniform("boundaryLength");
+        glUniform1f(boundaryLengthSlot, boundaryHeightProportion);
+
         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);
-    }
 
-    finishDrawAALine(widthSlot, lengthSlot);
+        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+        finishDrawAALine(widthSlot, lengthSlot);
+    }
 }
 
 /**
@@ -1882,6 +1892,9 @@
     }
 
     getAlphaAndMode(paint, &alpha, &mode);
+
+    mCaches.enableScissor();
+
     setupDraw();
     setupDrawNoTexture();
     if (isAA) {
@@ -1933,9 +1946,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
@@ -2012,7 +2023,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 +2049,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 +2122,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 +2263,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 +2321,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 +2329,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 +2342,7 @@
 
     mCaches.activeTexture(0);
     setupDraw();
+    setupDrawTextGamma(paint);
     setupDrawDirtyRegionsDisabled();
     setupDrawWithTexture(true);
     setupDrawAlpha8Color(paint->getColor(), alpha);
@@ -2302,33 +2355,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 +2409,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 +2422,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 +2435,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 +2450,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 +2487,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 +2497,7 @@
 
     mCaches.activeTexture(0);
     setupDraw();
+    setupDrawTextGamma(paint);
     setupDrawDirtyRegionsDisabled();
     setupDrawWithTexture(true);
     setupDrawAlpha8Color(paint->getColor(), alpha);
@@ -2485,24 +2510,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 +2551,8 @@
         return DrawGlInfo::kStatusDone;
     }
 
+    bool debugLayerUpdate = false;
+
     if (layer->deferredUpdateScheduled && layer->renderer && layer->displayList) {
         OpenGLRenderer* renderer = layer->renderer;
         Rect& dirty = layer->dirtyRect;
@@ -2546,6 +2568,8 @@
         layer->deferredUpdateScheduled = false;
         layer->renderer = NULL;
         layer->displayList = NULL;
+
+        debugLayerUpdate = mCaches.debugLayersUpdates;
     }
 
     mCaches.activeTexture(0);
@@ -2556,13 +2580,11 @@
 
     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;
 
             setupDraw();
             setupDrawWithTexture();
@@ -2574,12 +2596,12 @@
             setupDrawColorFilterUniforms();
             setupDrawTexture(layer->getTexture());
             if (CC_LIKELY(mSnapshot->transform->isPureTranslate())) {
-                x = (int) floorf(x + mSnapshot->transform->getTranslateX() + 0.5f);
-                y = (int) floorf(y + mSnapshot->transform->getTranslateY() + 0.5f);
+                int tx = (int) floorf(x + mSnapshot->transform->getTranslateX() + 0.5f);
+                int ty = (int) floorf(y + mSnapshot->transform->getTranslateY() + 0.5f);
 
                 layer->setFilter(GL_NEAREST);
-                setupDrawModelViewTranslate(x, y,
-                        x + layer->layer.getWidth(), y + layer->layer.getHeight(), true);
+                setupDrawModelViewTranslate(tx, ty,
+                        tx + layer->layer.getWidth(), ty + layer->layer.getHeight(), true);
             } else {
                 layer->setFilter(GL_LINEAR);
                 setupDrawModelViewTranslate(x, y,
@@ -2596,11 +2618,12 @@
             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 +2746,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 +2876,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 +2929,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..2369f47 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,9 +207,30 @@
 
     SkPaint* filterPaint(SkPaint* paint);
 
+    /**
+     * 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();
 
+    /**
+     * 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;
 
 protected:
@@ -213,6 +286,54 @@
      */
     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);
+
+    /**
+     * 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;
+        }
+    }
+
+    /**
+     * 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 +380,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 +391,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.
@@ -446,6 +566,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 +593,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 +609,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 +632,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 +647,7 @@
      * Invoked before any drawing operation. This sets required state.
      */
     void setupDraw(bool clear = true);
+
     /**
      * Various methods to setup OpenGL rendering.
      */
@@ -537,6 +660,7 @@
     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 +685,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 +695,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..6971d8a 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
@@ -278,13 +276,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..1818f82 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,10 @@
 #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
+
 ///////////////////////////////////////////////////////////////////////////////
 // Types
 ///////////////////////////////////////////////////////////////////////////////
@@ -94,14 +98,14 @@
  */
 struct ProgramDescription {
     enum ColorModifier {
-        kColorNone,
+        kColorNone = 0,
         kColorMatrix,
         kColorLighting,
         kColorBlend
     };
 
     enum Gradient {
-        kGradientLinear,
+        kGradientLinear = 0,
         kGradientCircular,
         kGradientSweep
     };
@@ -127,6 +131,7 @@
 
     bool hasGradient;
     Gradient gradientType;
+    bool isSimpleGradient;
 
     SkXfermode::Mode shadersMode;
 
@@ -146,6 +151,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.
@@ -165,6 +173,7 @@
 
         hasGradient = false;
         gradientType = kGradientLinear;
+        isSimpleGradient = false;
 
         shadersMode = SkXfermode::kClear_Mode;
 
@@ -180,6 +189,9 @@
 
         isPoint = false;
         pointSize = 0.0f;
+
+        hasGammaCorrection = false;
+        gamma = 2.2f;
     }
 
     /**
@@ -246,6 +258,8 @@
         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;
         return key;
     }
 
@@ -261,7 +275,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..8a9a2ac 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -65,25 +65,22 @@
 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_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 +88,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";
@@ -127,9 +129,7 @@
         "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";
@@ -137,13 +137,24 @@
         "uniform sampler2D sampler;\n";
 const char* gFS_Uniforms_ExternalTextureSampler =
         "uniform samplerExternalOES sampler;\n";
-const char* gFS_Uniforms_GradientSampler[3] = {
+#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 +170,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"
@@ -184,35 +203,46 @@
         "\nvoid main(void) {\n"
         "    gl_FragColor = texture2D(sampler, 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(sampler, outTexCoords).a, gamma));\n"
+        "}\n\n";
 const char* gFS_Fast_SingleModulateA8Texture =
         "\nvoid main(void) {\n"
         "    gl_FragColor = color * texture2D(sampler, 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(sampler, outTexCoords).a, gamma);\n"
         "}\n\n";
-const char* gFS_Fast_SingleModulateGradient =
+const char* gFS_Fast_SingleGradient[2] = {
         "\nvoid main(void) {\n"
-        "    gl_FragColor = color.a * texture2D(gradientSampler, linear);\n"
-        "}\n\n";
+        "    gl_FragColor = " FS_MAIN_DITHER " + texture2D(gradientSampler, linear);\n"
+        "}\n\n",
+        "\nvoid main(void) {\n"
+        "    gl_FragColor = " FS_MAIN_DITHER " + mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n"
+        "}\n\n"
+};
+const char* gFS_Fast_SingleModulateGradient[2] = {
+        "\nvoid main(void) {\n"
+        "    gl_FragColor " FS_MAIN_DITHER " + color.a * texture2D(gradientSampler, linear);\n"
+        "}\n\n",
+        "\nvoid main(void) {\n"
+        "    gl_FragColor " FS_MAIN_DITHER " + color.a * mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n"
+        "}\n\n"
+};
 
 // General case
 const char* gFS_Main_FetchColor =
         "    fragColor = color;\n";
 const char* gFS_Main_ModulateColor =
         "    fragColor *= color.a;\n";
+const char* gFS_Main_ModulateColor_ApplyGamma =
+        "    fragColor *= pow(color.a, gamma);\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_FetchTexture[2] = {
         // Don't modulate
         "    fragColor = texture2D(sampler, outTexCoords);\n",
@@ -225,15 +255,23 @@
         // Modulate
         "    fragColor = color * texture2D(sampler, outTexCoords).a;\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";
@@ -388,8 +426,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) {
@@ -423,13 +464,12 @@
         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
@@ -443,7 +483,7 @@
             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 ?
@@ -485,13 +525,12 @@
         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,11 +551,14 @@
         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 &&
@@ -544,16 +586,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;
         }
@@ -608,7 +658,8 @@
             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) {
@@ -643,7 +694,11 @@
             }
         }
         if (description.modulate && applyModulate) {
-            shader.append(gFS_Main_ModulateColor);
+            if (description.hasGammaCorrection) {
+                shader.append(gFS_Main_ModulateColor_ApplyGamma);
+            } else {
+                shader.append(gFS_Main_ModulateColor);
+            }
         }
         // Apply the color op if needed
         shader.append(gFS_Main_ApplyColorOp[description.colorOp]);
@@ -676,13 +731,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..6b6dc9e 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"
@@ -73,13 +77,30 @@
 #define PROPERTY_TEXT_CACHE_WIDTH "ro.hwui.text_cache_width"
 #define PROPERTY_TEXT_CACHE_HEIGHT "ro.hwui.text_cache_height"
 
-// 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"
+// 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"
 
-// TODO: This should be set by a system property
-#define PANEL_BIT_DEPTH 20
+// Gamma (>= 1.0, <= 10.0)
+#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..2153a8b 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -48,7 +48,8 @@
 
 void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) {
     Mutex::Autolock _l(mLock);
-    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+    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);
@@ -78,7 +79,8 @@
 
 void ResourceCache::decrementRefcount(void* resource) {
     Mutex::Autolock _l(mLock);
-    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+    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 decrement if we're not yet tracking it
         return;
@@ -111,12 +113,13 @@
 
 void ResourceCache::recycle(SkBitmap* resource) {
     Mutex::Autolock _l(mLock);
-    if (mCache->indexOfKey(resource) < 0) {
+    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->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+    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;
@@ -129,7 +132,8 @@
 
 void ResourceCache::destructor(SkPath* resource) {
     Mutex::Autolock _l(mLock);
-    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+    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 +150,8 @@
 
 void ResourceCache::destructor(SkBitmap* resource) {
     Mutex::Autolock _l(mLock);
-    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+    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 +168,8 @@
 
 void ResourceCache::destructor(SkiaShader* resource) {
     Mutex::Autolock _l(mLock);
-    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+    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 +183,8 @@
 
 void ResourceCache::destructor(SkiaColorFilter* resource) {
     Mutex::Autolock _l(mLock);
-    ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+    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;
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/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/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/packages/SystemUI/res/values-sw720dp-port/dimens.xml b/location/java/android/location/Geofence.aidl
similarity index 68%
copy from packages/SystemUI/res/values-sw720dp-port/dimens.xml
copy to location/java/android/location/Geofence.aidl
index 74b266d..a5c6aa0 100644
--- a/packages/SystemUI/res/values-sw720dp-port/dimens.xml
+++ b/location/java/android/location/Geofence.aidl
@@ -1,6 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (c) 2011, 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.
@@ -13,10 +12,8 @@
  * WITHOUT 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>
+ */
 
+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..bef363b 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,10 +991,6 @@
      * 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}.
      *
@@ -1080,22 +1005,66 @@
      * @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 no suitable permission is 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 no suitable permission is 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);
         }
     }
 
@@ -1104,44 +1073,122 @@
      *
      * @param intent the PendingIntent that no longer needs to be notified of
      * proximity alerts
+     *
+     * @throws IllegalArgumentException if intent is null
+     * @throws SecurityException if no suitable permission is 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 no suitable permission is 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 no suitable permission is 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 +1198,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 +1261,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 +1287,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 +1322,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 +1345,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 +1366,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 +1391,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 +1412,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 +1457,7 @@
             mNmeaBuffer = new ArrayList<Nmea>();
         }
 
+        @Override
         public void onGpsStarted() {
             if (mListener != null) {
                 Message msg = Message.obtain();
@@ -1375,6 +1466,7 @@
             }
         }
 
+        @Override
         public void onGpsStopped() {
             if (mListener != null) {
                 Message msg = Message.obtain();
@@ -1383,6 +1475,7 @@
             }
         }
 
+        @Override
         public void onFirstFix(int ttff) {
             if (mListener != null) {
                 mGpsStatus.setTimeToFirstFix(ttff);
@@ -1392,6 +1485,7 @@
             }
         }
 
+        @Override
         public void onSvStatusChanged(int svCount, int[] prns, float[] snrs,
                 float[] elevations, float[] azimuths, int ephemerisMask,
                 int almanacMask, int usedInFixMask) {
@@ -1407,6 +1501,7 @@
             }
         }
 
+        @Override
         public void onNmeaReceived(long timestamp, String nmea) {
             if (mNmeaListener != null) {
                 synchronized (mNmeaBuffer) {
@@ -1563,7 +1658,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 +1675,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 +1686,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/packages/SystemUI/res/values-sw720dp-port/dimens.xml b/location/java/android/location/LocationRequest.aidl
similarity index 68%
copy from packages/SystemUI/res/values-sw720dp-port/dimens.xml
copy to location/java/android/location/LocationRequest.aidl
index 74b266d..b1a8647 100644
--- a/packages/SystemUI/res/values-sw720dp-port/dimens.xml
+++ b/location/java/android/location/LocationRequest.aidl
@@ -1,6 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (c) 2011, 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.
@@ -13,10 +12,8 @@
  * WITHOUT 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>
+ */
 
+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/packages/SystemUI/res/values-sw720dp-port/dimens.xml b/location/java/com/android/internal/location/ProviderProperties.aidl
similarity index 68%
copy from packages/SystemUI/res/values-sw720dp-port/dimens.xml
copy to location/java/com/android/internal/location/ProviderProperties.aidl
index 74b266d..b901444 100644
--- a/packages/SystemUI/res/values-sw720dp-port/dimens.xml
+++ b/location/java/com/android/internal/location/ProviderProperties.aidl
@@ -1,6 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (c) 2011, 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.
@@ -13,10 +12,8 @@
  * WITHOUT 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>
+ */
 
+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/cmds/sensorservice/main_sensorservice.cpp b/location/java/com/android/internal/location/ProviderRequest.aidl
similarity index 69%
copy from cmds/sensorservice/main_sensorservice.cpp
copy to location/java/com/android/internal/location/ProviderRequest.aidl
index 8610627..4e1ea95 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/location/java/com/android/internal/location/ProviderRequest.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,12 +14,6 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+package com.android.internal.location;
 
-using namespace android;
-
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
-}
+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..b5613f3 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;
         }
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 2e153dd..c98fcd3 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -143,11 +143,12 @@
     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
 
     // flags for MSG_PERSIST_VOLUME indicating if current and/or last audible volume should be
@@ -381,7 +382,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;
@@ -438,7 +439,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);
@@ -1701,7 +1702,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() */
@@ -2875,7 +2882,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 +3056,7 @@
                     break;
 
                 case MSG_SET_FORCE_USE:
+                case MSG_SET_FORCE_BT_A2DP_USE:
                     setForceUse(msg.arg1, msg.arg2);
                     break;
 
@@ -3286,7 +3294,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) {
@@ -3652,9 +3662,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);
             }
         }
     }
@@ -4014,7 +4025,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;
         }
@@ -4646,17 +4657,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 +5324,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);
         }
     }
 
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/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index 687d3a5..4b8d3cb 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;
@@ -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..2d1be02 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -720,12 +720,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 +745,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 6f8b809..0d7b45e 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);
             }
 
@@ -1447,24 +1463,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/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/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/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/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..875d2c9 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -153,4 +153,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..2785991 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -38,7 +38,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;
@@ -65,7 +64,7 @@
     // 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 = 81;
 
     private Context mContext;
 
@@ -1119,6 +1118,33 @@
             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;
+        }
+
         // *** Remember to update DATABASE_VERSION above!
 
         if (upgradeVersion != currentVersion) {
@@ -1706,8 +1732,12 @@
             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);
@@ -1717,6 +1747,17 @@
 
             loadIntegerSetting(stmt, Settings.Secure.WIFI_MAX_DHCP_RETRY_COUNT,
                     R.integer.def_max_dhcp_retries);
+
+            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);
         } finally {
             if (stmt != null) stmt.close();
         }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index 18e7faa..9208cae 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -109,7 +109,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/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 10849f6..b185471 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -15,6 +15,8 @@
     <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" />
+
     <!-- Networking and telephony -->
     <uses-permission android:name="android.permission.BLUETOOTH" />
     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
@@ -40,6 +42,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 +53,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 +97,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 +143,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"
@@ -157,5 +179,17 @@
 <!--            <category android:name="android.intent.category.LAUNCHER" />-->
             </intent-filter>
         </activity>
+
+        <!-- Beans in space -->
+        <service
+            android:name=".BeanBagDream"
+            android:exported="true"
+            android:label="Beans in space">
+            <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>
     </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-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/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/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-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/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..c4b881e
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings.xml
@@ -0,0 +1,45 @@
+<?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"
+    >
+    <ImageView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:scaleType="centerInside"
+        android:src="@drawable/qs_coming_soon"
+        android:padding="4dp"
+        android:background="#80000080"
+        />
+    <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/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 5841978..8eff1f4 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -18,12 +18,12 @@
 */
 -->
 
-<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"
@@ -42,9 +42,10 @@
 
     <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,7 +66,7 @@
         <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="always"
             >
@@ -78,19 +79,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-port/status_bar_recent_item.xml b/packages/SystemUI/res/layout/status_bar_recent_item.xml
similarity index 97%
rename from packages/SystemUI/res/layout-port/status_bar_recent_item.xml
rename to packages/SystemUI/res/layout/status_bar_recent_item.xml
index ca72530..50643ab 100644
--- a/packages/SystemUI/res/layout-port/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout/status_bar_recent_item.xml
@@ -38,7 +38,7 @@
             android:fadingEdgeLength="@dimen/status_bar_recents_text_fading_edge_length"
             android:scrollHorizontally="true"
             android:layout_alignParentLeft="true"
-            android:layout_alignTop="@id/app_icon"
+            android:layout_alignTop="@+id/app_icon"
             android:paddingTop="2dp"
             android:layout_marginLeft="@dimen/status_bar_recents_app_label_left_margin"
             android:singleLine="true"
@@ -71,7 +71,7 @@
             android:background="@drawable/recents_callout_line"
         />
 
-        <ImageView android:id="@+id/app_icon"
+        <ImageView android:id="@id/app_icon"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_toRightOf="@id/app_label"
diff --git a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml b/packages/SystemUI/res/layout/status_bar_recent_panel.xml
similarity index 86%
rename from packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
rename to packages/SystemUI/res/layout/status_bar_recent_panel.xml
index a7e5db1..7335f86 100644
--- a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout/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"
@@ -38,12 +33,6 @@
         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"
diff --git a/packages/SystemUI/res/layout-port/status_bar_search_panel.xml b/packages/SystemUI/res/layout/status_bar_search_panel.xml
similarity index 97%
rename from packages/SystemUI/res/layout-port/status_bar_search_panel.xml
rename to packages/SystemUI/res/layout/status_bar_search_panel.xml
index 1e4bb57..b871bef 100644
--- a/packages/SystemUI/res/layout-port/status_bar_search_panel.xml
+++ b/packages/SystemUI/res/layout/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/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 5bf1a58..ad6b8f4 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="wrap_content"
+            />
+        <include layout="@layout/quick_settings"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            />
+    </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/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index a24a4d7..d5e4c0a 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Sien"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Gebruik by verstek vir hierdie USB-toestel"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Gebruik by verstek vir hierdie USB-toebehoorsel"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Moet USB-ontfouting toegelaat word?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Moet USB-ontfouting van hierdie rekenaar af toegelaat word?"\n"Jou RSA-sleutelvingerafdruk is"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Laat altyd hierdie rekenaar toe"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoem om skerm te vul"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Strek om skerm te vul"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Versoenbaarheidszoem"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 7c2956c..36b52e3 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -56,8 +56,11 @@
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"ምንም የተጫኑ መተግበሪያዎች ከዚህ የUSB ተቀጥላ ጋር አይሰሩም። በ<xliff:g id="URL">%1$s</xliff:g> ስለዚህ ተቀጥላ የበለጠ ለመረዳት።"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"የUSB  ተቀጥላ"</string>
     <string name="label_view" msgid="6304565553218192990">"ዕይታ"</string>
-    <string name="always_use_device" msgid="1450287437017315906">"ለዚህ USB  መሣሪያ በነባሪነት ተጠቀም"</string>
-    <string name="always_use_accessory" msgid="1210954576979621596">"ለዚህ USB  ተቀጥላ በነባሪነት ተጠቀም"</string>
+    <string name="always_use_device" msgid="1450287437017315906">"ለእዚህ USB  መሣሪያ በነባሪነት ተጠቀም"</string>
+    <string name="always_use_accessory" msgid="1210954576979621596">"ለእዚህ USB  ተቀጥላ በነባሪነት ተጠቀም"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"የUSB ማረሚያ ይፈቀድ?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"የUSB ማረም ከዚህ ኮምፒውተር ይፈቀድ?"\n"የእርስዎ RSA ቁልፍ ጣት አሻራ "\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g> ነው"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"ለዚህ ኮምፒውተር ሁልጊዜ ፍቀድ"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"ማያ እንዲሞላ አጉላ"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"ማያ ለመሙለት ሳብ"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"የተኳኋኝነት አጉላ"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index b2c9ab0..6540f0a 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="1114766024068112429">"هل تريد السماح بتصحيح أخطاء USB؟"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"هل تريد السماح بتصحيح أخطاء USB من هذا الكمبيوتر؟"\n"ملفك المرجعي لمفتاح RSA هو"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"السماح لهذا الكمبيوتر دومًا"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"تكبير/تصغير لملء الشاشة"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"توسيع بملء الشاشة"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"تكبير/تصغير التوافق"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index c4af8d8..8216e2b 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Прагляд"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Выкарыстоўваць налады па змаўчанні для дадзенай USB-прылады"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Выкарыстоўваць налады па змаўчанні для дадзенай USB-прылады"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Дазволіць адладку USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Дазволіць USB-адладку з гэтага камп\'ютара?"\n"Ваш адбiтак ключа RSA"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Дазваляць гэтаму камп\'ютару"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Павял. на ўвесь экран"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Расцягн. на ўвесь экран"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Маштабаванне для сумяшчальнасцi"</string>
@@ -142,6 +145,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index a4a0e78..56b8bb3 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Преглед"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Използване по подразб. за това USB устройство"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Използване по подразб. за този аксесоар за USB"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Да се разреши ли отстраняването на грешки през USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Да се разреши ли отстраняването на грешки през USB от този компютър?"\n"Отпечатъкът на вашия RSA ключ е"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Този компютър винаги да е разрешен"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Мащаб – запълва екрана"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Разпъване – запълва екрана"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Промяна на мащаба за съвместимост"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 5a2c9cd..3eb078d 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Mostra"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Utilitza de manera predet. per al dispositiu USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Utilitza de manera predet. per a l\'accessori USB"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Vols permetre la depuració USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Vols permetre la depuració USB des d\'aquest equip?"\n"L\'empremta de la teva clau RSA és"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Dóna sempre permís a aquest equip"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom per omplir pantalla"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Estira per omplir pant."</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilitat"</string>
@@ -142,6 +145,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 2d1f644..a7bf519 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Zobrazit"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Pro toto zařízení USB použít jako výchozí"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Pro toto periferní zařízení USB použít jako výchozí"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Povolit ladění USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Povolit ladění USB z tohoto počítače?"\n"Váš digitální otisk klíče RSA je"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Vždy povolit tento počítač."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Přiblížit na celou obrazovku"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Na celou obrazovku"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Úprava velikosti z důvodu kompatibility"</string>
@@ -142,6 +145,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 01068ec..48cab36 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Vis"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Brug som standard til denne USB-enhed"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Brug som standard til dette USB-tilbehør"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Vil du tillade USB-fejlretning?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Vil du tillade USB-fejlretning fra denne computer?"\n"Dit fingeraftryk for RSA-nøglen er"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Tillad altid denne computer"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom til fuld skærm"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Stræk til fuld skærm"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Kompatibilitetszoom"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 011d3a3..4bcbc31 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Anzeigen"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Standardmäßig für dieses USB-Gerät verwenden"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Standardmäßig für dieses USB-Zubehör verwenden"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"USB-Debugging zulassen?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"USB-Debugging auf diesem Computer zulassen?"\n"Ihr Fingerabdruck des RSA-Schlüssels lautet"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>."</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Auf diesem Computer immer zulassen"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom auf Bildschirmgröße"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Auf Bildschirmgröße anpassen"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Kompatibilitätszoom"</string>
@@ -142,6 +145,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 0b87777..2231a8c 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Προβολή"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Χρήση από προεπιλογή για αυτή τη συσκευή USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Χρήση από προεπιλογή για αυτό το εξάρτημα USB"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Να επιτρέπεται ο εντοπισμός σφαλμάτων USB;"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Να επιτρέπεται ο εντοπισμός σφαλμάτων USB από αυτόν τον υπολογιστή;"\n"Το αποτύπωμα κλειδιού σας RSA είναι"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Να επιτρέπεται πάντα σε αυτόν τον υπολογιστή"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Ζουμ σε πλήρη οθόνη"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Προβoλή σε πλήρη οθ."</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Ζουμ για συμβατότητα"</string>
@@ -142,6 +145,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index f02d09ca..671ac1b 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"View"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Use by default for this USB device"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Use by default for this USB accessory"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Allow USB Debugging?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Allow USB Debugging from this computer?"\n"Your RSA key fingerprint is"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Always allow this computer"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom to fill screen"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Stretch to fill screen"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Compatibility zoom"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index be2bf6e..87b0088 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Ver"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Se usa de forma predeterminada para este dispositivo USB."</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Se usa de forma predeterminada para este accesorio USB."</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"¿Permitir la depuración de USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"¿Quieres permitir la depuración de USB desde esta computadora?"\n"La huella digital de tu clave RSA es:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Permitir el uso de esta computadora siempre"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom para ocupar la pantalla"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Estirar p/ ocupar la pantalla"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilidad"</string>
@@ -142,6 +145,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index afbceff..cd03d92 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Ver"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Usar de forma predeterminada para este dispositivo USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Usar de forma predeterminada para este accesorio USB"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"¿Permitir depuración USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"¿Quieres permitir la depuración USB en este ordenador?"\n"La huella digital de tu clave RSA es:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Permitir siempre en este ordenador"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom para ajustar"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Expandir para ajustar"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilidad"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 318ed04..4348bda 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Kuva"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Kasuta vaikimisi selle USB-seadme jaoks"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Vaikimisi kasuta seda USB-lisaseadet"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Kas lubada USB-silumine?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Kas lubada USB-silumine sellest arvutist?"\n"Teie RSA-võtme sõrmejälg on"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Luba alati see arvuti"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Suumi ekraani täitmiseks"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Venita ekraani täitmiseks"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Sobivussuum"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 104ab038..66d65d9 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,26 @@
     <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>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"اشکال‌زدایی USB انجام شود؟"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"اشکال‌زدایی USB از این رایانه مجاز باشد؟"\n"اثر انگشت کلید RSA شما"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"این رایانه همیشه مجاز است"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"بزرگنمایی برای پر کردن صفحه"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"گسترده کردن برای پر کردن صفحه"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"بزرگنمایی سازگاری"</string>
-    <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,7 +72,7 @@
     <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="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>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index a4229b4..5132502 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Näytä"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Käytä oletuksena tällä USB-laitteella"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Käytä oletuksena tällä USB-lisälaitteella"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Sallitaanko USB-vianetsintä?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Sallitaanko USB-vianetsintä tällä tietokoneella?"\n"RSA-avaimesi sormenjälki on"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Salli vianetsintä tällä tietokoneella aina"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoomaa koko näyttöön"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Venytä koko näyttöön"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Yhteensopivuuszoomaus"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 30b3539..18f8c9d 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Afficher"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Utiliser par défaut pour ce périphérique USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Utiliser par défaut pour cet accessoire USB"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Autoriser le débogage USB ?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Autoriser le débogage USB via cet ordinateur ?"\n"Votre empreinte de clé RSA est "\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>."</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Toujours autoriser cet ordinateur"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoomer pour remplir l\'écran"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Étirer pour remplir l\'écran"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilité"</string>
@@ -135,13 +138,14 @@
     <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>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index aae070a..cfc0aec 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"देखें"</string>
     <string name="always_use_device" msgid="1450287437017315906">"इस USB उपकरण के लिए डिफ़ॉल्‍ट रूप से उपयोग करें"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"इस USB एसेसरी के लिए डिफ़ॉल्‍ट रूप से उपयोग करें"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"USB डीबगिंग करने दें?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"इस कंप्यूटर से USB डीबगिंग करने दें?"\n"आपका RSA कुंजी फ़िंगरप्रिंट यह है:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"इस कंप्यूटर को हमेशा अनुमति दें"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"स्‍क्रीन भरने हेतु ज़ूम करें"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"स्‍क्रीन को भरने के लिए खींचें"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"संगतता ज़ूम"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 4a1f35a..7150c94 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Prikaži"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Koristi se prema zadanim postavkama za ovaj USB uređaj"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Koristi se prema zadanim postavkama za ovaj USB pribor"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Omogućiti USB Debugging?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Omogućiti USB Debugging na ovom računalu?"\n"Vaš je otisak prsta RSA ključa"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Uvijek dopusti ovom računalu"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zumiraj i ispuni zaslon"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Rastegni i ispuni zaslon"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Kompatibilno zumiranje"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 2ea0f76..4d49939 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Megtekintés"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Alapértelmezett használat ehhez az USB-eszközhöz"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Alapértelmezett használat ehhez az USB-kiegészítőhöz"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Engedélyezi az USB hibakeresést?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Engedélyezi az USB hibakeresést erről a számítógépről?"\n"Az Ön RSA-kulcs ujjlenyomata"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Mindig legyen engedélyezve ezen a számítógépen"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Nagyítás a kitöltéshez"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Nyújtás kitöltéshez"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Kompatibilitás -- nagyítás/kicsinyítés"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index a69fc23..65e47dd 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Lihat"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Gunakan secara default untuk perangkat USB ini"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Gunakan secara default untuk aksesori USB ini"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Izinkan Debugging USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Izinkan Debugging USB dari komputer ini?"\n"Sidik jari kunci RSA Anda adalah"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Selalu izinkan komputer ini"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Perbesar utk mengisi layar"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Rentangkn utk mngisi layar"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Perbesar/perkecil untuk kompatibilitas"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 432d984..49b0fb0 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Visualizza"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Usa per impostazione predef. per dispositivo USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Usa per impostazione predef. per accessorio USB"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Consentire debug USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Consentire il debug USB da questo computer? "\n"La fingerprint della tua chiave RSA è "\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Consenti sempre da questo computer"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom per riempire schermo"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Estendi per riemp. schermo"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom compatibilità"</string>
@@ -142,6 +145,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index bdc84b6..f820464 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"הצג"</string>
     <string name="always_use_device" msgid="1450287437017315906">"השתמש כברירת מחדל עבור מכשיר USB זה"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"השתמש כברירת מחדל עבור אביזר USB זה"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"האם לאפשר ניפוי באגים ב-USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"האם להרשות ניפוי באגים ב-USB ממחשב זה?"\n"טביעת האצבע של מפתח ה-RSA שלך היא"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"הרשה תמיד במחשב זה"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"הגדל תצוגה כדי למלא את המסך"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"מתח כדי למלא את המסך"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"שינוי מרחק מתצוגה לצורך תאימות"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 70ba034..a9fe4ae 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"表示"</string>
     <string name="always_use_device" msgid="1450287437017315906">"このUSBデバイスにデフォルトで使用する"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"このUSBアクセサリにデフォルトで使用する"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"USBデバッグを許可しますか?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"このパソコンからのUSBデバッグを許可しますか?"\n"RSAキーのフィンガープリントは次のとおりです"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"このパソコンを常に許可する"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"画面サイズに合わせて拡大"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"画面サイズに合わせて拡大"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"互換ズーム"</string>
@@ -142,6 +145,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index e54b06c..bd1cf03 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"보기"</string>
     <string name="always_use_device" msgid="1450287437017315906">"이 USB 기기에 기본값으로 사용"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"이 USB 액세서리에 기본값으로 사용"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"USB 디버깅을 허용하시겠습니까?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"이 컴퓨터에서 USB 디버깅을 허용하시겠습니까?"\n"귀하의 RSA 키 지문 파일은 다음과 같습니다."\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"이 컴퓨터에서 항상 허용"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"전체화면 모드로 확대"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"전체화면 모드로 확대"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"호환성 확대/축소"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 018b5e5..a5a11e2 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Žiūrėti"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Šiam USB įreng. naudoti pagal numat. nustatymus"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Šiam USB priedui naudoti pagal numat. nustatymus"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Leisti derinti USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Leisti derinti USB šiuo kompiuteriu?"\n"RSA rakto kontrolinis kodas yra"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Visada leisti šį kompiuterį"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Keisti mast., kad atit. ekr."</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Ištempti, kad atit. ekr."</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Suderinamumo mastelio keitimas"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index e708804..c18b03f 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Skatīt"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Pēc noklusējuma izmantot šai USB ierīcei"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Pēc noklusējuma izmantot šim USB piederumam"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Vai atļaut USB atkļūdošanu?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Vai atļaut USB atkļūdošanu no šī datora?"\n"Jūsu RSA atslēgas identifikators ir"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Vienmēr atļaut no šī datora"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Tālumm., lai aizp. ekr."</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Stiepiet, lai aizp. ekr."</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Saderības tālummaiņa"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 3265cd5..ef926ac 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Lihat"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Gunakan secara lalai untuk peranti USB ini"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Gunakan secara lalai untuk aksesori USB ini"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Benarkan penyahpepijatan USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Benarkan Penyahpepijatan USB dari komputer ini?"\n"Cap jari kunci RSA anda ialah"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Sentiasa benarkan komputer ini"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zum untuk memenuhi skrin"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Regang utk memenuhi skrin"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zum keserasian"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index a1ee469..e7005fa 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Vis"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Bruk som standard for denne USB-enheten"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Bruk som standard for dette USB-tilbehøret"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Vil du tillate USB-feilsøking?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Vil du tillate USB-feilsøking fra denne datamaskinen?"\n"Nøkkelfingeravtrykket ditt for RSA er"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Gi alltid tillatelse til denne datamaskinen"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom for å fylle skjermen"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Strekk for å fylle skjerm"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Kompatibilitets-zooming"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 936e0958..d5e8444 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Weergeven"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Standaard gebruiken voor dit USB-apparaat"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Standaard gebruiken voor dit USB-accessoire"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"USB-foutopsporing toestaan?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"USB-foutopsporing toestaan vanaf deze computer?"\n"Uw RSA-sleutelvingerafdruk is"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Deze computer altijd toestaan"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom om scherm te vullen"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Rek uit v. schermvulling"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Compatibiliteitszoom"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index b4a77a2..7639c84 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Wyświetl"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Używaj domyślnie dla tego urządzenia USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Używaj domyślnie dla tego akcesorium USB"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Zezwalać na debugowanie USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Zezwalać na debugowanie USB z tego komputera?"\n"Twój odcisk cyfrowy klucza RSA to"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Zawsze zezwalaj dla tego komputera"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Powiększ, aby wypełnić ekran"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Rozciągnij, aby wypełnić ekran"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Powiększenie w trybie zgodności"</string>
@@ -140,6 +143,7 @@
     <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>
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..4b41ca0 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="1114766024068112429">"Permitir Depuração USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Permitir a Depuração USB a partir deste computador?"\n"A sua pegada digital da chave RSA é"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Permitir sempre este 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>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 596ceec..b88e096 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Visualizar"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Usar por padrão para este dispositivo USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Usar por padrão para este acessório USB"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Permitir a depuração USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Permitir a depuração USB a partir deste computador?"\n"A impressão digital de sua chave RSA é"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Sempre permitir este computador"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom p/ preencher a tela"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Ampliar p/ preencher tela"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom em modo de compatibilidade"</string>
@@ -142,6 +145,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 16e5719..ea88ddd 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -86,6 +86,12 @@
     <skip />
     <!-- no translation found for always_use_accessory (1210954576979621596) -->
     <skip />
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <!-- no translation found for compat_mode_on (6623839244840638213) -->
     <skip />
     <!-- no translation found for compat_mode_off (4434467572461327898) -->
@@ -250,6 +256,8 @@
     <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) -->
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 87eec9f..c7dff3a 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Afişaţi"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Utilizaţi în mod prestabilit pt. acest dispoz. USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Utiliz. în mod prestabilit pt. acest accesoriu USB"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Permiteţi depanarea USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Permiteţi depanarea USB de pe acest computer?"\n"Amprenta digitală din cheia RSA este"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Permiteţi întotdeauna de pe acest computer"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom pt. a umple ecranul"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Înt. pt. a umple ecranul"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilitate"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 7a7d08f..d435670 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -25,7 +25,7 @@
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Показать уведомления"</string>
     <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Удаление из списка"</string>
     <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"О приложении"</string>
-    <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"Нет данных"</string>
+    <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"В последнее время вы не запускали приложения."</string>
     <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Закрыть недавние приложения"</string>
   <plurals name="status_bar_accessibility_recent_apps">
     <item quantity="one" msgid="5854176083865845541">"Недавних приложений: 1"</item>
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Просмотр"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Использовать по умолчанию для этого USB-устройства"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Использовать по умолчанию для этого USB-аксессуара"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Разрешить отладку по USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Разрешить отладку по USB с этого компьютера?"\n"Контрольная сумма ключа RSA:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Всегда разрешать отладку с этого компьютера"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Подогнать по размерам экрана"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Растянуть на весь экран"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Масштаб и совместимость"</string>
@@ -135,13 +138,14 @@
     <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>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 8e64487..b57afe3 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Zobraziť"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Pre toto zariadenie USB použiť ako predvolené"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Pre toto periférne zar. USB použiť ako predvolené"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Chcete povoliť ladenie USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Chcete povoliť ladenie USB z tohto počítača?"\n"Digitálny odtlačok vášho kľúča RSA je"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Vždy povoliť v tomto počítači"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Priblížiť na celú obrazovku"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Na celú obrazovku"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Úprava veľkosti z dôvodu kompatibility"</string>
@@ -142,6 +145,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 1fa3b21..1bed89b 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Prikaži"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Privzeto uporabi za to napravo USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Privzeto uporabi za ta dodatek USB"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Ali dovolite odpravljanje težav s povezavo USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Ali dovolite odpravljanje težav s povezavo USB v tem računalniku?"\n"Prstni odtis ključa RSA je"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Vedno dovoli za ta računalnik"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Povečava čez cel zaslon"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Raztegnitev čez zaslon"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Razširitev združljivosti"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index fd41e02..5dbbbb4 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Прикажи"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Користи подразумевано за овај USB уређај"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Користи подразумевано за овај USB додатак"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Желите ли да дозволите отклањање USB грешака?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Желите ли да дозволите отклањање USB грешака са овог рачунара?"\n"Дигитални отисак RSA кључа је"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Увек дозволи овај рачунар"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Зумирај на целом екрану"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Развуци на цео екран"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Компатибилно зумирање"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index afbe0fb..f09dc2a 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Visa"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Använd som standard för den här USB-enheten"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Använd som standard för det här USB-tillbehöret"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Ska USB-felsökning tillåtas?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Vill du tillåta USB-felsökning från den här datorn?"\n"Din RSA-fingeravtrycksnyckel är"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Tillåt alltid för den här datorn"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zooma för att fylla skärm"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Dra för att fylla skärmen"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom i kompatibilitetsläge"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 8f22b81c..768b1c8 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -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="1114766024068112429">"Ruhusu Utatuaji USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Ruhusu Utatuaji wa USB kutoka kwenye kompyuta hii?"\n"Kitufe chako RSA cha alama ya kidole ni "\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Ruhusu kompyuta hii kila wakati"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Kuza ili kujaza skrini"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Tanua ili kujaza skrini"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Kukuza kwa Utangamanifu"</string>
@@ -138,6 +141,7 @@
     <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>
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/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/config.xml b/packages/SystemUI/res/values-sw720dp/config.xml
index 8af700a..de63d9f 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) -->
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..fb06e1a 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"ดู"</string>
     <string name="always_use_device" msgid="1450287437017315906">"ใช้ค่าเริ่มต้นสำหรับอุปกรณ์ USB นี้"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"ใช้ค่าเริ่มต้นสำหรับอุปกรณ์เสริม USB นี้"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"อนุญาตการแก้ไขข้อบกพร่องของ USB หรือไม่"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"อนุญาตการแก้ไขข้อบกพร่องของ USB จากคอมพิวเตอร์เครื่องนี้หรือไม่"\n"ลายนิ้วมือคีย์ RSA ของคุณคือ"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"อนุญาตคอมพิวเตอร์เครื่องนี้เสมอ"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"ขยายจนเต็มหน้าจอ"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"ยืดจนเต็มหน้าจอ"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"ความเข้ากันได้ของการย่อ/ขยาย"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index e1c4185..ad601c9 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Tingnan"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Gamitin bilang default para sa USB device"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Gamitin bilang default sa USB accessory na ito"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Payagan ang Pag-debug ng USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Payagan ang Pag-debug ng USB mula sa computer na ito?"\n"Ang iyong RSA key fingerprint ay"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Palaging payagan ang computer na ito"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"I-zoom upang punan screen"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"I-stretch upang mapuno screen"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom sa pagiging Tugma"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 9bf8f76..c4c64d9 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Görüntüle"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Bu USB cihazı için varsayılan olarak kullan"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Bu USB aksesuar için varsayılan olarak kullan"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"USB Hata Ayıklama işlemine izin verilsin mi?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Bu bilgisayardan USB Hata Ayıklama işlemine izin verilsin mi?"\n"RSA anahtarı parmak iziniz:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Bu bilgisayara her zaman izin ver"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Yakınlaştır (ekranı kaplasın)"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Genişlet (ekran kapansın)"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Uyumluluk yakınlaştırması"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 165baae..973c6bc 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Переглянути"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Використовувати за умовчанням для пристрою USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Використовувати за умовчанням для аксесуара USB"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Дозволити налагодження USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Дозволити налагодження USB на цьому комп’ютері?"\n"Цифровий відбиток вашого ключа RSA:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Завжди дозволяти цьому комп’ютеру"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Масштабув. на весь екран"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Розтягнути на весь екран"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Масштабування для сумісності"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index eef2c83..f9d2b3c 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Xem"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Sử dụng theo mặc định cho thiết bị USB này"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Sử dụng theo mặc định cho phụ kiện USB này"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Cho phép gỡ lỗi USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Cho phép gỡ lỗi USB từ máy tính này?"\n"Dấu tay khóa RSA của bạn là"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Luôn cho phép máy tính này"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"T.phóng để lấp đầy m.hình"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Giãn ra để lấp đầy m.hình"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Thu phóng tương thích"</string>
@@ -140,6 +143,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index ca29738..408f861 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"查看"</string>
     <string name="always_use_device" msgid="1450287437017315906">"默认情况下用于该 USB 设备"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"默认情况下用于该 USB 配件"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"是否允许 USB 调试?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"是否允许在此计算机上进行 USB 调试?"\n"您的 RSA 密钥指纹是"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"始终允许在此计算机上进行 USB 调试"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"缩放以填满屏幕"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"拉伸以填满屏幕"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"兼容性缩放"</string>
@@ -142,6 +145,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 8fa4af9..debdb1c 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"查看"</string>
     <string name="always_use_device" msgid="1450287437017315906">"預設用於這個 USB 裝置"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"預設用於這個 USB 配件"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"允許 USB 偵錯嗎?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"允許透過這台電腦進行 USB 偵錯嗎?"\n"您的 RSA 金鑰指紋如下"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"一律允許這台電腦"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"放大為全螢幕"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"放大為全螢幕"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"相容性縮放"</string>
@@ -142,6 +145,7 @@
     <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>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 4f3e787..f31a11e 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Buka"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Sebenzisa ngokuzenzakalelayo yale divayisi ye-USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Sebenzisa ngokuzenzakalelayo kule-accessory ye-USB"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Vumela ukulungisa iphutha le-USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Vumela isa ukulung-USB Debugging kusuka kule khompyutha?"\n"Izigxivizo zakho zeminwe zokhiye we-RSA ngu-"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Hlala uvumela le khompyutha"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Sondeza ukugcwalisa isikrini"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Nweba ukugcwalisa isikrini"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Ukuhambelana Kokusondeza"</string>
@@ -140,6 +143,7 @@
     <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>
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 26dba67..3337573 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -65,5 +65,16 @@
 
     <!-- Vibration duration for MultiWaveView used in SearchPanelView -->
     <integer translatable="false" name="config_search_panel_view_vibration_duration">20</integer>
+
+    <!-- The length of the vibration when the notificaiotn pops open. -->
+    <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>
 </resources>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 6c40461..0d7cdb1 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,10 +161,17 @@
     <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="one_finger_pop_limit">32dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 8ebbc52..4a73200 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -18,4 +18,5 @@
 <resources>
     <item type="id" name="expandable_tag" />
     <item type="id" name="user_expanded_tag" />
+    <item type="id" name="user_lock_tag" />
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index f18e33e..5747f22 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -154,6 +154,15 @@
     <!-- Checkbox label for USB accessory dialogs.  [CHAR LIMIT=50] -->
     <string name="always_use_accessory">Use by default for this USB accessory</string>
 
+    <!-- Title of confirmation dialog for USB debugging -->
+    <string name="usb_debugging_title">Allow USB Debugging?</string>
+
+    <!-- Message of confirmation dialog for USB debugging -->
+    <string name="usb_debugging_message">Allow USB Debugging from this computer?\nYour RSA key fingerprint is\n<xliff:g id="fingerprint">%1$s</xliff:g></string>
+
+    <!-- Option to always allow USB debugging from the attached computer -->
+    <string name="usb_debugging_always">Always allow this computer</string>
+
     <!-- Checkbox label for application compatibility mode ON (zooming app to look like it's running
          on a phone).  [CHAR LIMIT=25] -->
     <string name="compat_mode_on">Zoom to fill screen</string>
@@ -370,6 +379,9 @@
          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>
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 5dd15c3..674d9a3 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -22,24 +22,31 @@
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.content.Context;
+import android.os.Vibrator;
 import android.util.Slog;
 import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.ScaleGestureDetector;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.View.OnClickListener;
 
+import java.util.Stack;
+
 public class ExpandHelper implements Gefingerpoken, OnClickListener {
     public interface Callback {
         View getChildAtRawPosition(float x, float y);
         View getChildAtPosition(float x, float y);
         boolean canChildBeExpanded(View v);
-        boolean setUserExpandedChild(View v, boolean userxpanded);
+        boolean setUserExpandedChild(View v, boolean userExpanded);
+        boolean setUserLockedChild(View v, boolean userLocked);
     }
 
     private static final String TAG = "ExpandHelper";
     protected static final boolean DEBUG = false;
+    protected static final boolean DEBUG_SCALE = false;
+    protected static final boolean DEBUG_GLOW = false;
     private static final long EXPAND_DURATION = 250;
     private static final long GLOW_DURATION = 150;
 
@@ -63,6 +70,9 @@
     private Context mContext;
 
     private boolean mStretching;
+    private boolean mPullingWithOneFinger;
+    private boolean mWatchingForPull;
+    private boolean mHasPopped;
     private View mEventSource;
     private View mCurrView;
     private View mCurrViewTopGlow;
@@ -70,7 +80,12 @@
     private float mOldHeight;
     private float mNaturalHeight;
     private float mInitialTouchFocusY;
+    private float mInitialTouchY;
     private float mInitialTouchSpan;
+    private int mTouchSlop;
+    private int mLastMotionY;
+    private float mPopLimit;
+    private int mPopDuration;
     private Callback mCallback;
     private ScaleGestureDetector mDetector;
     private ViewScaler mScaler;
@@ -78,6 +93,7 @@
     private AnimatorSet mGlowAnimationSet;
     private ObjectAnimator mGlowTopAnimation;
     private ObjectAnimator mGlowBottomAnimation;
+    private Vibrator mVibrator;
 
     private int mSmallSize;
     private int mLargeSize;
@@ -85,6 +101,8 @@
 
     private int mGravity;
 
+    private View mScrollView;
+
     private class ViewScaler {
         View mView;
 
@@ -93,7 +111,7 @@
             mView = v;
         }
         public void setHeight(float h) {
-            if (DEBUG) Slog.v(TAG, "SetHeight: setting to " + h);
+            if (DEBUG_SCALE) Slog.v(TAG, "SetHeight: setting to " + h);
             ViewGroup.LayoutParams lp = mView.getLayoutParams();
             lp.height = (int)h;
             mView.setLayoutParams(lp);
@@ -108,7 +126,8 @@
         }
         public int getNaturalHeight(int maximum) {
             ViewGroup.LayoutParams lp = mView.getLayoutParams();
-            if (DEBUG) Slog.v(TAG, "Inspecting a child of type: " + mView.getClass().getName());
+            if (DEBUG_SCALE) Slog.v(TAG, "Inspecting a child of type: " +
+                    mView.getClass().getName());
             int oldHeight = lp.height;
             lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
             mView.setLayoutParams(lp);
@@ -142,6 +161,8 @@
         mGravity = Gravity.TOP;
         mScaleAnimation = ObjectAnimator.ofFloat(mScaler, "height", 0f);
         mScaleAnimation.setDuration(EXPAND_DURATION);
+        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
@@ -169,38 +190,30 @@
         mGlowAnimationSet.play(mGlowTopAnimation).with(mGlowBottomAnimation);
         mGlowAnimationSet.setDuration(GLOW_DURATION);
 
+        final ViewConfiguration configuration = ViewConfiguration.get(mContext);
+        mTouchSlop = configuration.getScaledTouchSlop();
+
         mDetector =
                 new ScaleGestureDetector(context,
                                          new ScaleGestureDetector.SimpleOnScaleGestureListener() {
             @Override
             public boolean onScaleBegin(ScaleGestureDetector detector) {
-                if (DEBUG) Slog.v(TAG, "onscalebegin()");
+                if (DEBUG_SCALE) Slog.v(TAG, "onscalebegin()");
                 float x = detector.getFocusX();
                 float y = detector.getFocusY();
 
-                View v = null;
-                if (mEventSource != null) {
-                    int[] location = new int[2];
-                    mEventSource.getLocationOnScreen(location);
-                    x += (float) location[0];
-                    y += (float) location[1];
-                    v = mCallback.getChildAtRawPosition(x, y);
-                } else {
-                    v = mCallback.getChildAtPosition(x, y);
-                }
-
                 // your fingers have to be somewhat close to the bounds of the view in question
                 mInitialTouchFocusY = detector.getFocusY();
                 mInitialTouchSpan = Math.abs(detector.getCurrentSpan());
-                if (DEBUG) Slog.d(TAG, "got mInitialTouchSpan: (" + mInitialTouchSpan + ")");
+                if (DEBUG_SCALE) Slog.d(TAG, "got mInitialTouchSpan: (" + mInitialTouchSpan + ")");
 
-                mStretching = initScale(v);
+                mStretching = initScale(findView(x, y));
                 return mStretching;
             }
 
             @Override
             public boolean onScale(ScaleGestureDetector detector) {
-                if (DEBUG) Slog.v(TAG, "onscale() on " + mCurrView);
+                if (DEBUG_SCALE) Slog.v(TAG, "onscale() on " + mCurrView);
 
                 // are we scaling or dragging?
                 float span = Math.abs(detector.getCurrentSpan()) - mInitialTouchSpan;
@@ -210,33 +223,71 @@
                 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;
-                if (DEBUG) Slog.d(TAG, "current span handle is: " + hand);
-                hand = hand + mOldHeight;
-                float target = hand;
-                if (DEBUG) Slog.d(TAG, "target is: " + target);
-                hand = hand < mSmallSize ? mSmallSize : (hand > mLargeSize ? mLargeSize : hand);
-                hand = hand > mNaturalHeight ? mNaturalHeight : hand;
-                if (DEBUG) Slog.d(TAG, "scale continues: hand =" + hand);
-                mScaler.setHeight(hand);
+                float target = hand + mOldHeight;
+                float newHeight = clamp(target);
+                mScaler.setHeight(newHeight);
 
-                // glow if overscale
-                float stretch = (float) Math.abs((target - hand) / mMaximumStretch);
-                float strength = 1f / (1f + (float) Math.pow(Math.E, -1 * ((8f * stretch) - 5f)));
-                if (DEBUG) Slog.d(TAG, "stretch: " + stretch + " strength: " + strength);
-                setGlow(GLOW_BASE + strength * (1f - GLOW_BASE));
+                setGlow(calculateGlow(target, newHeight));
                 return true;
             }
 
             @Override
             public void onScaleEnd(ScaleGestureDetector detector) {
-                if (DEBUG) Slog.v(TAG, "onscaleend()");
+                if (DEBUG_SCALE) Slog.v(TAG, "onscaleend()");
                 // I guess we're alone now
-                if (DEBUG) Slog.d(TAG, "scale end");
+                if (DEBUG_SCALE) Slog.d(TAG, "scale end");
                 finishScale(false);
+                clearView();
+                mStretching = false;
             }
         });
     }
 
+    private float clamp(float target) {
+        float out = target;
+        out = out < mSmallSize ? mSmallSize : (out > mLargeSize ? mLargeSize : out);
+        out = out > mNaturalHeight ? mNaturalHeight : out;
+        return out;
+    }
+
+    private View findView(float x, float y) {
+        View v = null;
+        if (mEventSource != null) {
+            int[] location = new int[2];
+            mEventSource.getLocationOnScreen(location);
+            x += (float) location[0];
+            y += (float) location[1];
+            v = mCallback.getChildAtRawPosition(x, y);
+        } else {
+            v = mCallback.getChildAtPosition(x, y);
+        }
+        return v;
+    }
+
+    private boolean isInside(View v, float x, float y) {
+        if (DEBUG) Slog.d(TAG, "isinside (" + x + ", " + y + ")");
+
+        if (v == null) {
+            if (DEBUG) Slog.d(TAG, "isinside null subject");
+            return false;
+        }
+        if (mEventSource != null) {
+            int[] location = new int[2];
+            mEventSource.getLocationOnScreen(location);
+            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 -= (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());
+        return inside;
+    }
+
     public void setEventSource(View eventSource) {
         mEventSource = eventSource;
     }
@@ -245,13 +296,26 @@
         mGravity = gravity;
     }
 
+    public void setScrollView(View scrollView) {
+        mScrollView = scrollView;
+    }
+
+    private float calculateGlow(float target, float actual) {
+        // glow if overscale
+        if (DEBUG_GLOW) Slog.d(TAG, "target: " + target + " actual: " + actual);
+        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));
+    }
+
     public void setGlow(float glow) {
         if (!mGlowAnimationSet.isRunning() || glow == 0f) {
             if (mGlowAnimationSet.isRunning()) {
-                mGlowAnimationSet.cancel();
+                mGlowAnimationSet.end();
             }
             if (mCurrViewTopGlow != null && mCurrViewBottomGlow != null) {
-                if (glow == 0f || mCurrViewTopGlow.getAlpha() == 0f) { 
+                if (glow == 0f || mCurrViewTopGlow.getAlpha() == 0f) {
                     // animate glow in and out
                     mGlowTopAnimation.setTarget(mCurrViewTopGlow);
                     mGlowBottomAnimation.setTarget(mCurrViewBottomGlow);
@@ -278,23 +342,115 @@
 
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         if (DEBUG) Slog.d(TAG, "interceptTouch: act=" + (ev.getAction()) +
-                         " stretching=" + mStretching);
+                         " stretching=" + mStretching +
+                         " onefinger=" + mPullingWithOneFinger);
+        // check for a two-finger gesture
         mDetector.onTouchEvent(ev);
-        return mStretching;
+        if (mStretching) {
+            return true;
+        } else {
+            final int action = ev.getAction();
+            if ((action == MotionEvent.ACTION_MOVE) && mPullingWithOneFinger) {
+                return true;
+            }
+            if (mScrollView != null && mScrollView.getScrollY() > 0) {
+                return false;
+            }
+            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) {
+                        mLastMotionY = y;
+                        mPullingWithOneFinger = initScale(findView(x, y));
+                        if (mPullingWithOneFinger) {
+                            mInitialTouchY = mLastMotionY;
+                            mHasPopped = false;
+                        }
+                    }
+                }
+                break;
+            }
+
+            case MotionEvent.ACTION_DOWN:
+                mWatchingForPull = isInside(mScrollView, ev.getX(), ev.getY());
+                mLastMotionY = (int) ev.getY();
+                break;
+
+            case MotionEvent.ACTION_CANCEL:
+            case MotionEvent.ACTION_UP:
+                if (mPullingWithOneFinger) {
+                    finishScale(false);
+                    clearView();
+                }
+                mPullingWithOneFinger = false;
+                mWatchingForPull = false;
+                break;
+            }
+            return mPullingWithOneFinger;
+        }
     }
 
     public boolean onTouchEvent(MotionEvent ev) {
         final int action = ev.getAction();
-        if (DEBUG) Slog.d(TAG, "touch: act=" + (action) + " stretching=" + mStretching);
+        if (DEBUG_SCALE) Slog.d(TAG, "touch: act=" + (action) +
+                         " stretching=" + mStretching +
+                         " onefinger=" + mPullingWithOneFinger);
         if (mStretching) {
-            if (DEBUG) Slog.d(TAG, "detector ontouch");
             mDetector.onTouchEvent(ev);
         }
         switch (action) {
+            case MotionEvent.ACTION_MOVE: {
+                if (mPullingWithOneFinger) {
+                    final float rawHeight = ev.getY() - mInitialTouchY + mOldHeight;
+                    final float newHeight = clamp(rawHeight);
+                    final boolean wasClosed = (mOldHeight == mSmallSize);
+                    boolean isFinished = false;
+                    if (rawHeight > mNaturalHeight) {
+                        isFinished = true;
+                    }
+                    if (rawHeight < mSmallSize) {
+                        isFinished = true;
+                    }
+
+                    final float pull = Math.abs(ev.getY() - mInitialTouchY);
+                    if (mHasPopped || pull > mPopLimit) {
+                        if (!mHasPopped) {
+                            vibrate(mPopDuration);
+                            mHasPopped = true;
+                        }
+                    }
+
+                    if (mHasPopped) {
+                        mScaler.setHeight(newHeight);
+                        setGlow(GLOW_BASE);
+                    } else {
+                        setGlow(calculateGlow(4f * pull, 0f));
+                    }
+
+                    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;
+                }
+                break;
+            }
             case MotionEvent.ACTION_UP:
             case MotionEvent.ACTION_CANCEL:
                 if (DEBUG) Slog.d(TAG, "cancel");
                 mStretching = false;
+                if (mPullingWithOneFinger) {
+                    finishScale(false);
+                    mPullingWithOneFinger = false;
+                }
                 clearView();
                 break;
         }
@@ -303,7 +459,7 @@
     private boolean initScale(View v) {
         if (v != null) {
             if (DEBUG) Slog.d(TAG, "scale begins on view: " + v);
-            mStretching = true;
+            mCallback.setUserLockedChild(v, true);
             setView(v);
             setGlow(GLOW_BASE);
             mScaler.setView(v);
@@ -318,30 +474,34 @@
             if (DEBUG) Slog.d(TAG, "got mOldHeight: " + mOldHeight +
                         " mNaturalHeight: " + mNaturalHeight);
             v.getParent().requestDisallowInterceptTouchEvent(true);
+            return true;
+        } else {
+            return false;
         }
-        return mStretching;
     }
 
     private void finishScale(boolean force) {
+        float currentHeight = mScaler.getHeight();
+        float targetHeight = mSmallSize;
         float h = mScaler.getHeight();
         final boolean wasClosed = (mOldHeight == mSmallSize);
         if (wasClosed) {
-            h = (force || h > mSmallSize) ? mNaturalHeight : mSmallSize;
+            targetHeight = (force || currentHeight > mSmallSize) ? mNaturalHeight : mSmallSize;
         } else {
-            h = (force || h < mNaturalHeight) ? mSmallSize : mNaturalHeight;
+            targetHeight = (force || currentHeight < mNaturalHeight) ? mSmallSize : mNaturalHeight;
         }
-        if (DEBUG && mCurrView != null) mCurrView.setBackgroundColor(0);
         if (mScaleAnimation.isRunning()) {
             mScaleAnimation.cancel();
         }
-        mScaleAnimation.setFloatValues(h);
-        mScaleAnimation.setupStartValues();
-        mScaleAnimation.start();
-        mStretching = false;
         setGlow(0f);
         mCallback.setUserExpandedChild(mCurrView, h == mNaturalHeight);
+        if (targetHeight != currentHeight) {
+            mScaleAnimation.setFloatValues(targetHeight);
+            mScaleAnimation.setupStartValues();
+            mScaleAnimation.start();
+        }
+        mCallback.setUserLockedChild(mCurrView, false);
         if (DEBUG) Slog.d(TAG, "scale was finished on view: " + mCurrView);
-        clearView();
     }
 
     private void clearView() {
@@ -357,7 +517,7 @@
             mCurrViewTopGlow = g.findViewById(R.id.top_glow);
             mCurrViewBottomGlow = g.findViewById(R.id.bottom_glow);
             if (DEBUG) {
-                String debugLog = "Looking for glows: " + 
+                String debugLog = "Looking for glows: " +
                         (mCurrViewTopGlow != null ? "found top " : "didn't find top") +
                         (mCurrViewBottomGlow != null ? "found bottom " : "didn't find bottom");
                 Slog.v(TAG,  debugLog);
@@ -369,6 +529,18 @@
     public void onClick(View v) {
         initScale(v);
         finishScale(true);
+        clearView();
+    }
 
+    /**
+     * Triggers haptic feedback.
+     */
+    private synchronized void vibrate(long duration) {
+        if (mVibrator == null) {
+            mVibrator = (android.os.Vibrator)
+                    mContext.getSystemService(Context.VIBRATOR_SERVICE);
+        }
+        mVibrator.vibrate(duration);
     }
 }
+
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index b0a7c4b..2512c02 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -74,10 +74,7 @@
         //noinspection PointlessBooleanExpression,ConstantConditions
         if (FIXED_SIZED_SURFACE && USE_OPENGL) {
             if (!isEmulator()) {
-                WindowManager windowManager =
-                        (WindowManager) getSystemService(Context.WINDOW_SERVICE);
-                Display display = windowManager.getDefaultDisplay();
-                mIsHwAccelerated = ActivityManager.isHighEndGfx(display);
+                mIsHwAccelerated = ActivityManager.isHighEndGfx();
             }
         }
     }
@@ -294,13 +291,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/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..2a225d9 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
@@ -30,7 +30,10 @@
 import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.Process;
+import android.os.UserHandle;
 import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
 
 import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
@@ -41,7 +44,7 @@
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
 
-public class RecentTasksLoader {
+public class RecentTasksLoader implements View.OnTouchListener {
     static final String TAG = "RecentTasksLoader";
     static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG || false;
 
@@ -50,18 +53,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 +119,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 +139,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 +242,43 @@
         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) {
+            mHandler.post(mPreloadTasksRunnable);
+        } else if (action == MotionEvent.ACTION_CANCEL) {
+            cancelLoadingThumbnailsAndIcons();
+            mHandler.removeCallbacks(mPreloadTasksRunnable);
+        } 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 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 +287,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 +316,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 +346,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 +428,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 +453,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..a4c8e64
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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 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);
+
+        handleIntent(getIntent());
+        mIntentFilter = new IntentFilter();
+        mIntentFilter.addAction(CLOSE_RECENTS_INTENT);
+        registerReceiver(mIntentReceiver, mIntentFilter);
+        super.onCreate(savedInstanceState);
+    }
+
+    @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 && !mRecentsPanel.isShowing()) {
+                final SystemUIApplication app = (SystemUIApplication) getApplication();
+                final RecentTasksLoader recentTasksLoader = app.getRecentTasksLoader();
+                mRecentsPanel.show(true, recentTasksLoader.getLoadedTasks(),
+                        recentTasksLoader.isFirstScreenful());
+            } else if ((mRecentsPanel != null && mRecentsPanel.isShowing())) {
+                dismissAndGoBack();
+            }
+        }
+    }
+
+}
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..c3ecdb5 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,24 @@
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Matrix;
-import android.graphics.Rect;
 import android.graphics.Shader.TileMode;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.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.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.AnimationUtils;
 import android.widget.AdapterView;
@@ -68,7 +68,7 @@
 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;
@@ -81,36 +81,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 {
@@ -249,15 +235,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 +254,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 +286,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 +336,6 @@
             createCustomAnimations(transitioner);
         } else {
             ((ViewGroup)mRecentsContainer).setLayoutTransition(null);
-            clearRecentTasksList();
         }
     }
 
@@ -400,16 +345,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
@@ -446,18 +381,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 +406,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 +416,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 +509,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 +531,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 +549,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 +570,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;
@@ -724,60 +600,10 @@
             usingDrawingCache = true;
         }
 
-        if (mPlaceholderThumbnail == null) {
-            mPlaceholderThumbnail =
-                    (ImageView) findViewById(R.id.recents_transition_placeholder_icon);
-        }
-        if (mTransitionBg == null) {
-            mTransitionBg = (View) findViewById(R.id.recents_transition_background);
+        ActivityOptions opts = ActivityOptions.makeThumbnailScaleUpAnimation(
+                holder.thumbnailViewImage, bm, 0, 0, null);
 
-            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,
@@ -788,24 +614,14 @@
                     | 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.toBundle(),
+                    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 +640,7 @@
         // mListAdapter.notifyDataSetChanged();
 
         if (mRecentTaskDescriptions.size() == 0) {
-            hide(false);
+            dismissAndGoBack();
         }
 
         // Currently, either direction means the same thing, so ignore direction and remove
@@ -845,8 +661,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 +690,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 1204a89..106ce7e 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,148 @@
         }
     }
 
+    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.getWidth() != thumbWidth || first.getHeight() != thumbHeight) {
+                    first = Bitmap.createScaledBitmap(first, (int) thumbWidth, (int) thumbHeight,
+                            true);
+                }
+
+                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();
+                  {
+                      // TODO:
+                      // need to implement this
+                      //final RecentsPanelView recentsPanel = getRecentsPanel();
+                      //if (recentsPanel != null) {
+                      //recentsPanel.preloadRecentTasksList();
+                      //}
+                  }
                   break;
              case MSG_CANCEL_PRELOAD_RECENT_APPS:
                   if (DEBUG) Slog.d(TAG, "cancel preloading recents");
-                  mRecentsPanel.clearRecentTasksList();
+                  {
+                      // TODO:
+                      // need to implement this
+                      //final RecentsPanelView recentsPanel = getRecentsPanel();
+                      //if (recentsPanel != null) {
+                      //recentsPanel.clearRecentTasksList();
+                      //}
+                  }
                   break;
              case MSG_OPEN_SEARCH_PANEL:
                  if (DEBUG) Slog.d(TAG, "opening search panel");
@@ -529,8 +650,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 +694,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 +725,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;
@@ -783,16 +909,20 @@
         int N = mNotificationData.size();
         for (int i = 0; i < N; i++) {
             NotificationData.Entry entry = mNotificationData.get(i);
-            if (i == (N-1)) {
-                if (DEBUG) Slog.d(TAG, "expanding top notification at " + i);
-                expandView(entry, true);
-            } else {
-                if (!entry.userExpanded()) {
-                    if (DEBUG) Slog.d(TAG, "collapsing notification at " + i);
-                    expandView(entry, false);
+            if (!entry.userLocked()) {
+                if (i == (N-1)) {
+                    if (DEBUG) Slog.d(TAG, "expanding top notification at " + i);
+                    expandView(entry, true);
                 } else {
-                    if (DEBUG) Slog.d(TAG, "ignoring user-modified notification at " + i);
+                    if (!entry.userExpanded()) {
+                        if (DEBUG) Slog.d(TAG, "collapsing notification at " + i);
+                        expandView(entry, false);
+                    } else {
+                        if (DEBUG) Slog.d(TAG, "ignoring user-modified notification at " + i);
+                    }
                 }
+            } else {
+                if (DEBUG) Slog.d(TAG, "ignoring notification being held by user at " + i);
             }
         }
     }
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/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index dfd8cf8..c82f250 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -71,6 +71,18 @@
         public boolean setUserExpanded(boolean userExpanded) {
             return NotificationData.setUserExpanded(row, userExpanded);
         }
+        /**
+         * Return whether the entry is being touched by the user.
+         */
+        public boolean userLocked() {
+            return NotificationData.getUserLocked(row);
+        }
+        /**
+         * Set the flag indicating that this is being touched by the user.
+         */
+        public boolean setUserLocked(boolean userLocked) {
+            return NotificationData.setUserLocked(row, userLocked);
+        }
     }
     private final ArrayList<Entry> mEntries = new ArrayList<Entry>();
     private final Comparator<Entry> mEntryCmp = new Comparator<Entry>() {
@@ -197,4 +209,18 @@
     public static boolean setUserExpanded(View row, boolean userExpanded) {
         return writeBooleanTag(row, R.id.user_expanded_tag, userExpanded);
     }
+
+    /**
+     * Return whether the entry is being touched by the user.
+     */
+    public static boolean getUserLocked(View row) {
+        return readBooleanTag(row, R.id.user_lock_tag);
+    }
+
+    /**
+     * Set whether the entry is being touched by the user.
+     */
+    public static boolean setUserLocked(View row, boolean userLocked) {
+        return writeBooleanTag(row, R.id.user_lock_tag, userLocked);
+    }
 }
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..33f467f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -0,0 +1,365 @@
+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.Log;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import com.android.systemui.R;
+
+public class PanelView extends FrameLayout {
+    public static final boolean DEBUG = false;
+    public static final String TAG = PanelView.class.getSimpleName();
+    public final void LOG(String fmt, Object... args) {
+        if (!DEBUG) return;
+        Log.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);
+    }
+
+    @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 void setBar(PanelBar panelBar) {
+        mBar = panelBar;
+    }
+
+    public void collapse() {
+        // TODO: abort animation or ongoing touch
+        if (mExpandedHeight > 0) {
+            fling(-mSelfCollapseVelocityPx, /*always=*/ true);
+        }
+    }
+
+    public void expand() {
+        if (mExpandedHeight < getFullHeight()) {
+            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..9b4ee38 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.phone;
 
 import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
@@ -47,11 +46,12 @@
 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;
@@ -60,9 +60,9 @@
 import android.view.VelocityTracker;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.WindowManagerGlobal;
 import android.view.ViewGroup.LayoutParams;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
@@ -72,14 +72,16 @@
 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;
@@ -87,9 +89,9 @@
 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,8 +109,7 @@
     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 boolean SHOW_CARRIER_LABEL = false; // XXX: doesn't work with rubberband panels right now
 
     private static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
     private static final int MSG_CLOSE_NOTIFICATION_PANEL = 1001;
@@ -149,7 +150,7 @@
     int mIconHPadding = -1;
     Display mDisplay;
 
-    IWindowManager mWindowManager;
+    IDreamManager mDreamManager;
 
     StatusBarWindowView mStatusBarWindow;
     PhoneStatusBarView mStatusBarView;
@@ -164,14 +165,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;
@@ -184,13 +190,8 @@
     private int mCarrierLabelHeight;
     private TextView mEmergencyCallLabel;
 
-    // drag bar
-    CloseDragHandle mCloseView;
-    private int mCloseViewHeight;
-
     // position
     int[] mPositionTmp = new int[2];
-    boolean mExpanded;
     boolean mExpandedVisible;
 
     // the date view
@@ -215,7 +216,6 @@
     boolean mTracking;
     VelocityTracker mVelocityTracker;
 
-    Choreographer mChoreographer;
     boolean mAnimating;
     boolean mClosing; // only valid when mAnimating; indicates the initial acceleration
     float mAnimY;
@@ -240,6 +240,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 +255,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 +296,7 @@
             @Override
             public boolean onTouch(View v, MotionEvent event) {
                 if (event.getAction() == MotionEvent.ACTION_DOWN) {
-                    if (mExpanded && !mAnimating) {
+                    if (mExpandedVisible && !mAnimating) {
                         animateCollapse();
                     }
                 }
@@ -354,39 +304,51 @@
             }});
 
         mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);
-        mNotificationPanel = mStatusBarWindow.findViewById(R.id.notification_panel);
+        mStatusBarView.setBar(this);
+
+        PanelHolder holder = (PanelHolder) mStatusBarWindow.findViewById(R.id.panel_holder);
+        mStatusBarView.setPanelHolder(holder);
+
+        mNotificationPanel = (PanelView) 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() {
+        View.OnTouchListener clickStopper = new View.OnTouchListener() {
             @Override
             public boolean onTouch(View v, MotionEvent event) {
                 return true;
             }
-        });
+        };
+        mNotificationPanel.setOnTouchListener(clickStopper);
         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)) {
+        // quick settings (WIP)
+        mSettingsPanel = (PanelView) mStatusBarWindow.findViewById(R.id.settings_panel);
+        mSettingsPanel.setOnTouchListener(clickStopper);
+
+        if (!ActivityManager.isHighEndGfx()) {
             mStatusBarWindow.setBackground(null);
             mNotificationPanel.setBackground(new FastColorDrawable(context.getResources().getColor(
                     R.color.notification_panel_solid_background)));
+            mSettingsPanel.setBackground(new FastColorDrawable(context.getResources().getColor(
+                    R.color.notification_panel_solid_background)));
         }
         if (ENABLE_INTRUDERS) {
             mIntruderAlertView = (IntruderAlertView) View.inflate(context, R.layout.intruder_alert, null);
             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 +392,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
@@ -487,9 +445,6 @@
 //        if (wimaxRSSI != null) {
 //            mNetworkController.addWimaxIconView(wimaxRSSI);
 //        }
-        // Recents Panel
-        mRecentTasksLoader = new RecentTasksLoader(context);
-        updateRecentsPanel();
 
         // receive broadcasts
         IntentFilter filter = new IntentFilter();
@@ -502,6 +457,11 @@
     }
 
     @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,6 +509,7 @@
         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
@@ -559,6 +520,7 @@
             mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPanel);
         }
     }
+    */
 
     @Override
     protected void updateSearchPanel() {
@@ -573,7 +535,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 +544,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 +560,6 @@
         return mNaturalBarHeight;
     }
 
-    private int getCloseViewHeight() {
-        return mCloseViewHeight;
-    }
-
     private View.OnClickListener mRecentsClickListener = new View.OnClickListener() {
         public void onClick(View v) {
             toggleRecentApps();
@@ -612,6 +570,7 @@
     private Runnable mShowSearchPanel = new Runnable() {
         public void run() {
             showSearchPanel();
+            awakenDreams();
         }
     };
 
@@ -628,17 +587,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 +620,7 @@
 
         prepareNavigationBarView();
 
-        WindowManagerImpl.getDefault().addView(
-                mNavigationBarView, getNavigationBarLayoutParams());
+        mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams());
     }
 
     private void repositionNavigationBar() {
@@ -659,8 +628,7 @@
 
         prepareNavigationBarView();
 
-        WindowManagerImpl.getDefault().updateViewLayout(
-                mNavigationBarView, getNavigationBarLayoutParams());
+        mWindowManager.updateViewLayout(mNavigationBarView, getNavigationBarLayoutParams());
     }
 
     private WindowManager.LayoutParams getNavigationBarLayoutParams() {
@@ -671,10 +639,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 +653,6 @@
     }
 
     private void addIntruderView() {
-        final int height = getStatusBarHeight();
-
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.WRAP_CONTENT,
@@ -703,7 +670,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) {
@@ -823,7 +790,6 @@
 
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
-        updateRecentsPanel();
         updateShowSearchHoldoff();
     }
 
@@ -843,9 +809,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 +836,6 @@
         mSettingsButton.setEnabled(isDeviceProvisioned());
     }
 
-    private void reloadAllNotificationIcons() {
-        if (mNotificationIcons == null) return;
-        mNotificationIcons.removeAllViews();
-        updateNotificationIcons();
-    }
-
     @Override
     protected void updateNotificationIcons() {
         if (mNotificationIcons == null) return;
@@ -897,10 +857,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>();
@@ -1166,20 +1126,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 +1134,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 +1155,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 +1191,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 +1215,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 +1228,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 +1243,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 +1290,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 +1303,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 +1405,7 @@
 
     private void notifyUiVisibilityChanged() {
         try {
-            mWindowManager.statusBarVisibilityChanged(mSystemUiVisibility);
+            mWindowManagerService.statusBarVisibilityChanged(mSystemUiVisibility);
         } catch (RemoteException ex) {
         }
     }
@@ -1807,64 +1435,6 @@
     @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);
-        }
-    }
-
     @Override
     protected void tick(IBinder key, StatusBarNotification n, boolean firstTime) {
         // no ticking in lights-out mode
@@ -1943,8 +1513,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 +1529,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 +1577,9 @@
             }
         }
 
+        pw.print("  status bar gestures: ");
+        mGestureRec.dump(fd, pw, args);
+
         mNetworkController.dump(fd, pw, args);
     }
 
@@ -2040,7 +1611,7 @@
         lp.packageName = mContext.getPackageName();
 
         makeStatusBarView();
-        WindowManagerImpl.getDefault().addView(mStatusBarWindow, lp);
+        mWindowManager.addView(mStatusBarWindow, lp);
     }
 
     void setNotificationIconVisibility(boolean visible, int anim) {
@@ -2066,88 +1637,24 @@
     }
 
     @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);
-
-        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);
+        lp = (FrameLayout.LayoutParams) mSettingsPanel.getLayoutParams();
+        lp.gravity = mSettingsPanelGravity;
+        lp.rightMargin = mNotificationPanelMarginPx;
+        mSettingsPanel.setLayoutParams(lp);
     }
 
+    // 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 +1692,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 +1728,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 +1778,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,7 +1801,7 @@
             }
             else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
                 // no waiting!
-                performCollapse();
+                makeExpandedInvisible();
             }
             else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
                 updateResources();
@@ -2302,6 +1811,13 @@
         }
     };
 
+    @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) {
@@ -2377,11 +1893,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 =
@@ -2444,7 +1964,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/SettingsPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
new file mode 100644
index 0000000..fb1528f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+public class SettingsPanelView extends PanelView {
+    public SettingsPanelView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @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 9317561..2d4c9ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -53,6 +53,7 @@
         int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_max_height);
         mExpandHelper = new ExpandHelper(mContext, latestItems, minHeight, maxHeight);
         mExpandHelper.setEventSource(this);
+        mExpandHelper.setScrollView(scroller);
     }
 
     @Override
@@ -70,13 +71,13 @@
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
-        MotionEvent cancellation = MotionEvent.obtain(ev);
-        cancellation.setAction(MotionEvent.ACTION_CANCEL);
-
         boolean intercept = mExpandHelper.onInterceptTouchEvent(ev) ||
                 super.onInterceptTouchEvent(ev);
         if (intercept) {
+            MotionEvent cancellation = MotionEvent.obtain(ev);
+            cancellation.setAction(MotionEvent.ACTION_CANCEL);
             latestItems.onInterceptTouchEvent(cancellation);
+            cancellation.recycle();
         }
         return intercept;
     }
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..457e9dd 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;
@@ -31,8 +32,8 @@
 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;
@@ -42,6 +43,10 @@
         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,11 +70,11 @@
             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);
     }
@@ -78,7 +83,7 @@
         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() {
@@ -98,7 +103,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/DeadZone.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
index 19fbe96..6ffca2a 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,145 @@
 
 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 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(true);
+    }
+
+    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 (DEBUG)
+                    Slog.v(TAG, "eating click!");
+                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/NotificationRowLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
index 61e5ab6..89eed1b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
@@ -78,6 +78,7 @@
         super(context, attrs, defStyle);
 
         mRealLayoutTransition = new LayoutTransition();
+        mRealLayoutTransition.setAnimateParentHierarchy(true);
         setLayoutTransitionsEnabled(true);
         
         setOrientation(LinearLayout.VERTICAL);
@@ -161,7 +162,12 @@
         return NotificationData.setUserExpanded(v, userExpanded);
     }
 
+    public boolean setUserLockedChild(View v, boolean userLocked) {
+        return NotificationData.setUserLocked(v, userLocked);
+    }
+
     public void onChildDismissed(View v) {
+        if (DEBUG) Slog.v(TAG, "onChildDismissed: " + v + " mRemoveViews=" + mRemoveViews);
         final View veto = v.findViewById(R.id.veto);
         if (veto != null && veto.getVisibility() != View.GONE && mRemoveViews) {
             veto.performClick();
@@ -225,6 +231,7 @@
      * get removed properly.
      */
     public void setViewRemoval(boolean removeViews) {
+        if (DEBUG) Slog.v(TAG, "setViewRemoval: " + removeViews);
         mRemoveViews = removeViews;
     }
 
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..8ca3a9c 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(mRecentsPanel); //TODO: plumb this
 
         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/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index fc187ce..8d19f34 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,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
+import android.os.UserManager;
 import android.os.Vibrator;
 import android.provider.Settings;
 import android.telephony.PhoneStateListener;
@@ -48,10 +50,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 +91,6 @@
     private boolean mHasTelephony;
     private boolean mHasVibrator;
 
-    private IWindowManager mIWindowManager;
-
     /**
      * @param context everything needs a context :(
      */
@@ -207,11 +209,11 @@
 
                 public void onPress() {
                     // shutdown by making sure radio and power are handled accordingly.
-                    mWindowManagerFuncs.shutdown();
+                    mWindowManagerFuncs.shutdown(true);
                 }
 
                 public boolean onLongPress() {
-                    mWindowManagerFuncs.rebootSafeMode();
+                    mWindowManagerFuncs.rebootSafeMode(true);
                     return true;
                 }
 
@@ -227,12 +229,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 +290,16 @@
             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();
+                            WindowManagerGlobal.getWindowManagerService().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 {
@@ -808,12 +872,4 @@
             mAirplaneState = on ? ToggleAction.State.On : ToggleAction.State.Off;
         }
     }
-
-    private IWindowManager getWindowManager() {
-        if (mIWindowManager == null) {
-            IBinder b = ServiceManager.getService(Context.WINDOW_SERVICE);
-            mIWindowManager = IWindowManager.Stub.asInterface(b);
-        }
-        return mIWindowManager;
-    }
 }
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
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/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 0aa3018..3e96f9bc 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().layoutDirection);
         }
         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..2b6e856 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -42,10 +42,10 @@
 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,11 +55,14 @@
 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;
@@ -82,6 +85,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,6 +110,7 @@
 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;
@@ -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,16 @@
     static final int NAVIGATION_BAR_PANEL_LAYER = 20;
     // system-level error dialogs
     static final int SYSTEM_ERROR_LAYER = 21;
+    // used to simulate secondary display devices
+    static final int DISPLAY_OVERLAY_LAYER = 22;
     // 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 = 23;
+    static final int SECURE_SYSTEM_OVERLAY_LAYER = 24;
+    static final int BOOT_PROGRESS_LAYER = 25;
     // the (mouse) pointer layer
-    static final int POINTER_LAYER = 25;
-    static final int HIDDEN_NAV_CONSUMER_LAYER = 26;
+    static final int POINTER_LAYER = 26;
+    static final int HIDDEN_NAV_CONSUMER_LAYER = 27;
 
     static final int APPLICATION_MEDIA_SUBLAYER = -2;
     static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
@@ -277,7 +283,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 +344,6 @@
     boolean mSystemReady;
     boolean mSystemBooted;
     boolean mHdmiPlugged;
-    int mExternalDisplayWidth;
-    int mExternalDisplayHeight;
     int mUiMode;
     int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
     int mLidOpenRotation;
@@ -361,6 +365,7 @@
     boolean mScreenOnEarly = false;
     boolean mScreenOnFully = false;
     boolean mOrientationSensorEnabled = false;
+    int mLastSensorRotation = -1;
     int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
     boolean mHasSoftInput = false;
     
@@ -472,13 +477,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 +568,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 +723,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 +740,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 +859,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 +892,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 +926,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 +952,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 +984,6 @@
             }
         }
 
-        mExternalDisplayWidth = mDisplay.getRawExternalWidth();
-        mExternalDisplayHeight = mDisplay.getRawExternalHeight();
-
         mStatusBarHeight = mContext.getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.status_bar_height);
 
@@ -1021,22 +1006,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 +1036,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 +1107,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 +1185,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 +1212,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 +1330,10 @@
             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;
         }
         Log.e(TAG, "Unknown window type: " + type);
         return APPLICATION_LAYER;
@@ -1400,6 +1360,10 @@
         return STATUS_BAR_LAYER;
     }
 
+    public int getAboveUniverseLayer() {
+        return SYSTEM_ERROR_LAYER;
+    }
+
     public boolean hasSystemNavBar() {
         return mHasSystemNavBar;
     }
@@ -1453,7 +1417,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 +1514,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 +1553,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 +1564,7 @@
                         "PhoneWindowManager");
                 if (mStatusBar != null) {
                     if (mStatusBar.isAlive()) {
-                        return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
+                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
                     }
                 }
                 mStatusBar = win;
@@ -1609,7 +1575,7 @@
                         "PhoneWindowManager");
                 if (mNavigationBar != null) {
                     if (mNavigationBar.isAlive()) {
-                        return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
+                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
                     }
                 }
                 mNavigationBar = win;
@@ -1632,12 +1598,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 +1733,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;
@@ -2114,7 +2082,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 +2090,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);
             }
@@ -2370,16 +2339,6 @@
             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;
-                    }
-                }
                 mTmpNavigationFrame.set(0, top, displayWidth, displayHeight);
                 mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
                 if (navVisible) {
@@ -2399,11 +2358,6 @@
             } 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) {
@@ -2720,7 +2674,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;
@@ -2872,8 +2827,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) {
@@ -3034,22 +2989,16 @@
                 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);
@@ -3192,7 +3141,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 +3152,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 +3172,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 +3190,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 +3213,7 @@
                             mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED);
                 } else {
                     // Otherwise, wake the device ourselves.
-                    result |= ACTION_POKE_USER_ACTIVITY;
+                    result |= ACTION_WAKE_UP;
                 }
             }
         }
@@ -3366,7 +3318,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 +3360,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 +3445,7 @@
                 mKeyguardMediator.onWakeMotionWhenKeyguardShowingTq();
             } else {
                 // Otherwise, wake the device ourselves.
-                result |= ACTION_POKE_USER_ACTIVITY;
+                result |= ACTION_WAKE_UP;
             }
         }
         return result;
@@ -3573,15 +3525,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 +3687,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 +3998,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 +4041,6 @@
     }
 
     private void applyLidSwitchState() {
-        mPowerManager.setKeyboardVisibility(isBuiltInKeyboardVisible());
-
         if (mLidState == LID_CLOSED && mLidControlsSleep) {
             mPowerManager.goToSleep(SystemClock.uptimeMillis());
         }
@@ -4326,24 +4222,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);
             }
         }
     }
diff --git a/policy/src/com/android/internal/policy/impl/BiometricSensorUnlock.java b/policy/src/com/android/internal/policy/impl/keyguard/BiometricSensorUnlock.java
similarity index 98%
rename from policy/src/com/android/internal/policy/impl/BiometricSensorUnlock.java
rename to policy/src/com/android/internal/policy/impl/keyguard/BiometricSensorUnlock.java
index f476f82..39afaa2 100644
--- a/policy/src/com/android/internal/policy/impl/BiometricSensorUnlock.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/BiometricSensorUnlock.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard;
 
 import android.view.View;
 
diff --git a/policy/src/com/android/internal/policy/impl/FaceUnlock.java b/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java
similarity index 95%
copy from policy/src/com/android/internal/policy/impl/FaceUnlock.java
copy to policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java
index fda3c9d..31d138b 100644
--- a/policy/src/com/android/internal/policy/impl/FaceUnlock.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,9 +14,8 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard;
 
-import com.android.internal.R;
 import com.android.internal.policy.IFaceLockCallback;
 import com.android.internal.policy.IFaceLockInterface;
 import com.android.internal.widget.LockPatternUtils;
@@ -31,7 +30,6 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
-import android.telephony.TelephonyManager;
 import android.util.Log;
 import android.view.View;
 
@@ -42,7 +40,6 @@
 
     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;
@@ -78,17 +75,15 @@
     // Unlock
     private final int BACKUP_LOCK_TIMEOUT = 5000;
 
-    KeyguardScreenCallback mKeyguardScreenCallback;
+    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, KeyguardUpdateMonitor updateMonitor,
-            LockPatternUtils lockPatternUtils, KeyguardScreenCallback keyguardScreenCallback) {
+    public FaceUnlock(Context context, KeyguardSecurityCallback keyguardScreenCallback) {
         mContext = context;
-        mUpdateMonitor = updateMonitor;
-        mLockPatternUtils = lockPatternUtils;
+        mLockPatternUtils = new LockPatternUtils(context);
         mKeyguardScreenCallback = keyguardScreenCallback;
         mHandler = new Handler(this);
     }
@@ -234,7 +229,6 @@
      * 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:
@@ -328,7 +322,7 @@
                 // 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();
+                mKeyguardScreenCallback.userActivity(0);
 
                 int[] position;
                 position = new int[2];
@@ -370,8 +364,8 @@
             Log.e(TAG, "mFaceUnlockView is null in handleUnlock()");
         }
         stop();
-        mKeyguardScreenCallback.keyguardDone(true);
         mKeyguardScreenCallback.reportSuccessfulUnlockAttempt();
+        mKeyguardScreenCallback.dismiss(true);
     }
 
     /**
@@ -385,7 +379,7 @@
             Log.e(TAG, "mFaceUnlockView is null in handleCancel()");
         }
         stop();
-        mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT);
+        mKeyguardScreenCallback.userActivity(BACKUP_LOCK_TIMEOUT);
     }
 
     /**
@@ -393,7 +387,7 @@
      */
     void handleReportFailedAttempt() {
         if (DEBUG) Log.d(TAG, "handleReportFailedAttempt()");
-        mUpdateMonitor.reportFailedBiometricUnlockAttempt();
+        mKeyguardScreenCallback.reportFailedUnlockAttempt();
     }
 
     /**
@@ -414,7 +408,7 @@
      * Pokes the wakelock to keep the screen alive and active for a specific amount of time.
      */
     void handlePokeWakelock(int millis) {
-        mKeyguardScreenCallback.pokeWakelock(millis);
+        mKeyguardScreenCallback.userActivity(millis);
     }
 
     /**
@@ -433,7 +427,6 @@
         /**
          * 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);
@@ -443,7 +436,6 @@
         /**
          * 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);
@@ -505,7 +497,6 @@
         /**
          * 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);
@@ -514,7 +505,6 @@
         /**
          * Called when Face Unlock wants to go to the backup.
          */
-        @Override
         public void cancel() {
             if (DEBUG) Log.d(TAG, "cancel()");
             mHandler.sendEmptyMessage(MSG_CANCEL);
@@ -523,7 +513,6 @@
         /**
          * 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);
@@ -534,7 +523,6 @@
          * 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);
diff --git a/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java
similarity index 77%
copy from policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java
copy to policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java
index a4baeed..1e73c5b 100644
--- a/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.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.
@@ -13,37 +13,34 @@
  * 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;
+package com.android.internal.policy.impl.keyguard;
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
-import android.accounts.OperationCanceledException;
+import android.accounts.AccountManagerCallback;
 import android.accounts.AccountManagerFuture;
 import android.accounts.AuthenticatorException;
-import android.accounts.AccountManagerCallback;
+import android.accounts.OperationCanceledException;
+import android.app.Dialog;
+import android.app.ProgressDialog;
 import android.content.Context;
 import android.content.Intent;
-import android.content.res.Configuration;
 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.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 android.widget.LinearLayout;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.R;
 
 import java.io.IOException;
 
@@ -51,53 +48,42 @@
  * 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,
+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";
 
-    /**
-     * The amount of millis to stay awake once this screen detects activity
-     */
-    private static final int AWAKE_POKE_MILLIS = 30000;
-
-    private KeyguardScreenCallback mCallback;
+    private KeyguardSecurityCallback mCallback;
     private LockPatternUtils mLockPatternUtils;
-    private KeyguardUpdateMonitor mUpdateMonitor;
-
-    private TextView mTopHeader;
-    private TextView mInstructions;
     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;
-    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;
+    public KeyguardAccountView(Context context) {
+        this(context, null, 0);
+    }
 
-        LayoutInflater.from(context).inflate(
-                R.layout.keyguard_screen_glogin_unlock, this, true);
+    public KeyguardAccountView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
 
-        mTopHeader = (TextView) findViewById(R.id.topHeader);
-        mTopHeader.setText(mLockPatternUtils.isPermanentlyLocked() ?
-                R.string.lockscreen_glogin_too_many_attempts :
-                R.string.lockscreen_glogin_forgot_pattern);
+    public KeyguardAccountView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        mLockPatternUtils = new LockPatternUtils(getContext());
+    }
 
-        mInstructions = (TextView) findViewById(R.id.instructions);
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mNavigationManager = new KeyguardNavigationManager(this);
 
         mLogin = (EditText) findViewById(R.id.login);
         mLogin.setFilters(new InputFilter[] { new LoginFilter.UsernameFilterGeneric() } );
@@ -108,13 +94,22 @@
 
         mOk = (Button) findViewById(R.id.ok);
         mOk.setOnClickListener(this);
-
-        mUpdateMonitor = updateMonitor;
-
-        mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, updateMonitor,
-                lockPatternUtils, callback, true);
+        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) {
     }
 
@@ -122,7 +117,9 @@
     }
 
     public void onTextChanged(CharSequence s, int start, int before, int count) {
-        mCallback.pokeWakelock(AWAKE_POKE_MILLIS);
+        if (mCallback != null) {
+            mCallback.userActivity(AWAKE_POKE_MILLIS);
+        }
     }
 
     @Override
@@ -132,23 +129,17 @@
         return mLogin.requestFocus(direction, previouslyFocusedRect);
     }
 
-    /** {@inheritDoc} */
     public boolean needsInput() {
         return true;
     }
 
-    /** {@inheritDoc} */
-    public void onPause() {
-        mKeyguardStatusViewManager.onPause();
-    }
-
-    /** {@inheritDoc} */
-    public void onResume() {
+    public void reset() {
         // start fresh
         mLogin.setText("");
         mPassword.setText("");
         mLogin.requestFocus();
-        mKeyguardStatusViewManager.onResume();
+        mNavigationManager.setMessage(mLockPatternUtils.isPermanentlyLocked() ?
+                R.string.kg_login_too_many_attempts : R.string.kg_login_instructions);
     }
 
     /** {@inheritDoc} */
@@ -156,15 +147,12 @@
         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();
+        mCallback.userActivity(0);
         if (v == mOk) {
             asyncCheckPassword();
         }
@@ -188,10 +176,10 @@
                     mContext.startActivity(intent);
                     mCallback.reportSuccessfulUnlockAttempt();
 
-                    // close the keyguard
-                    mCallback.keyguardDone(true);
+                    // dismiss keyguard
+                    mCallback.dismiss(true);
                 } else {
-                    mInstructions.setText(R.string.lockscreen_glogin_invalid_input);
+                    mNavigationManager.setMessage(R.string.kg_login_invalid_input);
                     mPassword.setText("");
                     mCallback.reportFailedUnlockAttempt();
                 }
@@ -204,9 +192,9 @@
         if (event.getAction() == KeyEvent.ACTION_DOWN
                 && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
             if (mLockPatternUtils.isPermanentlyLocked()) {
-                mCallback.goToLockScreen();
+                mCallback.dismiss(false);
             } else {
-                mCallback.forgotPattern(false);
+                // TODO: mCallback.forgotPattern(false);
             }
             return true;
         }
@@ -266,7 +254,7 @@
     }
 
     private void asyncCheckPassword() {
-        mCallback.pokeWakelock(AWAKE_POKE_MILLIS);
+        mCallback.userActivity(AWAKE_POKE_MILLIS);
         final String login = mLogin.getText().toString();
         final String password = mPassword.getText().toString();
         Account account = findIntendedAccount(login);
@@ -281,7 +269,7 @@
                 new AccountManagerCallback<Bundle>() {
             public void run(AccountManagerFuture<Bundle> future) {
                 try {
-                    mCallback.pokeWakelock(AWAKE_POKE_MILLIS);
+                    mCallback.userActivity(AWAKE_POKE_MILLIS);
                     final Bundle result = future.getResult();
                     final boolean verified = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT);
                     postOnCheckPasswordResult(verified);
@@ -306,7 +294,7 @@
         if (mCheckingDialog == null) {
             mCheckingDialog = new ProgressDialog(mContext);
             mCheckingDialog.setMessage(
-                    mContext.getString(R.string.lockscreen_glogin_checking_password));
+                    mContext.getString(R.string.kg_login_checking_password));
             mCheckingDialog.setIndeterminate(true);
             mCheckingDialog.setCancelable(false);
             mCheckingDialog.getWindow().setType(
@@ -314,4 +302,16 @@
         }
         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..843151b
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.LinearLayout;
+
+import com.android.internal.widget.LockPatternUtils;
+
+public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecurityView {
+
+    // Long enough to stay visible while dialer comes up
+    // Short enough to not be visible if the user goes back immediately
+    private static final int BIOMETRIC_AREA_EMERGENCY_DIALER_TIMEOUT = 1000;
+    private KeyguardSecurityCallback mKeyguardSecurityCallback;
+    private LockPatternUtils mLockPatternUtils;
+
+    public KeyguardFaceUnlockView(Context context) {
+        this(context, null);
+    }
+
+    public KeyguardFaceUnlockView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public void setKeyguardCallback(KeyguardSecurityCallback callback) {
+        mKeyguardSecurityCallback = callback;
+    }
+
+    @Override
+    public void setLockPatternUtils(LockPatternUtils utils) {
+        mLockPatternUtils = utils;
+    }
+
+    @Override
+    public void reset() {
+
+    }
+
+    @Override
+    public void onPause() {
+
+    }
+
+    @Override
+    public void onResume() {
+
+    }
+
+    @Override
+    public boolean needsInput() {
+        return false;
+    }
+
+    @Override
+    public KeyguardSecurityCallback getCallback() {
+        return mKeyguardSecurityCallback;
+    }
+
+    // TODO
+    //    public void onRefreshBatteryInfo(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;
+    //    }
+
+    // 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 (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);
+    //    }
+
+    //    /**
+    //     * 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 ShowingMode unlockMode = getUnlockMode();
+    //        final boolean backupIsTimedOut = (mUpdateMonitor.getFailedAttempts() >=
+    //                LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT);
+    //        return (mLockPatternUtils.usingBiometricWeak() &&
+    //                mLockPatternUtils.isBiometricWeakInstalled() &&
+    //                !mUpdateMonitor.getMaxBiometricUnlockAttemptsReached() &&
+    //                !backupIsTimedOut &&
+    //                (unlockMode == ShowingMode.Pattern || unlockMode == ShowingMode.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(
+    //                    com.android.internal.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();
+    //        }
+    //    }
+
+    //    /**
+    //     * 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/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
new file mode 100644
index 0000000..d74a5e7
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
@@ -0,0 +1,488 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.ActivityManager;
+import android.app.ActivityOptions;
+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.SharedPreferences;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.telephony.TelephonyManager;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AnimationUtils;
+import android.widget.Button;
+import android.widget.ViewFlipper;
+import android.widget.RemoteViews.OnClickHandler;
+
+import com.android.internal.policy.impl.keyguard.KeyguardSecurityModel.SecurityMode;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.R;
+
+import java.io.File;
+import java.util.ArrayList;
+
+public class KeyguardHostView extends KeyguardViewBase {
+    // Use this to debug all of keyguard
+    public static boolean DEBUG;
+
+    static final int APPWIDGET_HOST_ID = 0x4B455947;
+    private static final String KEYGUARD_WIDGET_PREFS = "keyguard_widget_prefs";
+
+    // 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 String TAG = "KeyguardViewHost";
+
+    private static final int SECURITY_SELECTOR_ID = R.id.keyguard_selector_view;
+    private static final int SECURITY_PATTERN_ID = R.id.keyguard_pattern_view;
+    private static final int SECURITY_PASSWORD_ID = R.id.keyguard_password_view;
+    private static final int SECURITY_BIOMETRIC_ID = R.id.keyguard_face_unlock_view;
+    private static final int SECURITY_SIM_PIN_ID = R.id.keyguard_sim_pin_view;
+    private static final int SECURITY_SIM_PUK_ID = R.id.keyguard_sim_puk_view;
+    private static final int SECURITY_ACCOUNT_ID = R.id.keyguard_account_view;
+
+    private AppWidgetHost mAppWidgetHost;
+    private KeyguardWidgetPager mAppWidgetContainer;
+    private ViewFlipper mViewFlipper;
+    private Button mEmergencyDialerButton;
+    private boolean mEnableMenuKey;
+    private boolean mScreenOn;
+    private boolean mIsVerifyUnlockOnly;
+    private int mCurrentSecurityId = SECURITY_SELECTOR_ID;
+
+    // KeyguardSecurityViews
+    final private int [] mViewIds = {
+        SECURITY_SELECTOR_ID,
+        SECURITY_PATTERN_ID,
+        SECURITY_PASSWORD_ID,
+        SECURITY_BIOMETRIC_ID,
+        SECURITY_SIM_PIN_ID,
+        SECURITY_SIM_PUK_ID,
+        SECURITY_ACCOUNT_ID,
+    };
+
+    private ArrayList<View> mViews = new ArrayList<View>(mViewIds.length);
+
+    protected Runnable mLaunchRunnable;
+
+    protected int mFailedAttempts;
+    private LockPatternUtils mLockPatternUtils;
+
+    private KeyguardSecurityModel mSecurityModel;
+
+    public KeyguardHostView(Context context) {
+        this(context, null);
+    }
+
+    public KeyguardHostView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mAppWidgetHost = new AppWidgetHost(mContext, APPWIDGET_HOST_ID, mOnClickHandler);
+        mSecurityModel = new KeyguardSecurityModel(mContext);
+
+        // The following enables the MENU key to work for testing automation
+        mEnableMenuKey = shouldEnableMenuKey();
+        setFocusable(true);
+        setFocusableInTouchMode(true);
+    }
+
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        super.dispatchDraw(canvas);
+        mCallback.keyguardDoneDrawing();
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        mAppWidgetContainer = (KeyguardWidgetPager) findViewById(R.id.app_widget_container);
+        mAppWidgetContainer.setVisibility(VISIBLE);
+
+        // View Flipper
+        mViewFlipper = (ViewFlipper) findViewById(R.id.view_flipper);
+        mViewFlipper.setInAnimation(AnimationUtils.loadAnimation(mContext,
+                R.anim.keyguard_security_animate_in));
+        mViewFlipper.setOutAnimation(AnimationUtils.loadAnimation(mContext,
+                R.anim.keyguard_security_animate_out));
+
+        // Initialize all security views
+        for (int i = 0; i < mViewIds.length; i++) {
+            View view = findViewById(mViewIds[i]);
+            mViews.add(view);
+            if (view != null) {
+                ((KeyguardSecurityView) view).setKeyguardCallback(mCallback);
+            } else {
+                Log.v("*********", "Can't find view id " + mViewIds[i]);
+            }
+        }
+
+        // Enable emergency dialer button
+        mEmergencyDialerButton = (Button) findViewById(R.id.emergency_call_button);
+        mEmergencyDialerButton.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                takeEmergencyCallAction();
+            }
+        });
+    }
+
+    void setLockPatternUtils(LockPatternUtils utils) {
+        mSecurityModel.setLockPatternUtils(utils);
+        mLockPatternUtils = utils;
+        for (int i = 0; i < mViews.size(); i++) {
+            KeyguardSecurityView ksv = (KeyguardSecurityView) mViews.get(i);
+            if (ksv != null) {
+                ksv.setLockPatternUtils(utils);
+            } else {
+                Log.w(TAG, "**** ksv was null at " + i);
+            }
+        }
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mAppWidgetHost.startListening();
+        populateWidgets();
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        mAppWidgetHost.stopListening();
+    }
+
+    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() {
+            // TODO
+            return false;
+        }
+
+        public void reportSuccessfulUnlockAttempt() {
+            KeyguardUpdateMonitor.getInstance(mContext).clearFailedAttempts();
+        }
+
+        public void reportFailedUnlockAttempt() {
+            // TODO: handle biometric attempt differently.
+            KeyguardUpdateMonitor.getInstance(mContext).reportFailedAttempt();
+        }
+
+        public int getFailedAttempts() {
+            return KeyguardUpdateMonitor.getInstance(mContext).getFailedAttempts();
+        }
+
+        public void showBackupUnlock() {
+            // TODO
+        }
+
+        public void keyguardDoneDrawing() {
+            mViewMediatorCallback.keyguardDoneDrawing();
+        }
+
+        @Override
+        public void setOnDismissRunnable(Runnable runnable) {
+            KeyguardHostView.this.setOnDismissRunnable(runnable);
+        }
+
+    };
+
+    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);
+        }
+    }
+
+    protected void showNextSecurityScreenOrFinish(boolean authenticated) {
+        boolean finish = false;
+        if (SECURITY_SELECTOR_ID == mCurrentSecurityId) {
+            int realSecurityId = getSecurityViewIdForMode(mSecurityModel.getSecurityMode());
+            if (realSecurityId == mCurrentSecurityId) {
+                finish = true; // no security required
+            } else {
+                showSecurityScreen(realSecurityId); // switch to the "real" security view
+            }
+        } else if (authenticated) {
+            if ((mCurrentSecurityId == SECURITY_PATTERN_ID
+                || mCurrentSecurityId == SECURITY_PASSWORD_ID
+                || mCurrentSecurityId == SECURITY_ACCOUNT_ID)) {
+                finish = true;
+            }
+        } else {
+            // Not authenticated but we were asked to dismiss so go back to selector screen.
+            showSecurityScreen(SECURITY_SELECTOR_ID);
+        }
+        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();
+                mViewFlipper.setDisplayedChild(0);
+                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() {
+        requestFocus();
+    }
+
+    /**
+     *  Sets a runnable to run when keyguard is dismissed
+     * @param runnable
+     */
+    protected void setOnDismissRunnable(Runnable runnable) {
+        mLaunchRunnable = runnable;
+    }
+
+    private KeyguardSecurityView getSecurityView(int securitySelectorId) {
+        final int children = mViewFlipper.getChildCount();
+        for (int child = 0; child < children; child++) {
+            if (mViewFlipper.getChildAt(child).getId() == securitySelectorId) {
+                return ((KeyguardSecurityView)mViewFlipper.getChildAt(child));
+            }
+        }
+        return null;
+    }
+
+    private void showSecurityScreen(int securityViewId) {
+
+        if (securityViewId == mCurrentSecurityId) return;
+
+        KeyguardSecurityView oldView = getSecurityView(mCurrentSecurityId);
+        KeyguardSecurityView newView = getSecurityView(securityViewId);
+
+        // Emulate Activity life cycle
+        oldView.onPause();
+        newView.onResume();
+
+        mViewMediatorCallback.setNeedsInput(newView.needsInput());
+        mCurrentSecurityId = securityViewId;
+
+        // Find and show this child.
+        final int childCount = mViewFlipper.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            if (securityViewId == mViewFlipper.getChildAt(i).getId()) {
+                mViewFlipper.setDisplayedChild(i);
+                break;
+            }
+        }
+    }
+
+    @Override
+    public void onScreenTurnedOn() {
+        if (DEBUG) Log.d(TAG, "screen on");
+        mScreenOn = true;
+        showSecurityScreen(mCurrentSecurityId);
+    }
+
+    @Override
+    public void onScreenTurnedOff() {
+        if (DEBUG) Log.d(TAG, "screen off");
+        mScreenOn = false;
+        showSecurityScreen(SECURITY_SELECTOR_ID);
+    }
+
+    @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(SECURITY_SELECTOR_ID);
+            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(getSecurityViewIdForMode(securityMode));
+        }
+    }
+
+    private int getSecurityViewIdForMode(SecurityMode securityMode) {
+        switch (securityMode) {
+            case None: return SECURITY_SELECTOR_ID;
+            case Pattern: return SECURITY_PATTERN_ID;
+            case Password: return SECURITY_PASSWORD_ID;
+            case Biometric: return SECURITY_BIOMETRIC_ID;
+            case Account: return SECURITY_ACCOUNT_ID;
+            case SimPin: return SECURITY_SIM_PIN_ID;
+            case SimPuk: return SECURITY_SIM_PUK_ID;
+        }
+        return 0;
+    }
+
+    private void addWidget(int appId) {
+        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
+        AppWidgetProviderInfo appWidgetInfo = appWidgetManager.getAppWidgetInfo(appId);
+        AppWidgetHostView view = getAppWidgetHost().createView(mContext, appId, appWidgetInfo);
+        addWidget(view);
+    }
+
+    private void populateWidgets() {
+        SharedPreferences prefs = mContext.getSharedPreferences(
+                KEYGUARD_WIDGET_PREFS, Context.MODE_PRIVATE);
+        for (String key : prefs.getAll().keySet()) {
+            int appId = prefs.getInt(key, -1);
+            if (appId != -1) {
+                Log.w(TAG, "populate: adding " + key);
+                addWidget(appId);
+            } else {
+                Log.w(TAG, "populate: can't find " + key);
+            }
+        }
+    }
+
+    @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(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/KeyguardNavigationManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardNavigationManager.java
new file mode 100644
index 0000000..d3feced
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardNavigationManager.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.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;
+
+    public KeyguardNavigationManager(KeyguardSecurityView view) {
+        mKeyguardSecurityView = view;
+        mMessageArea = (TextView) ((View) view).findViewById(R.id.message_area);
+        mMessageArea.setSelected(true); // Make marquee work
+        mMessageArea.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/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java
similarity index 68%
copy from policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
copy to policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java
index 203f9db..6938561 100644
--- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 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.
@@ -14,96 +14,98 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+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.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()
+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;
 
-    public PasswordUnlockScreen(Context context, Configuration configuration,
-            LockPatternUtils lockPatternUtils, KeyguardUpdateMonitor updateMonitor,
-            KeyguardScreenCallback callback) {
+    public KeyguardPasswordView(Context context) {
         super(context);
+    }
 
-        mCreationHardKeyboardHidden = configuration.hardKeyboardHidden;
-        mCreationOrientation = configuration.orientation;
-        mUpdateMonitor = updateMonitor;
+    public KeyguardPasswordView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public void setKeyguardCallback(KeyguardSecurityCallback callback) {
         mCallback = callback;
-        mLockPatternUtils = lockPatternUtils;
+    }
 
-        LayoutInflater layoutInflater = LayoutInflater.from(context);
-        if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) {
-            layoutInflater.inflate(R.layout.keyguard_screen_password_portrait, this, true);
+    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 {
-            layoutInflater.inflate(R.layout.keyguard_screen_password_landscape, this, true);
+            mNavigationManager.setMessage(
+                    mIsAlpha ? R.string.kg_password_instructions : R.string.kg_pin_instructions);
         }
+    }
 
-        mStatusViewManager = new KeyguardStatusViewManager(this, mUpdateMonitor, mLockPatternUtils,
-                mCallback, true);
+    @Override
+    protected void onFinishInflate() {
+        mLockPatternUtils = new LockPatternUtils(mContext); // TODO: use common one
 
-        final int quality = lockPatternUtils.getKeyguardStoredPasswordQuality();
+        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;
@@ -112,8 +114,9 @@
         mPasswordEntry = (EditText) findViewById(R.id.passwordEntry);
         mPasswordEntry.setOnEditorActionListener(this);
 
-        mKeyboardHelper = new PasswordEntryKeyboardHelper(context, mKeyboardView, this, false);
+        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
@@ -122,17 +125,16 @@
         } else {
             // Use lockscreen's numeric keyboard if the physical keyboard isn't showing
             mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
-            mKeyboardView.setVisibility(mCreationHardKeyboardHidden
+            mKeyboardView.setVisibility(getResources().getConfiguration().hardKeyboardHidden
                     == 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);
+            View pinDelete = findViewById(R.id.delete_button);
             if (pinDelete != null) {
                 pinDelete.setVisibility(View.VISIBLE);
                 imeOrDeleteButtonVisible = true;
                 pinDelete.setOnClickListener(new OnClickListener() {
-                    @Override
                     public void onClick(View v) {
                         mKeyboardHelper.handleBackspace();
                     }
@@ -147,22 +149,19 @@
             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();
+                mCallback.userActivity(0); // TODO: customize timeout for text?
             }
         });
+
         mPasswordEntry.addTextChangedListener(new TextWatcher() {
             public void onTextChanged(CharSequence s, int start, int before, int count) {
             }
@@ -171,9 +170,7 @@
             }
 
             public void afterTextChanged(Editable s) {
-                if (!mResuming) {
-                    mCallback.pokeWakelock();
-                }
+                mCallback.userActivity(0);
             }
         });
 
@@ -186,7 +183,7 @@
             imeOrDeleteButtonVisible = true;
             switchImeButton.setOnClickListener(new OnClickListener() {
                 public void onClick(View v) {
-                    mCallback.pokeWakelock(); // Leave the screen on a bit longer
+                    mCallback.userActivity(0); // Leave the screen on a bit longer
                     imm.showInputMethodPicker();
                 }
             });
@@ -257,61 +254,26 @@
         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();
+        boolean wrongPassword = true;
         if (mLockPatternUtils.checkPassword(entry)) {
-            mCallback.keyguardDone(true);
             mCallback.reportSuccessfulUnlockAttempt();
-            mStatusViewManager.setInstructionText(null);
             KeyStore.getInstance().password(entry);
+            mCallback.dismiss(true);
+            wrongPassword = false;
         } 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()
+            if (0 == (mCallback.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));
         }
+        mNavigationManager.setMessage(wrongPassword ?
+                (mIsAlpha ? R.string.kg_wrong_password : R.string.kg_wrong_pin) : 0);
         mPasswordEntry.setText("");
     }
 
@@ -325,52 +287,25 @@
             @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);
+                mNavigationManager.setMessage(
+                        R.string.kg_too_many_failed_attempts_countdown, secondsRemaining);
             }
 
             @Override
             public void onFinish() {
                 mPasswordEntry.setEnabled(true);
                 mKeyboardView.setEnabled(true);
-                mStatusViewManager.resetStatusInfo();
             }
         }.start();
     }
 
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
-        mCallback.pokeWakelock();
+        mCallback.userActivity(0);
         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
@@ -380,4 +315,26 @@
         }
         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..a95cfcb
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.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.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.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.LinearLayout;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternView;
+import com.android.internal.R;
+
+import java.io.IOException;
+import java.util.List;
+
+public class KeyguardPatternView extends LinearLayout implements KeyguardSecurityView {
+
+    private static final String TAG = "SecurityPatternView";
+    private static final boolean DEBUG = false;
+
+    // how long before we clear the wrong pattern
+    private static final int PATTERN_CLEAR_TIMEOUT_MS = 2000;
+
+    // how long we stay awake after each key beyond MIN_PATTERN_BEFORE_POKE_WAKELOCK
+    private static final int UNLOCK_PATTERN_WAKE_INTERVAL_MS = 7000;
+
+    // how long we stay awake after the user hits the first dot.
+    private static final int UNLOCK_PATTERN_WAKE_INTERVAL_FIRST_DOTS_MS = 2000;
+
+    // how many cells the user has to cross before we poke the wakelock
+    private static final int MIN_PATTERN_BEFORE_POKE_WAKELOCK = 2;
+
+    private int mFailedPatternAttemptsSinceLastTimeout = 0;
+    private int mTotalFailedPatternAttempts = 0;
+    private CountDownTimer mCountdownTimer = null;
+    private LockPatternUtils mLockPatternUtils;
+    private LockPatternView mLockPatternView;
+    private Button mForgotPatternButton;
+    private KeyguardSecurityCallback mCallback;
+    private boolean mEnableFallback;
+    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();
+        }
+    };
+
+    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.showBackupUnlock();
+            }
+        });
+
+        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) {
+        final 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();
+        }
+        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));
+            } 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();
+        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..36342a5
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityCallback.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 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 unlock for the current method.  If none available, this call is a NOP.
+     */
+    void showBackupUnlock();
+
+    /**
+     * Used to inform keyguard when the current view is done drawing.
+     */
+    void keyguardDoneDrawing();
+
+    /**
+     * Sets a runnable to launch after the user enters their
+     * @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..d041dd3
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityModel.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package 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;
+    }
+
+    SecurityMode getSecurityMode() {
+        KeyguardUpdateMonitor mUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
+        final IccCardConstants.State simState = mUpdateMonitor.getSimState();
+        if (simState == IccCardConstants.State.PIN_REQUIRED) {
+            return SecurityMode.SimPin;
+        } else if (simState == IccCardConstants.State.PUK_REQUIRED) {
+            return SecurityMode.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:
+                    return mLockPatternUtils.isLockPasswordEnabled() ?
+                            SecurityMode.Password : SecurityMode.None;
+
+                case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
+                case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
+                    if (mLockPatternUtils.isLockPatternEnabled()) {
+                        return mLockPatternUtils.isPermanentlyLocked() ?
+                            SecurityMode.Account : SecurityMode.Pattern;
+                    } else {
+                        return SecurityMode.None;
+                    }
+                default:
+                   throw new IllegalStateException("Unknown unlock mode:" + mode);
+            }
+        }
+    }
+
+    SecurityMode getBackupFor(SecurityMode mode) {
+        return SecurityMode.None;  // TODO: handle biometric unlock, etc.
+    }
+}
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/KeyguardSelectorView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
new file mode 100644
index 0000000..a38b247
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.policy.impl.keyguard;
+
+import android.animation.ObjectAnimator;
+import android.app.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.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.widget.LockPatternUtils;
+import com.android.internal.widget.multiwaveview.GlowPadView;
+import com.android.internal.widget.multiwaveview.GlowPadView.OnTriggerListener;
+import com.android.internal.R;
+
+public class KeyguardSelectorView extends LinearLayout implements KeyguardSecurityView {
+    private static final boolean DEBUG = KeyguardHostView.DEBUG;
+    private static final String TAG = "SecuritySelectorView";
+    private static final String ASSIST_ICON_METADATA_NAME =
+        "com.android.systemui.action_assist_icon";
+    private KeyguardSecurityCallback mCallback;
+    private GlowPadView mGlowPadView;
+    private 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() {
+
+        }
+
+    };
+
+    KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
+
+        private boolean mEmergencyDialerDisableBecauseSimLocked;
+
+        @Override
+        public void onDevicePolicyManagerStateChanged() {
+            updateTargets();
+        }
+
+        @Override
+        public void onSimStateChanged(IccCardConstants.State simState) {
+            // Some carriers aren't capable of handling emergency calls while the SIM is locked
+            mEmergencyDialerDisableBecauseSimLocked = KeyguardUpdateMonitor.isSimLocked(simState)
+                    && !mLockPatternUtils.isEmergencyCallEnabledWhileSimLocked();
+            updateTargets();
+        }
+
+        void onPhoneStateChanged(int phoneState) {
+            if (mEmergencyCallButton != null) {
+                mLockPatternUtils.isEmergencyCallEnabledWhileSimLocked();
+                mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton,
+                        phoneState, !mEmergencyDialerDisableBecauseSimLocked);
+            }
+        };
+    };
+
+    public KeyguardSelectorView(Context context) {
+        this(context, null);
+    }
+
+    protected void launchCamera() {
+        if (mLockPatternUtils.isSecure()) {
+            // Launch the secure version of the camera
+            launchActivity(new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE), 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);
+        KeyguardUpdateMonitor.getInstance(getContext()).registerCallback(mInfoCallback);
+        updateTargets();
+    }
+
+    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.setFlags(
+                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..294ea5c
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPinView.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package 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.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;
+
+    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();
+                }
+            });
+        }
+
+        setFocusableInTouchMode(true);
+        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 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 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 (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();
+
+        new CheckSimPin(mPinEntry.getText().toString()) {
+            void onSimLockChangedResponse(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(false); //
+                        } else {
+                            mNavigationManager.setMessage(R.string.kg_password_wrong_pin_code);
+                            mPinEntry.setText("");
+                        }
+                        mCallback.userActivity(0);
+                    }
+                });
+            }
+        }.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..801dfc3
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPukView.java
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.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;
+
+    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();
+
+        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("");
+                        }
+                    }
+                });
+            }
+        }.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 (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..d6ce967
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusView.java
@@ -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.
+ */
+
+package com.android.internal.policy.impl.keyguard;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.GridLayout;
+
+public class KeyguardStatusView extends GridLayout {
+    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.
+        new KeyguardStatusViewManager(this);
+    }
+
+}
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java
similarity index 72%
copy from policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
copy to policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java
index c1fd515..06ed88a 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java
@@ -14,17 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+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 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;
@@ -36,15 +32,13 @@
 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 {
+class KeyguardStatusViewManager {
     private static final boolean DEBUG = false;
     private static final String TAG = "KeyguardStatusView";
 
@@ -52,7 +46,6 @@
     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;
@@ -63,7 +56,6 @@
 
     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
@@ -72,7 +64,6 @@
     private TextView mStatus1View;
     private TextView mOwnerInfoView;
     private TextView mAlarmStatusView;
-    private TransportControlView mTransportView;
 
     // Top-level container view for above views
     private View mContainer;
@@ -91,8 +82,6 @@
 
     private LockPatternUtils mLockPatternUtils;
     private KeyguardUpdateMonitor mUpdateMonitor;
-    private Button mEmergencyCallButton;
-    private boolean mEmergencyButtonEnabledBecauseSimLocked;
 
     // Shadowed text values
     private CharSequence mCarrierText;
@@ -101,61 +90,15 @@
     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);
-        }
-    };
+    protected boolean mBatteryCharged;
+    protected boolean mBatteryIsLow;
+    private boolean mEmergencyButtonEnabledBecauseSimLocked;
+    private Button mEmergencyCallButton;
+    private boolean mEmergencyCallButtonEnabledInScreen;
 
     /**
      *
@@ -165,41 +108,22 @@
      * @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) {
+    public KeyguardStatusViewManager(View view) {
         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;
+        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.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);
+        // Registering this callback immediately updates the battery state, among other things.
+        mUpdateMonitor.registerCallback(mInfoCallback);
 
         resetStatusInfo();
         refreshDate();
@@ -215,10 +139,6 @@
         }
     }
 
-    private boolean inWidgetMode() {
-        return mTransportView != null && mTransportView.getVisibility() == View.VISIBLE;
-    }
-
     void setInstructionText(String string) {
         mInstructionText = string;
         update(INSTRUCTION_TEXT, string);
@@ -263,31 +183,12 @@
     }
 
     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);
-        }
+        updateStatusLines(mShowingStatus);
     }
 
     public void onPause() {
         if (DEBUG) Log.v(TAG, "onPause()");
         mUpdateMonitor.removeCallback(mInfoCallback);
-        mUpdateMonitor.removeCallback(mSimStateCallback);
     }
 
     /** {@inheritDoc} */
@@ -299,22 +200,12 @@
             mDigitalClock.updateTime();
         }
 
-        mUpdateMonitor.registerInfoCallback(mInfoCallback);
-        mUpdateMonitor.registerSimStateCallback(mSimStateCallback);
+        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;
-        mShowingBatteryInfo = mUpdateMonitor.shouldShowBatteryInfo();
-        mPluggedIn = mUpdateMonitor.isDevicePluggedIn();
-        mBatteryLevel = mUpdateMonitor.getBatteryLevel();
         updateStatusLines(true);
     }
 
@@ -367,9 +258,7 @@
     }
 
     private void updateCarrierText() {
-        if (!inWidgetMode() && mCarrierView != null) {
-            mCarrierView.setText(mCarrierText);
-        }
+        mCarrierView.setText(mCarrierText);
     }
 
     private CharSequence getAltTextMessage(MutableInt icon) {
@@ -379,14 +268,11 @@
         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);
-                }
+                // 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 (mBatteryLevel < KeyguardUpdateMonitor.LOW_BATTERY_THRESHOLD) {
+            } else if (mBatteryIsLow) {
                 // Battery is low
                 string = getContext().getString(R.string.lockscreen_low_battery);
                 icon.value = BATTERY_LOW_ICON;
@@ -406,20 +292,16 @@
         } 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);
-                }
+                // 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 (mBatteryLevel < KeyguardUpdateMonitor.LOW_BATTERY_THRESHOLD) {
+            } 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
+        } else if (mOwnerInfoView == null && mOwnerInfoText != null) {
             string = mOwnerInfoText;
         }
         return string;
@@ -629,14 +511,15 @@
         }
     }
 
-    private InfoCallbackImpl mInfoCallback = new InfoCallbackImpl() {
+    private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
 
         @Override
-        public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn,
-                int batteryLevel) {
-            mShowingBatteryInfo = showBatteryInfo;
-            mPluggedIn = pluggedIn;
-            mBatteryLevel = batteryLevel;
+        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));
         }
@@ -659,21 +542,12 @@
             updateEmergencyCallButtonState(phoneState);
         }
 
-    };
-
-    private SimStateCallback mSimStateCallback = new SimStateCallback() {
-
+        @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
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..dad0dff
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java
@@ -0,0 +1,710 @@
+/*
+ * 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.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.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 #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 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 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);
+                    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;
+        }
+
+        /**
+         * 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_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 = 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) {
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+            if (cb != null) {
+                cb.onUserSwitched(userId);
+            }
+        }
+    }
+
+    /**
+     * 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 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(new WeakReference<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);
+        } else {
+            if (DEBUG) Log.e(TAG, "Object tried to add another callback",
+                    new Exception("Called by"));
+        }
+
+        // Clean up any unused references
+        for (int i = mCallbacks.size() - 1; i >= 0; i--) {
+            if (mCallbacks.get(i).get() == null) {
+                mCallbacks.remove(i);
+            }
+        }
+    }
+
+    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 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/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewBase.java
similarity index 87%
copy from policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
copy to policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewBase.java
index 29a5573..ad5de0e 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewBase.java
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard;
 
 import android.content.Context;
-import android.content.Intent;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
 import android.graphics.PixelFormat;
@@ -29,15 +28,13 @@
 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.widget.LinearLayout;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Slog;
 
 /**
- * Base class for keyguard views.  {@link #reset} is where you should
+ * 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).
@@ -45,19 +42,20 @@
  * Handles intercepting of media keys that still work when the keyguard is
  * showing.
  */
-public abstract class KeyguardViewBase extends FrameLayout {
+public abstract class KeyguardViewBase extends LinearLayout {
 
     private static final int BACKGROUND_COLOR = 0x70000000;
-    private KeyguardViewCallback mCallback;
     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
-    Drawable mBackgroundDrawable = new Drawable() {
+    private static final Drawable mBackgroundDrawable = new Drawable() {
         @Override
         public void draw(Canvas canvas) {
             canvas.drawColor(BACKGROUND_COLOR, PorterDuff.Mode.SRC);
@@ -77,18 +75,17 @@
         }
     };
 
-    public KeyguardViewBase(Context context, KeyguardViewCallback callback) {
-        super(context);
-        mCallback = callback;
+    public KeyguardViewBase(Context context) {
+        this(context, null);
+    }
+
+    public KeyguardViewBase(Context context, AttributeSet attrs) {
+        super(context, attrs);
         resetBackground();
     }
 
     public void resetBackground() {
-        setBackgroundDrawable(mBackgroundDrawable);
-    }
-
-    public KeyguardViewCallback getCallback() {
-        return mCallback;
+        setBackground(mBackgroundDrawable);
     }
 
     /**
@@ -142,31 +139,12 @@
 
     @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),
@@ -267,4 +245,10 @@
         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/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
similarity index 71%
copy from policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
copy to policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
index fb6ff24..61003bf 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
@@ -14,26 +14,27 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard;
 
-import com.android.internal.R;
-
+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.graphics.Canvas;
 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 android.graphics.Color;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.R;
 
 /**
  * Manages creating, showing, hiding and resetting the keyguard.  Calls back
@@ -41,24 +42,22 @@
  * 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 {
+public class KeyguardViewManager {
     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 final KeyguardViewMediator.ViewMediatorCallback mViewMediatorCallback;
 
     private WindowManager.LayoutParams mWindowLayoutParams;
     private boolean mNeedsInput = false;
 
     private FrameLayout mKeyguardHost;
-    private KeyguardViewBase mKeyguardView;
+    private KeyguardHostView mKeyguardView;
 
     private boolean mScreenOn = false;
+    private LockPatternUtils mLockPatternUtils;
 
     public interface ShowListener {
         void onShown(IBinder windowToken);
@@ -68,34 +67,15 @@
      * @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,
-            KeyguardViewCallback callback, KeyguardViewProperties keyguardViewProperties,
-            KeyguardUpdateMonitor updateMonitor) {
+            KeyguardViewMediator.ViewMediatorCallback callback,
+            LockPatternUtils lockPatternUtils) {
         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();
-        }
+        mViewMediatorCallback = callback;
+        mLockPatternUtils = lockPatternUtils;
     }
 
     /**
@@ -105,46 +85,100 @@
     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();
-        boolean enableScreenRotation =
-                SystemProperties.getBoolean("lockscreen.rot_override",false)
-                || res.getBoolean(R.bool.config_enableLockScreenRotation);
+        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 KeyguardViewHost(mContext, mCallback);
+            mKeyguardHost = new ViewManagerHost(mContext);
 
-            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*/ ;
+                    | WindowManager.LayoutParams.FLAG_SLIPPERY;
+
             if (!mNeedsInput) {
                 flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
             }
-            if (ActivityManager.isHighEndGfx(((WindowManager)mContext.getSystemService(
-                    Context.WINDOW_SERVICE)).getDefaultDisplay())) {
+            if (ActivityManager.isHighEndGfx()) {
                 flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
             }
+
+            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, WindowManager.LayoutParams.TYPE_KEYGUARD,
-                    flags, PixelFormat.TRANSLUCENT);
+                    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(((WindowManager)mContext.getSystemService(
-                    Context.WINDOW_SERVICE)).getDefaultDisplay())) {
+            if (ActivityManager.isHighEndGfx()) {
                 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
                 lp.privateFlags |=
                         WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
             }
             lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY;
-            lp.setTitle("Keyguard");
+            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;
@@ -152,40 +186,7 @@
             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) {
@@ -198,7 +199,13 @@
                 mWindowLayoutParams.flags |=
                     WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
             }
-            mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
+
+            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");
+            }
         }
     }
 
@@ -233,7 +240,7 @@
                 // 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() {
+                    public void run() {
                         if (mKeyguardHost.getVisibility() == View.VISIBLE) {
                             showListener.onShown(mKeyguardHost.getWindowToken());
                         } else {
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
similarity index 85%
copy from policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
copy to policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
index 5fa6dbf..d6733ea 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard;
 
 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.Activity;
 import android.app.ActivityManagerNative;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
@@ -34,18 +34,19 @@
 import android.media.AudioManager;
 import android.media.SoundPool;
 import android.os.Handler;
-import android.os.LocalPowerManager;
+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.WindowManagerImpl;
+import android.view.WindowManager;
 import android.view.WindowManagerPolicy;
 
 
@@ -90,8 +91,7 @@
  * 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 {
+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;
@@ -158,10 +158,6 @@
     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;
 
@@ -216,8 +212,6 @@
 
     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
@@ -226,7 +220,6 @@
     private WindowManagerPolicy.OnKeyguardExitResult mExitSecureCallback;
 
     // the properties of the keyguard
-    private KeyguardViewProperties mKeyguardViewProperties;
 
     private KeyguardUpdateMonitor mUpdateMonitor;
 
@@ -257,7 +250,76 @@
      */
     private final float mLockSoundVolume;
 
-    InfoCallbackImpl mInfoCallback = new InfoCallbackImpl() {
+    /**
+     * 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();
+            }
+        }
+
+        @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() {
@@ -269,47 +331,133 @@
             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;
+            }
+        }
+
     };
 
-    public KeyguardViewMediator(Context context, PhoneWindowManager callback,
-            LocalPowerManager powerManager) {
-        mContext = context;
+    ViewMediatorCallback mViewMediatorCallback = new ViewMediatorCallback() {
+        public void pokeWakelock() {
+            KeyguardViewMediator.this.pokeWakelock();
+        }
 
-        mRealPowerManager = powerManager;
+        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);
         mWakeLock = mPM.newWakeLock(
-                PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
-                "keyguard");
+                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 = 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;
+        mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(DELAYED_KEYGUARD_ACTION));
 
-        mUpdateMonitor = new KeyguardUpdateMonitor(context);
+        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
 
-        mUpdateMonitor.registerInfoCallback(mInfoCallback);
+        mUpdateMonitor = KeyguardUpdateMonitor.getInstance(context);
 
-        mUpdateMonitor.registerSimStateCallback(this);
+        mLockPatternUtils = lockPatternUtils != null
+                ? lockPatternUtils : new LockPatternUtils(mContext);
 
-        mLockPatternUtils = new LockPatternUtils(mContext);
-        mKeyguardViewProperties
-                = new LockPatternKeyguardViewProperties(mLockPatternUtils, mUpdateMonitor);
+        WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
 
-        mKeyguardViewManager = new KeyguardViewManager(
-                context, WindowManagerImpl.getDefault(), this,
-                mKeyguardViewProperties, mUpdateMonitor);
+        mKeyguardViewManager = new KeyguardViewManager(context, wm, mViewMediatorCallback,
+                mLockPatternUtils);
 
         mUserPresentIntent = new Intent(Intent.ACTION_USER_PRESENT);
         mUserPresentIntent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
@@ -337,11 +485,7 @@
         }
         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);
+        mLockSoundVolume = (float)Math.pow(10, (float)lockSoundDefaultAttenuation/20);
     }
 
     /**
@@ -351,6 +495,7 @@
         synchronized (this) {
             if (DEBUG) Log.d(TAG, "onSystemReady");
             mSystemReady = true;
+            mUpdateMonitor.registerCallback(mUpdateCallback);
             doKeyguardLocked();
         }
     }
@@ -459,7 +604,6 @@
         synchronized (this) {
             if (DEBUG) Log.d(TAG, "setKeyguardEnabled(" + enabled + ")");
 
-
             mExternallyEnabled = enabled;
 
             if (!enabled && mShowing) {
@@ -728,123 +872,22 @@
         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();
+        return mLockPatternUtils.isSecure()
+            || KeyguardUpdateMonitor.getInstance(mContext).isSimPinSecure();
     }
 
-    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() {
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            if (Intent.ACTION_USER_SWITCHED.equals(action)) {
-                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 (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.
+                        // 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();
                     }
                 }
@@ -852,7 +895,6 @@
         }
     };
 
-
     /**
      * 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
@@ -935,36 +977,6 @@
         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);
@@ -992,22 +1004,13 @@
     }
 
     /**
-     * {@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() {
+    private Handler mHandler = new Handler(Looper.myLooper(), null, true /*async*/) {
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
@@ -1042,7 +1045,7 @@
                     handleKeyguardDoneDrawing();
                     return;
                 case KEYGUARD_DONE_AUTHENTICATING:
-                    keyguardDone(true);
+                    keyguardDone(true, true);
                     return;
                 case SET_HIDDEN:
                     handleSetHidden(msg.arg1 != 0);
@@ -1064,10 +1067,14 @@
         if (DEBUG) Log.d(TAG, "handleKeyguardDone");
         handleHide();
         if (wakeup) {
-            mPM.userActivity(SystemClock.uptimeMillis(), true);
+            mPM.wakeUp(SystemClock.uptimeMillis());
         }
         mWakeLock.release();
-        mContext.sendBroadcast(mUserPresentIntent);
+
+        if (!(mContext instanceof Activity)) {
+            final UserHandle currentUser = new UserHandle(mLockPatternUtils.getCurrentUser());
+            mContext.sendBroadcastAsUser(mUserPresentIntent, currentUser);
+        }
     }
 
     /**
@@ -1197,7 +1204,8 @@
         // 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);
+        // FIXME: Replace this with a new timeout control mechanism.
+        //mRealPowerManager.enableUserActivity(enabled);
         if (!enabled && mScreenOn) {
             // reinstate our short screen timeout policy
             pokeWakelock();
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..d778129
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.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.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 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(
+                    com.android.internal.R.drawable.kg_widget_overscroll_layer_left);
+            sRightOverscrollDrawable = res.getDrawable(
+                    com.android.internal.R.drawable.kg_widget_overscroll_layer_right);
+            sWidgetPagePadding =
+                    res.getDimensionPixelSize(com.android.internal.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 (left && mForegroundDrawable != sLeftOverscrollDrawable) {
+            mForegroundDrawable = sLeftOverscrollDrawable;
+        } else if (!left && mForegroundDrawable != sRightOverscrollDrawable) {
+            mForegroundDrawable = sRightOverscrollDrawable;
+        }
+
+        mForegroundAlpha = (int) Math.round((r * 255));
+        mForegroundDrawable.setAlpha(mForegroundAlpha);
+        invalidate();
+    }
+}
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..7d077e2
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.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.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);
+                    }
+                }
+
+                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..1b46efa
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java
@@ -0,0 +1,1704 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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) {
+    }
+
+    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/AccountUnlockScreen.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/AccountUnlockScreen.java
similarity index 99%
rename from policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java
rename to policy/src/com/android/internal/policy/impl/keyguard_obsolete/AccountUnlockScreen.java
index a4baeed..d6a31b8 100644
--- a/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/AccountUnlockScreen.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard_obsolete;
 
 import com.android.internal.R;
 import com.android.internal.widget.LockPatternUtils;
diff --git a/policy/src/com/android/internal/policy/impl/BiometricSensorUnlock.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/BiometricSensorUnlock.java
similarity index 97%
copy from policy/src/com/android/internal/policy/impl/BiometricSensorUnlock.java
copy to policy/src/com/android/internal/policy/impl/keyguard_obsolete/BiometricSensorUnlock.java
index f476f82..c38525e 100644
--- a/policy/src/com/android/internal/policy/impl/BiometricSensorUnlock.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/BiometricSensorUnlock.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard_obsolete;
 
 import android.view.View;
 
diff --git a/policy/src/com/android/internal/policy/impl/FaceUnlock.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/FaceUnlock.java
similarity index 99%
rename from policy/src/com/android/internal/policy/impl/FaceUnlock.java
rename to policy/src/com/android/internal/policy/impl/keyguard_obsolete/FaceUnlock.java
index fda3c9d..e4d9215 100644
--- a/policy/src/com/android/internal/policy/impl/FaceUnlock.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/FaceUnlock.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard_obsolete;
 
 import com.android.internal.R;
 import com.android.internal.policy.IFaceLockCallback;
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardScreen.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardScreen.java
similarity index 94%
rename from policy/src/com/android/internal/policy/impl/KeyguardScreen.java
rename to policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardScreen.java
index bbb6875..ba5b7ff 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardScreen.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardScreen.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard_obsolete;
 
 /**
  * Common interface of each {@link android.view.View} that is a screen of
@@ -27,7 +27,7 @@
      * keyboard to be displayed.
      */
     boolean needsInput();
-    
+
     /**
      * This screen is no longer in front of the user.
      */
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardScreenCallback.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardScreenCallback.java
similarity index 97%
rename from policy/src/com/android/internal/policy/impl/KeyguardScreenCallback.java
rename to policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardScreenCallback.java
index a843603..be505a1 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardScreenCallback.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardScreenCallback.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard_obsolete;
 
 import android.content.res.Configuration;
 
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardStatusViewManager.java
similarity index 92%
rename from policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
rename to policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardStatusViewManager.java
index c1fd515..409f87b 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardStatusViewManager.java
@@ -14,15 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+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 com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallbackImpl;
-import com.android.internal.policy.impl.KeyguardUpdateMonitor.SimStateCallback;
 
 import java.util.ArrayList;
 import java.util.Date;
@@ -107,6 +105,8 @@
     private CharSequence mSpn;
     protected int mPhoneState;
     private DigitalClock mDigitalClock;
+    protected boolean mBatteryCharged;
+    protected boolean mBatteryIsLow;
 
     private class TransientTextManager {
         private TextView mTextView;
@@ -198,8 +198,8 @@
 
         mTransientTextManager = new TransientTextManager(mCarrierView);
 
-        mUpdateMonitor.registerInfoCallback(mInfoCallback);
-        mUpdateMonitor.registerSimStateCallback(mSimStateCallback);
+        // Registering this callback immediately updates the battery state, among other things.
+        mUpdateMonitor.registerCallback(mInfoCallback);
 
         resetStatusInfo();
         refreshDate();
@@ -287,7 +287,6 @@
     public void onPause() {
         if (DEBUG) Log.v(TAG, "onPause()");
         mUpdateMonitor.removeCallback(mInfoCallback);
-        mUpdateMonitor.removeCallback(mSimStateCallback);
     }
 
     /** {@inheritDoc} */
@@ -299,8 +298,7 @@
             mDigitalClock.updateTime();
         }
 
-        mUpdateMonitor.registerInfoCallback(mInfoCallback);
-        mUpdateMonitor.registerSimStateCallback(mSimStateCallback);
+        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
@@ -312,9 +310,6 @@
 
     void resetStatusInfo() {
         mInstructionText = null;
-        mShowingBatteryInfo = mUpdateMonitor.shouldShowBatteryInfo();
-        mPluggedIn = mUpdateMonitor.isDevicePluggedIn();
-        mBatteryLevel = mUpdateMonitor.getBatteryLevel();
         updateStatusLines(true);
     }
 
@@ -379,14 +374,11 @@
         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);
-                }
+                // 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 (mBatteryLevel < KeyguardUpdateMonitor.LOW_BATTERY_THRESHOLD) {
+            } else if (mBatteryIsLow) {
                 // Battery is low
                 string = getContext().getString(R.string.lockscreen_low_battery);
                 icon.value = BATTERY_LOW_ICON;
@@ -406,14 +398,11 @@
         } 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);
-                }
+                // 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 (mBatteryLevel < KeyguardUpdateMonitor.LOW_BATTERY_THRESHOLD) {
+            } else if (mBatteryIsLow) {
                 // Battery is low
                 string = getContext().getString(R.string.lockscreen_low_battery);
                 icon.value = BATTERY_LOW_ICON;
@@ -629,14 +618,14 @@
         }
     }
 
-    private InfoCallbackImpl mInfoCallback = new InfoCallbackImpl() {
+    private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
 
-        @Override
-        public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn,
-                int batteryLevel) {
-            mShowingBatteryInfo = showBatteryInfo;
-            mPluggedIn = pluggedIn;
-            mBatteryLevel = batteryLevel;
+        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));
         }
@@ -659,10 +648,7 @@
             updateEmergencyCallButtonState(phoneState);
         }
 
-    };
-
-    private SimStateCallback mSimStateCallback = new SimStateCallback() {
-
+        @Override
         public void onSimStateChanged(IccCardConstants.State simState) {
             updateCarrierStateWithSimStatus(simState);
         }
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/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewBase.java
similarity index 99%
rename from policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
rename to policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewBase.java
index 29a5573..f9fe797 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewBase.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard_obsolete;
 
 import android.content.Context;
 import android.content.Intent;
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewCallback.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewCallback.java
similarity index 94%
rename from policy/src/com/android/internal/policy/impl/KeyguardViewCallback.java
rename to policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewCallback.java
index b376d65..4cc0f30 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewCallback.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewCallback.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard_obsolete;
 
 /**
- * The callback used by the keyguard view to tell the {@link KeyguardViewMediator} 
+ * The callback used by the keyguard view to tell the {@link KeyguardViewMediator}
  * various things.
  */
 public interface KeyguardViewCallback {
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewManager.java
similarity index 96%
rename from policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
rename to policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewManager.java
index fb6ff24..5dbef48 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewManager.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard_obsolete;
 
 import com.android.internal.R;
 
@@ -123,8 +123,7 @@
             if (!mNeedsInput) {
                 flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
             }
-            if (ActivityManager.isHighEndGfx(((WindowManager)mContext.getSystemService(
-                    Context.WINDOW_SERVICE)).getDefaultDisplay())) {
+            if (ActivityManager.isHighEndGfx()) {
                 flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
             }
             WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
@@ -132,8 +131,7 @@
                     flags, PixelFormat.TRANSLUCENT);
             lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
             lp.windowAnimations = com.android.internal.R.style.Animation_LockScreen;
-            if (ActivityManager.isHighEndGfx(((WindowManager)mContext.getSystemService(
-                    Context.WINDOW_SERVICE)).getDefaultDisplay())) {
+            if (ActivityManager.isHighEndGfx()) {
                 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
                 lp.privateFlags |=
                         WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
@@ -233,7 +231,7 @@
                 // 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() {
+                    public void run() {
                         if (mKeyguardHost.getVisibility() == View.VISIBLE) {
                             showListener.onShown(mKeyguardHost.getWindowToken());
                         } else {
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewMediator.java
similarity index 88%
rename from policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
rename to policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewMediator.java
index 5fa6dbf..641ee88 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewMediator.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard_obsolete;
 
 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
 
-import com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallbackImpl;
+import com.android.internal.policy.impl.PhoneWindowManager;
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.widget.LockPatternUtils;
 
@@ -34,18 +34,19 @@
 import android.media.AudioManager;
 import android.media.SoundPool;
 import android.os.Handler;
-import android.os.LocalPowerManager;
+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.WindowManagerImpl;
+import android.view.WindowManager;
 import android.view.WindowManagerPolicy;
 
 
@@ -90,8 +91,7 @@
  * 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 {
+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;
@@ -158,10 +158,6 @@
     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;
 
@@ -257,7 +253,38 @@
      */
     private final float mLockSoundVolume;
 
-    InfoCallbackImpl mInfoCallback = new InfoCallbackImpl() {
+    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() {
@@ -269,47 +296,91 @@
             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;
+            }
+        }
+
     };
 
-    public KeyguardViewMediator(Context context, PhoneWindowManager callback,
-            LocalPowerManager powerManager) {
+    public KeyguardViewMediator(Context context, PhoneWindowManager callback) {
         mContext = context;
-
-        mRealPowerManager = powerManager;
+        mCallback = callback;
         mPM = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
         mWakeLock = mPM.newWakeLock(
-                PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
-                "keyguard");
+                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 = 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;
+        mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(DELAYED_KEYGUARD_ACTION));
+
+        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
 
         mUpdateMonitor = new KeyguardUpdateMonitor(context);
 
-        mUpdateMonitor.registerInfoCallback(mInfoCallback);
-
-        mUpdateMonitor.registerSimStateCallback(this);
-
         mLockPatternUtils = new LockPatternUtils(mContext);
         mKeyguardViewProperties
                 = new LockPatternKeyguardViewProperties(mLockPatternUtils, mUpdateMonitor);
 
+        WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
         mKeyguardViewManager = new KeyguardViewManager(
-                context, WindowManagerImpl.getDefault(), this,
-                mKeyguardViewProperties, mUpdateMonitor);
+                context, wm, this, mKeyguardViewProperties, mUpdateMonitor);
 
         mUserPresentIntent = new Intent(Intent.ACTION_USER_PRESENT);
         mUserPresentIntent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
@@ -337,11 +408,7 @@
         }
         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);
+        mLockSoundVolume = (float)Math.pow(10, (float)lockSoundDefaultAttenuation/20);
     }
 
     /**
@@ -351,6 +418,7 @@
         synchronized (this) {
             if (DEBUG) Log.d(TAG, "onSystemReady");
             mSystemReady = true;
+            mUpdateMonitor.registerCallback(mUpdateCallback);
             doKeyguardLocked();
         }
     }
@@ -728,123 +796,21 @@
         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() {
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            if (Intent.ACTION_USER_SWITCHED.equals(action)) {
-                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 (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.
+                        // 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();
                     }
                 }
@@ -852,7 +818,6 @@
         }
     };
 
-
     /**
      * 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
@@ -1007,7 +972,7 @@
      * interacts with the keyguard ui should be posted to this handler, rather
      * than called directly.
      */
-    private Handler mHandler = new Handler() {
+    private Handler mHandler = new Handler(true /*async*/) {
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
@@ -1064,10 +1029,12 @@
         if (DEBUG) Log.d(TAG, "handleKeyguardDone");
         handleHide();
         if (wakeup) {
-            mPM.userActivity(SystemClock.uptimeMillis(), true);
+            mPM.wakeUp(SystemClock.uptimeMillis());
         }
         mWakeLock.release();
-        mContext.sendBroadcast(mUserPresentIntent);
+
+        final UserHandle currentUser = new UserHandle(mLockPatternUtils.getCurrentUser());
+        mContext.sendBroadcastAsUser(mUserPresentIntent, currentUser);
     }
 
     /**
@@ -1197,7 +1164,8 @@
         // 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);
+        // FIXME: Replace this with a new timeout control mechanism.
+        //mRealPowerManager.enableUserActivity(enabled);
         if (!enabled && mScreenOn) {
             // reinstate our short screen timeout policy
             pokeWakelock();
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewProperties.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewProperties.java
similarity index 96%
rename from policy/src/com/android/internal/policy/impl/KeyguardViewProperties.java
rename to policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewProperties.java
index 51b7f1e..676574d 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewProperties.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewProperties.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard_obsolete;
 
 import android.content.Context;
 
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardWindowController.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardWindowController.java
similarity index 93%
rename from policy/src/com/android/internal/policy/impl/KeyguardWindowController.java
rename to policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardWindowController.java
index 4ad48fb..98e3209 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardWindowController.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardWindowController.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard_obsolete;
 
 /**
  * Interface passed to the keyguard view, for it to call up to control
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardView.java
similarity index 98%
rename from policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
rename to policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardView.java
index 041211c..0ce87b1 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardView.java
@@ -14,16 +14,12 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard_obsolete;
 
 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;
@@ -40,10 +36,8 @@
 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;
@@ -449,9 +443,8 @@
         mWindowController = controller;
         mSuppressBiometricUnlock = sIsFirstAppearanceAfterBoot;
         sIsFirstAppearanceAfterBoot = false;
-        mPluggedIn = mUpdateMonitor.isDevicePluggedIn();
         mScreenOn = ((PowerManager)context.getSystemService(Context.POWER_SERVICE)).isScreenOn();
-        mUpdateMonitor.registerInfoCallback(mInfoCallback);
+        mUpdateMonitor.registerCallback(mInfoCallback);
 
         /**
          * We'll get key events the current screen doesn't use. see
@@ -692,17 +685,17 @@
         post(mRecreateRunnable);
     }
 
-    InfoCallbackImpl mInfoCallback = new InfoCallbackImpl() {
+    KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
 
         @Override
-        public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn,
-                int batteryLevel) {
+        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();
@@ -732,7 +725,7 @@
         }
 
         @Override
-        public void onUserChanged(int userId) {
+        public void onUserSwitched(int userId) {
             if (mBiometricUnlock != null) {
                 mBiometricUnlock.stop();
             }
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardViewProperties.java
similarity index 95%
rename from policy/src/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java
rename to policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardViewProperties.java
index 6d3c20a6..5d9cc8e 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardViewProperties.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard_obsolete;
 
 import com.android.internal.widget.LockPatternUtils;
 
@@ -58,7 +58,6 @@
         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/keyguard_obsolete/LockScreen.java
similarity index 95%
rename from policy/src/com/android/internal/policy/impl/LockScreen.java
rename to policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockScreen.java
index 26078ec..4e9a1f7 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockScreen.java
@@ -14,11 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard_obsolete;
 
 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;
@@ -34,6 +32,7 @@
 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;
@@ -86,7 +85,7 @@
     // Is there a vibrator
     private final boolean mHasVibrator;
 
-    InfoCallbackImpl mInfoCallback = new InfoCallbackImpl() {
+    KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
 
         @Override
         public void onRingerModeChanged(int state) {
@@ -102,9 +101,7 @@
             updateTargets();
         }
 
-    };
-
-    SimStateCallback mSimStateCallback = new SimStateCallback() {
+        @Override
         public void onSimStateChanged(IccCardConstants.State simState) {
             updateTargets();
         }
@@ -279,7 +276,8 @@
 
             // Update the search icon with drawable from the search .apk
             if (!mSearchDisabled) {
-                Intent intent = SearchManager.getAssistIntent(mContext);
+                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
@@ -313,7 +311,9 @@
             final int resId = mGlowPadView.getResourceIdForTarget(target);
             switch (resId) {
                 case com.android.internal.R.drawable.ic_action_assist_generic:
-                    Intent assistIntent = SearchManager.getAssistIntent(mContext);
+                    Intent assistIntent =
+                            ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+                            .getAssistIntent(mContext, UserHandle.USER_CURRENT);
                     if (assistIntent != null) {
                         launchActivity(assistIntent);
                     } else {
@@ -339,6 +339,10 @@
             }
         }
 
+        /**
+         * Launches the said intent for the current foreground user.
+         * @param intent
+         */
         private void launchActivity(Intent intent) {
             intent.setFlags(
                     Intent.FLAG_ACTIVITY_NEW_TASK
@@ -350,7 +354,7 @@
                 Log.w(TAG, "can't dismiss keyguard on launch");
             }
             try {
-                mContext.startActivity(intent);
+                mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
             } catch (ActivityNotFoundException e) {
                 Log.w(TAG, "Activity not found for intent + " + intent.getAction());
             }
@@ -526,7 +530,9 @@
         } else if (disabledBySimState) {
             Log.v(TAG, "Camera disabled by Sim State");
         }
-        boolean searchActionAvailable = SearchManager.getAssistIntent(mContext) != null;
+        boolean searchActionAvailable =
+                ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+                .getAssistIntent(mContext, UserHandle.USER_CURRENT) != null;
         mCameraDisabled = disabledByAdmin || disabledBySimState || !cameraTargetPresent;
         mSearchDisabled = disabledBySimState || !searchActionAvailable || !searchTargetPresent;
         mUnlockWidgetMethods.updateResources();
@@ -582,7 +588,6 @@
     /** {@inheritDoc} */
     public void onPause() {
         mUpdateMonitor.removeCallback(mInfoCallback);
-        mUpdateMonitor.removeCallback(mSimStateCallback);
         mStatusViewManager.onPause();
         mUnlockWidgetMethods.reset(false);
     }
@@ -597,8 +602,7 @@
     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);
+        mUpdateMonitor.registerCallback(mInfoCallback);
 
         mStatusViewManager.onResume();
         postDelayed(mOnResumePing, ON_RESUME_PING_DELAY);
@@ -607,7 +611,6 @@
     /** {@inheritDoc} */
     public void cleanUp() {
         mUpdateMonitor.removeCallback(mInfoCallback); // this must be first
-        mUpdateMonitor.removeCallback(mSimStateCallback);
         mUnlockWidgetMethods.cleanUp();
         mLockPatternUtils = null;
         mUpdateMonitor = null;
diff --git a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/PasswordUnlockScreen.java
similarity index 99%
rename from policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
rename to policy/src/com/android/internal/policy/impl/keyguard_obsolete/PasswordUnlockScreen.java
index 203f9db..87a7371 100644
--- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/PasswordUnlockScreen.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard_obsolete;
 
 import java.util.List;
 
diff --git a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/PatternUnlockScreen.java
similarity index 99%
rename from policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
rename to policy/src/com/android/internal/policy/impl/keyguard_obsolete/PatternUnlockScreen.java
index 9a6d2cc..6d5706b 100644
--- a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/PatternUnlockScreen.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard_obsolete;
 
 import android.content.Context;
 import android.content.res.Configuration;
diff --git a/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/SimPukUnlockScreen.java
similarity index 99%
rename from policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
rename to policy/src/com/android/internal/policy/impl/keyguard_obsolete/SimPukUnlockScreen.java
index 3b2a473..3c1703a 100644
--- a/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/SimPukUnlockScreen.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard_obsolete;
 
 import android.app.Dialog;
 import android.app.ProgressDialog;
diff --git a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/SimUnlockScreen.java
similarity index 99%
rename from policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
rename to policy/src/com/android/internal/policy/impl/keyguard_obsolete/SimUnlockScreen.java
index 80407f5..13c040c 100644
--- a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/SimUnlockScreen.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard_obsolete;
 
 import android.app.Dialog;
 import android.app.ProgressDialog;
diff --git a/policy/tests/src/com/android/internal/policy/impl/LockPatternKeyguardViewTest.java b/policy/tests/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardViewTest.java
similarity index 96%
rename from policy/tests/src/com/android/internal/policy/impl/LockPatternKeyguardViewTest.java
rename to policy/tests/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardViewTest.java
index 862e683..97c5672 100644
--- a/policy/tests/src/com/android/internal/policy/impl/LockPatternKeyguardViewTest.java
+++ b/policy/tests/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardViewTest.java
@@ -14,10 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy.impl;
+package com.android.internal.policy.impl.keyguard_obsolete;
 
 import android.content.Context;
-import com.android.internal.policy.impl.KeyguardViewCallback;
+
+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;
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 a0f549f..f6a2419 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..8604f95 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -1693,7 +1693,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 +1702,7 @@
         }
 
         if (MotionEvent::isTouchEvent(motionEntry->source, motionEntry->action)) {
-            eventType = POWER_MANAGER_TOUCH_EVENT;
+            eventType = USER_ACTIVITY_EVENT_TOUCH;
         }
         break;
     }
@@ -1711,7 +1711,7 @@
         if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) {
             return;
         }
-        eventType = POWER_MANAGER_BUTTON_EVENT;
+        eventType = USER_ACTIVITY_EVENT_BUTTON;
         break;
     }
     }
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index cd6a2ec..6d63998 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -2620,7 +2620,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));
@@ -3051,7 +3050,6 @@
         }
 
         // Orientation
-        mOrientationCenter = 0;
         mOrientationScale = 0;
         if (mHaveTilt) {
             mOrientedRanges.haveOrientation = true;
@@ -3067,10 +3065,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;
+                    }
                 }
             }
 
@@ -3284,6 +3285,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 +3407,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 +3960,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 +4057,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);
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index 122a2ab..6c06986 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -1162,6 +1162,7 @@
             SIZE_CALIBRATION_NONE,
             SIZE_CALIBRATION_GEOMETRIC,
             SIZE_CALIBRATION_DIAMETER,
+            SIZE_CALIBRATION_BOX,
             SIZE_CALIBRATION_AREA,
         };
 
@@ -1294,7 +1295,6 @@
 
     float mSizeScale;
 
-    float mOrientationCenter;
     float mOrientationScale;
 
     float mDistanceScale;
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/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..9b7be02 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;
@@ -303,7 +304,7 @@
             }
         }
     }
-    
+
     public void removeLocked(String packageName) {
         removeLocked(mRtcWakeupAlarms, packageName);
         removeLocked(mRtcAlarms, packageName);
@@ -327,6 +328,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.getTargetUid()) == userHandle) {
+                it.remove();
+            }
+        }
+    }
     
     public boolean lookForPackageLocked(String packageName) {
         return lookForPackageLocked(mRtcWakeupAlarms, packageName)
@@ -822,6 +846,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 +866,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..8e341df 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -177,7 +177,7 @@
         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);
     }
diff --git a/services/java/com/android/server/AppWidgetServiceImpl.java b/services/java/com/android/server/AppWidgetServiceImpl.java
index f9c432b..539e561 100644
--- a/services/java/com/android/server/AppWidgetServiceImpl.java
+++ b/services/java/com/android/server/AppWidgetServiceImpl.java
@@ -36,24 +36,26 @@
 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.IBinder;
 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 +190,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 +213,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 +236,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 +268,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 +286,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) {
@@ -479,7 +499,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 +507,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));
                 }
             }
         }
@@ -573,7 +593,7 @@
     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 +665,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 +756,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();
@@ -860,7 +880,7 @@
             intent.setComponent(p.info.provider);
             intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id.appWidgetId);
             intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
-            mContext.sendBroadcast(intent, mUserId);
+            mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId));
         }
     }
 
@@ -1006,7 +1026,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 +1205,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 +1213,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));
         }
     }
 
@@ -1355,7 +1375,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);
         }
@@ -1642,7 +1662,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 +1673,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 +1684,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 +1709,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 +1726,7 @@
                 if (p == null) {
                     if (addProviderLocked(ri)) {
                         keep.add(ai.name);
+                        providersUpdated = true;
                     }
                 } else {
                     Provider parsed = parseProviderInfoXml(component, ri);
@@ -1729,6 +1761,7 @@
                             }
                             // Now that we've told the host, push out an update.
                             sendUpdateIntentLocked(p, appWidgetIds);
+                            providersUpdated = true;
                         }
                     }
                 }
@@ -1741,17 +1774,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 +1807,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..8be0ba8 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -65,6 +65,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.os.WorkSource;
 import android.os.storage.IMountService;
 import android.provider.Settings;
@@ -4845,6 +4846,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 +4950,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 +5019,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..4192a93 100644
--- a/services/java/com/android/server/BatteryService.java
+++ b/services/java/com/android/server/BatteryService.java
@@ -68,7 +68,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 +93,7 @@
 
     private boolean mAcOnline;
     private boolean mUsbOnline;
+    private boolean mWirelessOnline;
     private int mBatteryStatus;
     private int mBatteryHealth;
     private boolean mBatteryPresent;
@@ -148,12 +149,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 +171,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 +200,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();
@@ -243,6 +253,8 @@
             mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
         } else if (mUsbOnline) {
             mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
+        } else if (mWirelessOnline) {
+            mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
         } else {
             mPlugType = BATTERY_PLUGGED_NONE;
         }
@@ -398,6 +410,7 @@
                     " temperature: " + mBatteryTemperature +
                     " technology: " + mBatteryTechnology +
                     " AC powered:" + mAcOnline + " USB powered:" + mUsbOnline +
+                    " Wireless powered:" + mWirelessOnline +
                     " icon:" + icon  + " invalid charger:" + mInvalidCharger);
         }
 
@@ -503,6 +516,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 +537,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 +619,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..4c98ac3
--- /dev/null
+++ b/services/java/com/android/server/BluetoothManagerService.java
@@ -0,0 +1,740 @@
+/*
+ * 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.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
+
+    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_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.System.getString(resolver,
+                Settings.System.AIRPLANE_MODE_RADIOS);
+        final String toggleableRadios = Settings.System.getString(resolver,
+                Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
+        boolean mIsAirplaneSensitive = airplaneModeRadios == null ? true :
+                airplaneModeRadios.contains(Settings.System.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.System.getInt(mContext.getContentResolver(),
+                Settings.System.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.sendBroadcast(intent,BLUETOOTH_PERM);
+                    }
+                    break;
+                }
+                case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED:
+                {
+                    if (DBG) Log.d(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED");
+                    sendBluetoothServiceDownCallback();
+                    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..0bf7aad 100644
--- a/services/java/com/android/server/ClipboardService.java
+++ b/services/java/com/android/server/ClipboardService.java
@@ -36,7 +36,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 +96,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,7 +115,7 @@
     }
 
     private PerUserClipboard getClipboard() {
-        return getClipboard(UserId.getCallingUserId());
+        return getClipboard(UserHandle.getCallingUserId());
     }
 
     private PerUserClipboard getClipboard(int userId) {
@@ -258,7 +258,7 @@
         PackageInfo pi;
         try {
             pi = mPm.getPackageInfo(pkg, 0);
-            if (!UserId.isSameApp(pi.applicationInfo.uid, uid)) {
+            if (!UserHandle.isSameApp(pi.applicationInfo.uid, uid)) {
                 throw new SecurityException("Calling uid " + uid
                         + " does not own package " + 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..8a1ac10 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;
@@ -69,6 +82,8 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 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 +91,23 @@
 
 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.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 +123,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 +145,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 +167,9 @@
      */
     private NetworkStateTracker mNetTrackers[];
 
+    /* Handles captive portal check on a network */
+    private CaptivePortalTracker mCaptivePortalTracker;
+
     /**
      * The link properties that define the current links
      */
@@ -186,95 +214,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 +344,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 +387,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 +502,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 +547,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 +608,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 +647,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 +669,7 @@
 
         return wimaxStateTracker;
     }
+
     /**
      * Sets the preferred network.
      * @param preference the new preference
@@ -630,7 +677,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 +797,9 @@
             info = new NetworkInfo(info);
             info.setDetailedState(DetailedState.BLOCKED, null, null);
         }
+        if (mLockdownTracker != null) {
+            info = mLockdownTracker.augmentNetworkInfo(info);
+        }
         return info;
     }
 
@@ -766,6 +817,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 +985,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 +1087,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 +1367,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 +1669,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 +1692,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 +1802,7 @@
         }
     }
 
-    private void sendConnectedBroadcast(NetworkInfo info) {
+    public void sendConnectedBroadcast(NetworkInfo info) {
         sendGeneralBroadcast(info, CONNECTIVITY_ACTION_IMMEDIATE);
         sendGeneralBroadcast(info, CONNECTIVITY_ACTION);
     }
@@ -1734,8 +1817,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 +1847,13 @@
         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);
+        mContext.sendOrderedBroadcast(intent, RECEIVE_DATA_ACTIVITY_CHANGE);
+    }
+
     /**
      * Called when an attempt to fail over to another network has failed.
      * @param info the {@link NetworkInfo} for the failed network
@@ -1779,6 +1874,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);
         }
@@ -1856,31 +1952,49 @@
         }
         // 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 +2007,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 +2028,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 +2040,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 +2337,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
@@ -2431,8 +2632,8 @@
     }
 
     // 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 +2669,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 +2686,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 +2702,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 +2786,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;
                 }
             }
         }
@@ -2907,11 +3134,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 +3191,7 @@
      */
     @Override
     public boolean protectVpn(ParcelFileDescriptor socket) {
+        throwIfLockdownEnabled();
         try {
             int type = mActiveDefaultNetwork;
             if (ConnectivityManager.isNetworkTypeValid(type)) {
@@ -2990,6 +3218,7 @@
      */
     @Override
     public boolean prepareVpn(String oldPackage, String newPackage) {
+        throwIfLockdownEnabled();
         return mVpn.prepare(oldPackage, newPackage);
     }
 
@@ -3002,18 +3231,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 +3257,7 @@
      */
     @Override
     public LegacyVpnInfo getLegacyVpnInfo() {
+        throwIfLockdownEnabled();
         return mVpn.getLegacyVpnInfo();
     }
 
@@ -3038,10 +3272,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 +3345,58 @@
             }
         }
     }
+
+    @Override
+    public boolean updateLockdownVpn() {
+        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+
+        // 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");
+        }
+    }
 }
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index ea19d6e..f966a33 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -1626,7 +1626,7 @@
             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 +1667,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) {
diff --git a/services/java/com/android/server/DeviceStorageMonitorService.java b/services/java/com/android/server/DeviceStorageMonitorService.java
index 0ed5189..9231674 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;
@@ -36,8 +40,10 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 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 +77,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 +102,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 +209,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 +235,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 +313,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 +349,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 +362,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();
@@ -435,4 +476,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..f1ff27f 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,15 @@
 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.provider.Settings;
-import android.server.BluetoothService;
+import android.service.dreams.IDreamManager;
 import android.util.Log;
 import android.util.Slog;
 
@@ -40,14 +45,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 +66,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 +79,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 +93,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 +106,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.sendStickyBroadcast(intent);
+            }
+        }
+    }
+
+    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/EventLogTags.logtags b/services/java/com/android/server/EventLogTags.logtags
index 41f7335..dd50beb 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)
 
 
 # ---------------------------
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index fdb278d..747cf0b 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 {
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..3a45720 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -16,27 +16,21 @@
 
 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 +39,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 +50,21 @@
 import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.SystemClock;
 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 +73,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 +85,260 @@
 /**
  * The service class that manages LocationProviders and issues location
  * updates and alerts.
- *
- * {@hide}
  */
-public class LocationManagerService extends ILocationManager.Stub implements Runnable {
+public class LocationManagerService extends ILocationManager.Stub implements Observer, 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();
+
+        synchronized (mLock) {
+            loadProvidersLocked();
+        }
+        mBlacklist = new LocationBlacklist(mContext, mLocationHandler);
+        mBlacklist.init();
+        mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
+        mLocationFudger = new LocationFudger();
+
+        // listen for settings changes
+        ContentResolver resolver = mContext.getContentResolver();
+        Cursor settingsCursor = resolver.query(Settings.Secure.CONTENT_URI, null,
+                "(" + NameValueTable.NAME + "=?)",
+                new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED}, null);
+        ContentQueryMap query = new ContentQueryMap(settingsCursor, NameValueTable.NAME, true,
+                mLocationHandler);
+        settingsCursor.close();
+        query.addObserver(this);
+        mPackageMonitor.register(mContext, Looper.myLooper(), true);
+    }
+
+    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");
+        }
+
+        updateProvidersLocked();
+    }
 
     /**
      * A wrapper class holding either an ILocationListener or a PendingIntent to receive
      * location updates.
      */
     private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
+        final int mUid;  // uid of receiver
+        final int mPid;  // pid of receiver
+        final String mPackageName;  // package name of receiver
+        final 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 +350,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 +380,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 +387,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 +403,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 +422,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 +437,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 +460,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 +475,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 +489,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 +502,7 @@
             }
         }
 
+        @Override
         public void onSendFinished(PendingIntent pendingIntent, Intent intent,
                 int resultCode, String resultData, Bundle resultExtras) {
             synchronized (this) {
@@ -437,6 +525,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 +543,25 @@
         }
     }
 
-    private final class SettingsObserver implements Observer {
-        public void update(Observable o, Object arg) {
-            synchronized (mLock) {
-                updateProvidersLocked();
-            }
+    /** Settings Observer callback */
+    @Override
+    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 +576,131 @@
         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;
-        }
-        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() {
@@ -997,16 +727,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 +748,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 +831,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 +882,256 @@
         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;
+        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) {
+        checkPermission();
+        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 +1150,7 @@
         return true;
     }
 
+    @Override
     public void removeGpsStatusListener(IGpsStatusListener listener) {
         synchronized (mLock) {
             try {
@@ -1416,14 +1161,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 +1177,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 +1291,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 +1309,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 +1338,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 +1382,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 +1399,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 +1504,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 +1520,7 @@
     }
 
 
+    @Override
     public String getFromLocationName(String locationName,
             double lowerLeftLatitude, double lowerLeftLongitude,
             double upperRightLatitude, double upperRightLongitude, int maxResults,
@@ -2205,12 +1546,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 +1559,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 +1589,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 +1618,7 @@
         }
     }
 
+    @Override
     public void clearTestProviderLocation(String provider) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2292,6 +1630,7 @@
         }
     }
 
+    @Override
     public void setTestProviderEnabled(String provider, boolean enabled) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2314,6 +1653,7 @@
         }
     }
 
+    @Override
     public void clearTestProviderEnabled(String provider) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2329,6 +1669,7 @@
         }
     }
 
+    @Override
     public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2340,6 +1681,7 @@
         }
     }
 
+    @Override
     public void clearTestProviderStatus(String provider) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
@@ -2351,119 +1693,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 +1708,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..bb5d552 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -48,7 +48,7 @@
 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;
@@ -1713,7 +1713,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 = " +
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..efa16af 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;
@@ -55,7 +56,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 +94,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 +127,7 @@
 
         public static final int InterfaceChange           = 600;
         public static final int BandwidthControl          = 601;
+        public static final int InterfaceClassActivity    = 613;
     }
 
     /**
@@ -151,7 +158,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 +301,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 +369,9 @@
                 }
             }
         }
+
+        // TODO: Push any existing firewall state
+        setFirewallEnabled(mFirewallEnabled || LockdownVpnTracker.isEnabled());
     }
 
     //
@@ -403,6 +443,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 +833,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 +1006,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 +1049,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 +1056,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 +1071,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 +1434,72 @@
         }
     }
 
-    /** {@inheritDoc} */
+    @Override
+    public void setFirewallEnabled(boolean enabled) {
+        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+        try {
+            mConnector.execute("firewall", enabled ? "enable" : "disable");
+            mFirewallEnabled = enabled;
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
+    @Override
+    public boolean isFirewallEnabled() {
+        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+        return mFirewallEnabled;
+    }
+
+    @Override
+    public void setFirewallInterfaceRule(String iface, boolean allow) {
+        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+        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) {
+        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+        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) {
+        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+        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) {
+        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+        Preconditions.checkState(mFirewallEnabled);
+        final String rule = allow ? ALLOW : DENY;
+        try {
+            mConnector.execute("firewall", "set_uid_rule", uid, rule);
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
+    @Override
     public void monitor() {
         if (mConnector != null) {
             mConnector.monitor();
@@ -1338,5 +1530,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..9b61ec4 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -48,11 +48,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 +63,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;
 
@@ -148,6 +149,8 @@
     private AtomicFile mPolicyFile;
     private HashSet<String> mBlockedPackages = new HashSet<String>();
 
+    private IDreamManager mSandman;
+
     private static final int DB_VERSION = 1;
 
     private static final String TAG_BODY = "notification-policy";
@@ -541,6 +544,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) {
+                    cancelAllNotificationsUser(userHandle);
+                }
             } else if (action.equals(Intent.ACTION_USER_PRESENT)) {
                 // turn off LED when user passes through lock screen
                 mNotificationLight.turnOff();
@@ -616,6 +624,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);
@@ -634,6 +643,8 @@
     void systemReady() {
         mAudioService = IAudioService.Stub.asInterface(
                 ServiceManager.getService(Context.AUDIO_SERVICE));
+        mSandman = IDreamManager.Stub.asInterface(
+                ServiceManager.getService("dreams"));
 
         // no beeping until we're basically done booting
         mSystemReady = true;
@@ -972,6 +983,16 @@
                         | Notification.FLAG_NO_CLEAR;
             }
 
+            // Stop screensaver if the notification has a full-screen intent.
+            // (like an incoming phone call)
+            if (notification.fullScreenIntent != null && mSandman != null) {
+                try {
+                    mSandman.awaken();
+                } catch (RemoteException e) {
+                    // noop
+                }
+            }
+
             if (notification.icon != 0) {
                 StatusBarNotification n = new StatusBarNotification(pkg, id, tag,
                         r.uid, r.initialPid, score, notification);
@@ -1234,6 +1255,29 @@
         }
     }
 
+    /**
+     * Cancels all notifications from a given user.
+     */
+    boolean cancelAllNotificationsUser(int userHandle) {
+        synchronized (mNotificationList) {
+            final int N = mNotificationList.size();
+            boolean canceledSomething = false;
+            for (int i = N-1; i >= 0; --i) {
+                NotificationRecord r = mNotificationList.get(i);
+                if (UserHandle.getUserId(r.uid) != userHandle) {
+                    continue;
+                }
+                canceledSomething = true;
+                mNotificationList.remove(i);
+                cancelNotificationLocked(r, false);
+            }
+            if (canceledSomething) {
+                updateLightsLocked();
+            }
+            return canceledSomething;
+        }
+    }
+
     @Deprecated
     public void cancelNotification(String pkg, int id) {
         cancelNotificationWithTag(pkg, null /* tag */, id);
@@ -1257,7 +1301,7 @@
 
     void checkCallerIsSystem() {
         int uid = Binder.getCallingUid();
-        if (uid == Process.SYSTEM_UID || uid == 0) {
+        if (UserHandle.getAppId(uid) == Process.SYSTEM_UID || uid == 0) {
             return;
         }
         throw new SecurityException("Disallowed call for uid " + uid);
@@ -1265,13 +1309,13 @@
 
     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)) {
+            if (!UserHandle.isSameApp(ai.uid, uid)) {
                 throw new SecurityException("Calling uid " + uid + " gave package"
                         + pkg + " which is owned by uid " + ai.uid);
             }
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/SystemServer.java b/services/java/com/android/server/SystemServer.java
index e55e7fe..48b1215 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;
@@ -36,14 +38,13 @@
 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;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
+import android.view.Display;
 import android.view.WindowManager;
 
 import com.android.internal.os.BinderInternal;
@@ -51,11 +52,15 @@
 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.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;
 
@@ -118,6 +123,7 @@
         ContentService contentService = null;
         LightsService lights = null;
         PowerManagerService power = null;
+        DisplayManagerService display = null;
         BatteryService battery = null;
         VibratorService vibrator = null;
         AlarmManagerService alarm = null;
@@ -131,11 +137,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,7 +149,52 @@
         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 {
             Slog.i(TAG, "Entropy Mixer");
             ServiceManager.addService("entropy", new EntropyMixer());
@@ -155,6 +206,10 @@
             Slog.i(TAG, "Activity Manager");
             context = ActivityManagerService.main(factoryTest);
 
+            Slog.i(TAG, "Display Manager");
+            display = new DisplayManagerService(context, uiHandler);
+            ServiceManager.addService(Context.DISPLAY_SERVICE, display, true);
+
             Slog.i(TAG, "Telephony Registry");
             ServiceManager.addService("telephony.registry", new TelephonyRegistry(context));
 
@@ -164,10 +219,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;
@@ -186,6 +245,11 @@
             }
 
             ActivityManagerService.setSystemProcess();
+            
+            Slog.i(TAG, "User Service");
+            ServiceManager.addService(Context.USER_SERVICE,
+                    UserManagerService.getInstance());
+
 
             mContentResolver = context.getContentResolver();
 
@@ -218,7 +282,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 +294,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);
@@ -246,23 +312,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) {
@@ -555,7 +607,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 +639,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 +769,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,16 +793,22 @@
         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.
@@ -750,6 +821,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 +835,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
@@ -811,6 +882,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 +952,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..087e8db 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -35,6 +35,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 +110,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 +243,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 +337,7 @@
         broadcastSignalStrengthChanged(signalStrength);
     }
 
-    public void notifyCellInfo(CellInfo cellInfo) {
+    public void notifyCellInfo(List<CellInfo> cellInfo) {
         if (!checkNotifyPermission("notifyCellInfo()")) {
             return;
         }
@@ -346,7 +347,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);
                     }
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index f35a5af..98e6dc0 100644
--- a/services/java/com/android/server/ThrottleService.java
+++ b/services/java/com/android/server/ThrottleService.java
@@ -195,6 +195,7 @@
 
         public void interfaceRemoved(String iface) {}
         public void limitReached(String limitName, String iface) {}
+        public void interfaceClassDataActivityChanged(String label, boolean active) {}
     }
 
 
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..617b29d 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,33 @@
 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.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 +83,6 @@
 
     private NotificationManager mNotificationManager;
 
-    private AlarmManager mAlarmManager;
-
-    private LocationManager mLocationManager;
-    private Location mLocation;
     private StatusBarManager mStatusBarManager;
     private final PowerManager.WakeLock mWakeLock;
 
@@ -206,15 +179,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 +200,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 +235,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 +296,8 @@
         synchronized (mLock) {
             mSystemReady = true;
             mCarModeEnabled = mDockState == Intent.EXTRA_DOCK_STATE_CAR;
+            updateComputedNightModeLocked();
             updateLocked(0, 0);
-            mHandler.sendEmptyMessage(MSG_ENABLE_LOCATION_UPDATES);
         }
     }
 
@@ -467,7 +344,7 @@
         }
         if (mCarModeEnabled) {
             if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
-                updateTwilightLocked();
+                updateComputedNightModeLocked();
                 uiMode |= mComputedNightMode ? Configuration.UI_MODE_NIGHT_YES
                         : Configuration.UI_MODE_NIGHT_NO;
             } else {
@@ -651,189 +528,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 +566,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/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index 8a08277..7ed698b 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -19,6 +19,7 @@
 import static android.os.FileObserver.*;
 import static android.os.ParcelFileDescriptor.*;
 
+import android.app.AppGlobals;
 import android.app.IWallpaperManager;
 import android.app.IWallpaperManagerCallback;
 import android.app.PendingIntent;
@@ -31,6 +32,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;
@@ -48,7 +50,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;
@@ -146,6 +148,7 @@
 
     final Context mContext;
     final IWindowManager mIWindowManager;
+    final IPackageManager mIPackageManager;
     final MyPackageMonitor mMonitor;
     WallpaperData mLastWallpaper;
 
@@ -389,6 +392,7 @@
         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();
@@ -423,9 +427,9 @@
             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));
+                    switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
                 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
-                    removeUser(intent.getIntExtra(Intent.EXTRA_USERID, 0));
+                    removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
                 }
             }
         }, userFilter);
@@ -484,7 +488,7 @@
     public void clearWallpaper() {
         if (DEBUG) Slog.v(TAG, "clearWallpaper");
         synchronized (mLock) {
-            clearWallpaperLocked(false, UserId.getCallingUserId());
+            clearWallpaperLocked(false, UserHandle.getCallingUserId());
         }
     }
 
@@ -521,7 +525,7 @@
     public void setDimensionHints(int width, int height) throws RemoteException {
         checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
 
-        int userId = UserId.getCallingUserId();
+        int userId = UserHandle.getCallingUserId();
         WallpaperData wallpaper = mWallpaperMap.get(userId);
         if (wallpaper == null) {
             throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
@@ -552,14 +556,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 +578,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 +601,7 @@
     }
 
     public WallpaperInfo getWallpaperInfo() {
-        int userId = UserId.getCallingUserId();
+        int userId = UserHandle.getCallingUserId();
         synchronized (mLock) {
             WallpaperData wallpaper = mWallpaperMap.get(userId);
             if (wallpaper.connection != null) {
@@ -609,7 +613,7 @@
 
     public ParcelFileDescriptor setWallpaper(String name) {
         if (DEBUG) Slog.v(TAG, "setWallpaper");
-        int userId = UserId.getCallingUserId();
+        int userId = UserHandle.getCallingUserId();
         WallpaperData wallpaper = mWallpaperMap.get(userId);
         if (wallpaper == null) {
             throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
@@ -656,7 +660,7 @@
 
     public void setWallpaperComponent(ComponentName name) {
         if (DEBUG) Slog.v(TAG, "setWallpaperComponent name=" + name);
-        int userId = UserId.getCallingUserId();
+        int userId = UserHandle.getCallingUserId();
         WallpaperData wallpaper = mWallpaperMap.get(userId);
         if (wallpaper == null) {
             throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
@@ -710,8 +714,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 +733,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,11 +774,6 @@
             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(
@@ -804,8 +806,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);
             }
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java
index c14e2f6..2c5038e 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;
@@ -351,7 +352,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..6bc5e10 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -58,6 +58,7 @@
 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 +111,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;
@@ -161,6 +158,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 +240,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 +249,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 +303,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 +412,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();
                         }
                     }
@@ -430,6 +437,44 @@
         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
@@ -541,16 +586,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 +607,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.
@@ -874,7 +917,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 +927,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 +970,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);
@@ -1011,12 +1054,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,
@@ -1207,13 +1244,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 +1363,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 +1373,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;
         }
     }
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..fc774d4 100644
--- a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -16,13 +16,12 @@
 
 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;
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index e42ec84..857334e 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -58,6 +58,7 @@
 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;
@@ -74,7 +75,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;
 
@@ -157,7 +157,7 @@
 
     private boolean mIsTouchExplorationEnabled;
 
-    private final WindowManagerService mWindowManagerService;
+    private final IWindowManager mWindowManager;
 
     private final SecurityPolicy mSecurityPolicy;
 
@@ -181,8 +181,7 @@
     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();
         registerPackageChangeAndBootCompletedBroadcastReceiver();
@@ -358,8 +357,7 @@
                         // We will update when the automation service dies.
                         if (mUiAutomationService == null) {
                             populateTouchExplorationGrantedAccessibilityServicesLocked();
-                            unbindAllServicesLocked();
-                            manageServicesLocked();
+                            handleTouchExplorationGrantedAccessibilityServicesChangedLocked();
                         }
                     }
                 }
@@ -584,15 +582,21 @@
      *
      * @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 {
+                mWindowManager.getWindowFrame(token, outBounds);
+                return true;
+            } catch (RemoteException re) {
+                /* ignore */
+            }
+            return false;
         }
     }
 
-    int getActiveWindowId() {
+    public int getActiveWindowId() {
         return mSecurityPolicy.mActiveWindowId;
     }
 
@@ -624,7 +628,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;
             }
@@ -967,13 +971,21 @@
                 if (mInputFilter == null) {
                     mInputFilter = new AccessibilityInputFilter(mContext, this);
                 }
-                mWindowManagerService.setInputFilter(mInputFilter);
+                try {
+                    mWindowManager.setInputFilter(mInputFilter);
+                } catch (RemoteException re) {
+                    /* ignore */
+                }
             }
             return;
         }
         if (mHasInputFilter) {
             mHasInputFilter = false;
-            mWindowManagerService.setInputFilter(null);
+            try {
+                mWindowManager.setInputFilter(null);
+            } catch (RemoteException re) {
+                /* ignore */
+            }
         }
     }
 
@@ -1000,6 +1012,22 @@
                 Settings.Secure.TOUCH_EXPLORATION_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(
@@ -1163,8 +1191,6 @@
 
         boolean mCanRetrieveScreenContent;
 
-        boolean mReqeustTouchExplorationMode;
-
         boolean mIsAutomation;
 
         final Rect mTempBounds = new Rect();
@@ -1204,7 +1230,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 +1360,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 +1372,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 +1379,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 +1388,7 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return getCompatibilityScale(resolvedWindowId);
+            return 0;
         }
 
         @Override
@@ -1377,8 +1397,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 +1410,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 +1427,7 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return getCompatibilityScale(resolvedWindowId);
+            return 0;
         }
 
         @Override
@@ -1421,8 +1436,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 +1449,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 +1456,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 +1465,7 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return getCompatibilityScale(resolvedWindowId);
+            return 0;
         }
 
         @Override
@@ -1465,8 +1474,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 +1487,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 +1503,7 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return getCompatibilityScale(resolvedWindowId);
+            return 0;
         }
 
         @Override
@@ -1508,8 +1512,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 +1525,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 +1541,7 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return getCompatibilityScale(resolvedWindowId);
+            return 0;
         }
 
         @Override
@@ -1820,7 +1819,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 +1943,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/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index 48c6b2a..ba9f2cd 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -28,6 +28,7 @@
 import android.os.Handler;
 import android.os.SystemClock;
 import android.util.Slog;
+import android.view.InputFilter;
 import android.view.MotionEvent;
 import android.view.MotionEvent.PointerCoords;
 import android.view.MotionEvent.PointerProperties;
@@ -37,7 +38,6 @@
 import android.view.accessibility.AccessibilityEvent;
 
 import com.android.internal.R;
-import com.android.server.input.InputFilter;
 
 import java.util.ArrayList;
 import java.util.Arrays;
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..b0dfa80
--- /dev/null
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -0,0 +1,2145 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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 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;
+        }
+    }
+
+    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);
+        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 long origId = Binder.clearCallingIdentity();
+        try {
+            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) {
+                            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));
+        if (DEBUG_MU)
+            Slog.i(TAG_MU, "bindService uid=" + Binder.getCallingUid() + " origUid="
+                    + Binder.getOrigCallingUid());
+        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;
+        }
+        if (mAm.isSingleton(res.record.processName, res.record.appInfo,
+                res.record.serviceInfo.name, res.record.serviceInfo.flags)) {
+            userId = 0;
+            res = retrieveServiceLocked(service, resolvedType, Binder.getCallingPid(),
+                    Binder.getCallingUid(), 0, true);
+        }
+        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) {
+        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 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);
+
+        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;
+                }
+            }
+            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());
+        }
+    }
+
+    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);
+            }
+        }
+    }
+
+    boolean forceStopLocked(String name, int userId, boolean evenPersistent, boolean doit) {
+        boolean didSomething = false;
+        ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
+        for (ServiceRecord service : mServiceMap.getAllServices(userId)) {
+            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;
+                services.add(service);
+            }
+        }
+
+        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) {
+                List<UserInfo> users = mAm.getUserManager().getUsers();
+                for (int ui=0; ui<users.size() && res.size() < maxNum; ui++) {
+                    final UserInfo user = users.get(ui);
+                    if (mServiceMap.getAllServices(user.id).size() > 0) {
+                        Iterator<ServiceRecord> it = mServiceMap.getAllServices(
+                                user.id).iterator();
+                        while (it.hasNext() && res.size() < maxNum) {
+                            res.add(makeRunningServiceInfoLocked(it.next()));
+                        }
+                    }
+                }
+
+                for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
+                    ServiceRecord r = mRestartingServices.get(i);
+                    ActivityManager.RunningServiceInfo info =
+                            makeRunningServiceInfoLocked(r);
+                    info.restarting = r.nextRestartTime;
+                    res.add(info);
+                }
+            } 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 {
+            List<UserInfo> users = mAm.getUserManager().getUsers();
+            for (int ui=0; ui<users.size(); ui++) {
+                final UserInfo user = users.get(ui);
+                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) {
+                            if (ui > 0) {
+                                pw.println();
+                            }
+                            pw.println("  User " + user.id + " 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>();
+
+        List<UserInfo> users = mAm.getUserManager().getUsers();
+        if ("all".equals(name)) {
+            synchronized (this) {
+                for (UserInfo user : users) {
+                    for (ServiceRecord r1 : mServiceMap.getAllServices(user.id)) {
+                        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) {
+                }
+            }
+
+            synchronized (this) {
+                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);
+                        }
+                    }
+                }
+            }
+        }
+
+        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 73deef0..a061d58 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -46,12 +46,12 @@
 import android.app.INotificationManager;
 import android.app.IProcessObserver;
 import android.app.IServiceConnection;
+import android.app.IStopUserCallback;
 import android.app.IThumbnailReceiver;
 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 +76,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;
@@ -111,7 +111,8 @@
 import android.os.StrictMode;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.os.UserId;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.Settings;
 import android.text.format.Time;
 import android.util.EventLog;
@@ -144,7 +145,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;
@@ -242,31 +242,6 @@
     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;
 
@@ -454,6 +429,11 @@
     long mPreviousProcessVisibleTime;
 
     /**
+     * Which uses have been started, so are allowed to run code.
+     */
+    final SparseArray<UserStartedState> mStartedUsers = new SparseArray<UserStartedState>();
+
+    /**
      * Packages that the user has asked to have run in screen size
      * compatibility mode instead of filling the screen.
      */
@@ -514,6 +494,11 @@
         }
 
         @Override
+        protected BroadcastFilter[] newArray(int size) {
+            return new BroadcastFilter[size];
+        }
+
+        @Override
         protected String packageForFilter(BroadcastFilter filter) {
             return filter.packageName;
         }
@@ -527,35 +512,7 @@
     final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
             new 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
@@ -733,6 +690,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 +796,9 @@
     static ActivityManagerService mSelf;
     static ActivityThread mSystemThread;
 
+    private int mCurrentUserId;
+    private UserManager mUserManager;
+
     private final class AppDeathRecipient implements IBinder.DeathRecipient {
         final ProcessRecord mApp;
         final int mPid;
@@ -1010,10 +982,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) {
@@ -1115,7 +1087,7 @@
                     boolean restart = (msg.arg2 == 1);
                     String pkg = (String) msg.obj;
                     forceStopPackageLocked(pkg, uid, restart, false, true, false,
-                            UserId.getUserId(uid));
+                            UserHandle.getUserId(uid));
                 }
             } break;
             case FINALIZE_PENDING_INTENT_MSG: {
@@ -1284,7 +1256,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);
                         }
@@ -1521,6 +1494,8 @@
         mBroadcastQueues[0] = mFgBroadcastQueue;
         mBroadcastQueues[1] = mBgBroadcastQueue;
 
+        mServices = new ActiveServices(this);
+
         File dataDir = Environment.getDataDirectory();
         File systemDir = new File(dataDir, "system");
         systemDir.mkdirs();
@@ -1536,6 +1511,9 @@
                 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));
+
         GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
             ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
 
@@ -1857,7 +1835,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 +1970,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,10 +1986,21 @@
             int uid = app.uid;
 
             int[] gids = null;
+            int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
             if (!app.isolated) {
                 try {
-                    gids = mContext.getPackageManager().getPackageGids(
-                            app.info.packageName);
+                    final PackageManager pm = mContext.getPackageManager();
+                    gids = 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);
                 }
@@ -2053,7 +2042,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 +2084,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 +2096,7 @@
             }
         } catch (RuntimeException e) {
             // XXX do better error recovery.
-            app.pid = 0;
+            app.setPid(0);
             Slog.e(TAG, "Failure starting process " + app.processName, e);
         }
     }
@@ -2120,7 +2109,7 @@
         }
     }
 
-    boolean startHomeActivityLocked(int userId) {
+    boolean startHomeActivityLocked(int userId, UserStartedState startingUser) {
         if (mHeadless) {
             // Added because none of the other calls to ensureBootCompleted seem to fire
             // when running headless.
@@ -2160,6 +2149,9 @@
                         null, null, 0, 0, 0, 0, null, false, null);
             }
         }
+        if (startingUser != null) {
+            mMainStack.addStartingUserLocked(startingUser);
+        }
 
         return true;
     }
@@ -2223,7 +2215,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,19 +2343,48 @@
             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;
+        if (userId != UserHandle.getCallingUserId()) {
+            // Requesting a different user, make sure that they have the permission
+            if (checkComponentPermission(
+                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                    Binder.getCallingPid(), Binder.getCallingUid(), -1, true)
+                    == PackageManager.PERMISSION_GRANTED) {
+                // Translate to the current user id, if caller wasn't aware
+                if (userId == UserHandle.USER_CURRENT) {
+                    userId = mCurrentUserId;
+                }
             } else {
-                userId = Binder.getOrigCallingUser();
+                String msg = "Permission Denial: "
+                        + "Request to startActivity as user " + userId
+                        + " but is calling from user " + UserHandle.getCallingUserId()
+                        + "; this requires "
+                        + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+                Slog.w(TAG, msg);
+                throw new SecurityException(msg);
+            }
+        } else {
+            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();
+                }
             }
         }
         return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
@@ -2456,7 +2477,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;
@@ -2528,7 +2549,6 @@
         
         // This is so super not safe, that only the system (or okay root)
         // can do it.
-        int userId = Binder.getOrigCallingUser();
         final int callingUid = Binder.getCallingUid();
         if (callingUid != 0 && callingUid != Process.myUid()) {
             throw new SecurityException(
@@ -2537,7 +2557,7 @@
 
         int ret = mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
                 resultTo, resultWho, requestCode, startFlags,
-                null, null, null, null, options, userId);
+                null, null, null, null, options, UserHandle.getUserId(uid));
         return ret;
     }
 
@@ -2561,7 +2581,7 @@
                     "startActivityInPackage only available to the system");
         }
         int ret = mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo,
-                options, UserId.getUserId(uid));
+                options, UserHandle.getUserId(uid));
         return ret;
     }
 
@@ -3437,7 +3457,7 @@
             throw new SecurityException(msg);
         }
         
-        int userId = UserId.getCallingUserId();
+        int userId = UserHandle.getCallingUserId();
         long callingId = Binder.clearCallingIdentity();
         try {
             IPackageManager pm = AppGlobals.getPackageManager();
@@ -3451,7 +3471,7 @@
                     Slog.w(TAG, "Invalid packageName: " + packageName);
                     return;
                 }
-                killPackageProcessesLocked(packageName, pkgUid,
+                killPackageProcessesLocked(packageName, pkgUid, -1,
                         ProcessList.SERVICE_ADJ, false, true, true, false, "kill background");
             }
         } finally {
@@ -3511,7 +3531,7 @@
             Slog.w(TAG, msg);
             throw new SecurityException(msg);
         }
-        final int userId = UserId.getCallingUserId();
+        final int userId = UserHandle.getCallingUserId();
         long callingId = Binder.clearCallingIdentity();
         try {
             IPackageManager pm = AppGlobals.getPackageManager();
@@ -3647,7 +3667,8 @@
     }
 
     private void forceStopPackageLocked(final String packageName, int uid) {
-        forceStopPackageLocked(packageName, uid, false, false, true, false, UserId.getUserId(uid));
+        forceStopPackageLocked(packageName, 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 +3678,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 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, userId);
+    }
+
     private final boolean killPackageProcessesLocked(String packageName, int uid,
-            int minOomAdj, boolean callerWillRestart, boolean allowRestart, boolean doit,
-            boolean evenPersistent, String reason) {
+            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,6 +3713,18 @@
                     if (doit) {
                         procs.add(app);
                     }
+                // If no package is specified, we call all processes under the
+                // give user id.
+                } else if (packageName == null) {
+                    if (app.userId == userId) {
+                        if (app.setAdj >= minOomAdj) {
+                            if (!doit) {
+                                return true;
+                            }
+                            app.removed = true;
+                            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)
@@ -3711,7 +3755,7 @@
         int i;
         int N;
 
-        if (uid < 0) {
+        if (uid < 0 && name != null) {
             try {
                 uid = AppGlobals.getPackageManager().getPackageUid(name, userId);
             } catch (RemoteException e) {
@@ -3719,24 +3763,45 @@
         }
 
         if (doit) {
-            Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
+            if (name != null) {
+                Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
+            } 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 (entUid == uid) {
+                            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, uid,
+                name == null ? userId : -1 , -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);
+            final boolean samePackage = r.packageName.equals(name)
+                    || (name == null && r.userId == userId);
             if (r.userId == userId
                     && (samePackage || r.task == lastTask)
                     && (r.app == null || evenPersistent || !r.app.persistent)) {
@@ -3764,32 +3829,16 @@
             }
         }
 
-        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;
             }
-        }
-
-        N = services.size();
-        for (i=0; i<N; i++) {
-            bringDownServiceLocked(services.get(i), true);
+            didSomething = true;
         }
 
         ArrayList<ContentProviderRecord> providers = new ArrayList<ContentProviderRecord>();
         for (ContentProviderRecord provider : mProviderMap.getProvidersByClass(userId).values()) {
-            if (provider.info.packageName.equals(name)
+            if ((name == null || provider.info.packageName.equals(name))
                     && (provider.proc == null || evenPersistent || !provider.proc.persistent)) {
                 if (!doit) {
                     return true;
@@ -3805,7 +3854,7 @@
         }
 
         if (doit) {
-            if (purgeCache) {
+            if (purgeCache && name != null) {
                 AttributeCache ac = AttributeCache.instance();
                 if (ac != null) {
                     ac.removePackage(name);
@@ -3884,18 +3933,7 @@
             // 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 +4133,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 +4259,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 +4280,18 @@
                 // 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;
+                        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,
+                                mStartedUsers.keyAt(i));
+                    }
+                }
             }
         }
     }
@@ -4417,8 +4438,8 @@
             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()
@@ -4466,7 +4487,8 @@
 
         PendingIntentRecord.Key key = new PendingIntentRecord.Key(
                 type, packageName, activity, resultWho,
-                requestCode, intents, resolvedTypes, flags, options);
+                requestCode, intents, resolvedTypes, flags, options,
+                UserHandle.getUserId(callingUid));
         WeakReference<PendingIntentRecord> ref;
         ref = mIntentSenderRecords.get(key);
         PendingIntentRecord rec = ref != null ? ref.get() : null;
@@ -4514,8 +4536,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 +4756,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 +4766,7 @@
     int checkCallingPermission(String permission) {
         return checkPermission(permission,
                 Binder.getCallingPid(),
-                UserId.getAppId(Binder.getCallingUid()));
+                UserHandle.getAppId(Binder.getCallingUid()));
     }
 
     /**
@@ -4875,7 +4897,7 @@
             pid = tlsIdentity.pid;
         }
 
-        uid = UserId.getAppId(uid);
+        uid = UserHandle.getAppId(uid);
         // Our own process gets to do everything.
         if (pid == MY_PID) {
             return PackageManager.PERMISSION_GRANTED;
@@ -4921,13 +4943,13 @@
         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 +4961,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 +5253,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 +5589,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 +5619,7 @@
                     == PackageManager.PERMISSION_GRANTED;
 
             IPackageManager pm = AppGlobals.getPackageManager();
-            
+
             final int N = mRecentTasks.size();
             ArrayList<ActivityManager.RecentTaskInfo> res
                     = new ArrayList<ActivityManager.RecentTaskInfo>(
@@ -5590,7 +5627,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 +5655,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 +5726,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 +6070,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)
@@ -6221,7 +6247,7 @@
             }
 
             // First check if this content provider has been published...
-            int userId = UserId.getUserId(r != null ? r.uid : Binder.getCallingUid());
+            int userId = UserHandle.getUserId(r != null ? r.uid : Binder.getCallingUid());
             cpr = mProviderMap.getProviderByName(name, userId);
             boolean providerRunning = cpr != null;
             if (providerRunning) {
@@ -6296,6 +6322,7 @@
                 Binder.restoreCallingIdentity(origId);
             }
 
+            boolean singleton;
             if (!providerRunning) {
                 try {
                     cpi = AppGlobals.getPackageManager().
@@ -6306,7 +6333,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 +6354,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 +6380,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.
                     }
@@ -6766,7 +6805,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 +6813,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 +6851,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 "
@@ -7219,7 +7258,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;
@@ -8423,11 +8462,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 +8538,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 +8551,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 +8607,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 +8780,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 +8801,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 +8840,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 +9115,13 @@
         }
 
         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.println(":");
+            uss.dump("      ", pw);
+        }
         pw.println("  mHomeProcess: " + mHomeProcess);
         pw.println("  mPreviousProcess: " + mPreviousProcess);
         if (dumpAll) {
@@ -9134,7 +9198,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 +9280,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 +9479,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,7 +9520,7 @@
 
         needSep = true;
         
-        if (mStickyBroadcasts != null && dumpPackage == null) {
+        if (!onlyHistory && mStickyBroadcasts != null && dumpPackage == null) {
             if (needSep) {
                 pw.println();
             }
@@ -9594,7 +9552,7 @@
             needSep = true;
         }
         
-        if (dumpAll) {
+        if (!onlyHistory && dumpAll) {
             pw.println();
             for (BroadcastQueue queue : mBroadcastQueues) {
                 pw.println("  mBroadcastsScheduled [" + queue.mQueueName + "]="
@@ -9608,199 +9566,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 +9871,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 +10360,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 +10369,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 +10457,7 @@
         app.hasShownUi = false;
         app.hasAboveClient = false;
 
-        killServicesLocked(app, allowRestart);
+        mServices.killServicesLocked(app, allowRestart);
 
         boolean restart = false;
 
@@ -10972,806 +10619,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) {
@@ -11783,9 +10647,10 @@
         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;
         }
@@ -11797,60 +10662,26 @@
             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, UserHandle.getUserId(uid));
             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) {
@@ -11859,149 +10690,51 @@
         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);
-                        }
-                    }
-                    if (removeNotification) {
-                        r.cancelNotification();
-                        r.foregroundId = 0;
-                        r.foregroundNoti = null;
-                    }
-                }
-            }
-        }
-        } finally {
-            Binder.restoreCallingIdentity(origId);
+            mServices.setServiceForegroundLocked(className, token, id, notification,
+                    removeNotification);
         }
     }
 
-    public 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) {
-                updateOomAdjLocked();
-            }
-        }
-    }
-
-    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;
     }
@@ -12015,239 +10748,36 @@
             throw new IllegalArgumentException("File descriptors passed in Intent");
         }
 
-        checkValidCaller(Binder.getCallingUid(), userId);
+        if (userId != UserHandle.getCallingUserId()) {
+            // Requesting a different user, make sure that they have permission
+            if (checkComponentPermission(
+                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                    Binder.getCallingPid(), Binder.getCallingUid(), -1, true)
+                    == PackageManager.PERMISSION_GRANTED) {
+                // Translate to the current user id, if caller wasn't aware
+                if (userId == UserHandle.USER_CURRENT) {
+                    userId = mCurrentUserId;
+                }
+            } else {
+                String msg = "Permission Denial: Request to bindService as user " + userId
+                        + " but is calling from user " + UserHandle.getCallingUserId()
+                        + "; this requires "
+                        + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+                Slog.w(TAG, msg);
+                throw new SecurityException(msg);
+            }
+        }
 
         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) {
@@ -12260,53 +10790,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);
         }
     }
 
@@ -12317,38 +10801,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);
         }
     }
 
@@ -12357,137 +10810,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);
         }
     }
     
@@ -12513,7 +10836,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 "
@@ -12674,6 +10997,7 @@
     public Intent registerReceiver(IApplicationThread caller, String callerPackage,
             IIntentReceiver receiver, IntentFilter filter, String permission) {
         enforceNotIsolatedCaller("registerReceiver");
+        int callingUid;
         synchronized(this) {
             ProcessRecord callerApp = null;
             if (caller != null) {
@@ -12689,8 +11013,10 @@
                     throw new SecurityException("Given caller package " + callerPackage
                             + " is not running in process " + callerApp);
                 }
+                callingUid = callerApp.info.uid;
             } else {
                 callerPackage = null;
+                callingUid = Binder.getCallingUid();
             }
 
             List allSticky = null;
@@ -12735,7 +11061,8 @@
                 }
                 mRegisteredReceivers.put(receiver.asBinder(), rl);
             }
-            BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission);
+            BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
+                    permission, callingUid);
             rl.add(bf);
             if (!bf.debugCheck()) {
                 Slog.w(TAG, "==> For Dynamic broadast");
@@ -12754,7 +11081,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();
                 }
@@ -12846,7 +11173,40 @@
         if ((resultTo != null) && !ordered) {
             Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
         }
-        
+
+        // If the caller is trying to send this broadcast to a different
+        // user, verify that is allowed.
+        if (UserHandle.getUserId(callingUid) != userId) {
+            if (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) {
+                String msg = "Permission Denial: " + intent.getAction()
+                        + " broadcast from " + callerPackage
+                        + " asks to send as user " + userId
+                        + " but is calling from user " + UserHandle.getUserId(callingUid)
+                        + "; this requires "
+                        + android.Manifest.permission.INTERACT_ACROSS_USERS;
+                Slog.w(TAG, msg);
+                throw new SecurityException(msg);
+            } else {
+                if (userId == UserHandle.USER_CURRENT) {
+                    userId = mCurrentUserId;
+                }
+            }
+        }
+
+        // Make sure that the user who is receiving this broadcast is started
+        // If not, we will just skip it.
+        if (mStartedUsers.get(userId) == null) {
+            Slog.w(TAG, "Skipping broadcast of " + intent
+                    + ": user " + userId + " is stopped");
+            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.
@@ -12942,7 +11302,8 @@
          * processes) from sending protected broadcasts.
          */
         if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
-                || callingUid == Process.SHELL_UID || callingUid == 0) {
+            || callingUid == Process.SHELL_UID || callingUid == Process.BLUETOOTH_UID ||
+            callingUid == 0) {
             // Always okay.
         } else if (callerApp == null || !callerApp.persistent) {
             try {
@@ -13003,30 +11364,15 @@
         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);
+            // 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);
+            }
+            if (intent.getComponent() == null) {
+                registeredReceivers = mReceiverResolver.queryIntent(intent,
+                        resolvedType, false, userId);
             }
         } catch (RemoteException ex) {
             // pm is in same process, this will never happen.
@@ -13047,7 +11393,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);
@@ -13137,7 +11483,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());
@@ -13345,7 +11691,7 @@
                 throw new SecurityException(msg);
             }
 
-            int userId = UserId.getCallingUserId();
+            int userId = UserHandle.getCallingUserId();
             final long origId = Binder.clearCallingIdentity();
             // Instrumentation can kill and relaunch even persistent processes
             forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true, userId);
@@ -13403,12 +11749,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");
@@ -13721,7 +12067,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);
@@ -13773,14 +12119,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;
         }
@@ -13788,7 +12135,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;
@@ -13805,6 +12152,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;
@@ -13815,12 +12163,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;
                     }
                 }
             }
@@ -13829,6 +12180,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.
@@ -13844,6 +12196,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;
@@ -13865,21 +12218,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;
@@ -13896,6 +12241,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) {
@@ -13913,9 +12259,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.
@@ -14003,7 +12360,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.
@@ -14049,8 +12406,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
@@ -14066,7 +12431,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
@@ -14188,8 +12554,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) {
@@ -14602,9 +12976,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;
@@ -14614,7 +12989,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) {
@@ -14692,7 +13067,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;
@@ -14701,7 +13076,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) {
@@ -14729,34 +13105,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,
@@ -14764,8 +13159,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
@@ -14795,18 +13219,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;
@@ -15165,101 +13591,198 @@
 
     // 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)) {
-                    return false;
-                }
-                mLoggedInUsers.append(userId, userId);
+            if (mCurrentUserId == userId) {
+                return true;
+            }
+
+            // 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;
             boolean haveActivities = mMainStack.switchUser(userId);
             if (!haveActivities) {
-                startHomeActivityLocked(userId);
+                startHomeActivityLocked(userId, mStartedUsers.get(userId));
             }
-
         }
 
-        // 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);
+        long ident = Binder.clearCallingIdentity();
+        try {
+            // Inform of user switch
+            Intent addedIntent = new Intent(Intent.ACTION_USER_SWITCHED);
+            addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+            mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_USERS);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
 
         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 finishUserSwitch(UserStartedState uss) {
+        synchronized (this) {
+            if (uss.mState == UserStartedState.STATE_BOOTING
+                    && mStartedUsers.get(uss.mHandle.getIdentifier()) == uss) {
+                uss.mState = UserStartedState.STATE_RUNNING;
+                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, uss.mHandle.getIdentifier());
+            }
         }
-        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>>();
+    @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) {
-            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)));
-                    }
+            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) {
+                            finishUserStop(uss);
+                        }
+                    };
+                    broadcastIntentLocked(null, null, intent,
+                            null, resultReceiver, 0, null, null, null,
+                            true, false, MY_PID, Process.SYSTEM_UID, userId);
+                } finally {
+                    Binder.restoreCallingIdentity(ident);
                 }
             }
+        }
 
-            for (Pair<String,Integer> pkgAndUid : pkgAndUids) {
-                forceStopPackageLocked(pkgAndUid.first, pkgAndUid.second,
-                        false, false, true, true, extraUserId);
+        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 getUserManager().getUserInfo(mCurrentUserId);
+        }
     }
 
     private boolean userExists(int userId) {
-        try {
-            UserInfo user = AppGlobals.getPackageManager().getUser(userId);
-            return user != null;
-        } catch (RemoteException re) {
-            // Won't happen, in same process
-        }
+        UserInfo user = getUserManager().getUserInfo(userId);
+        return user != null;
+    }
 
-        return false;
+    UserManager getUserManager() {
+        if (mUserManager == null) {
+            mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        }
+        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);
@@ -15270,7 +13793,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;
         }
 
@@ -15278,86 +13801,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..c70650d 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;
@@ -614,14 +614,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 9171e47..a389edc2 100755
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -55,10 +55,11 @@
 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 +211,10 @@
      */
     final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible
             = new ArrayList<IActivityManager.WaitResult>();
-    
+
+    final ArrayList<UserStartedState> mStartingUsers
+            = new ArrayList<UserStartedState>();
+
     /**
      * Set when the system is going to sleep, until we have
      * successfully paused the current activity and released our wake lock.
@@ -500,7 +504,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 +548,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--) {
@@ -902,7 +906,7 @@
             mService.notifyAll();
         }
     }
-    
+
     public final Bitmap screenshotActivities(ActivityRecord who) {
         if (who.noDisplay) {
             return null;
@@ -919,7 +923,8 @@
         }
 
         if (w > 0) {
-            return mService.mWindowManager.screenshotApplications(who.appToken, w, h);
+            return mService.mWindowManager.screenshotApplications(who.appToken,
+                    Display.DEFAULT_DISPLAY, w, h);
         }
         return null;
     }
@@ -1395,7 +1400,7 @@
             // Launcher...
             if (mMainStack) {
                 ActivityOptions.abort(options);
-                return mService.startHomeActivityLocked(0);
+                return mService.startHomeActivityLocked(0, null);
             }
         }
 
@@ -1425,7 +1430,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);
@@ -1492,7 +1506,7 @@
                     Slog.d(TAG, "no-history finish of " + last + " on new resume");
                 }
                 requestFinishActivityLocked(last.appToken, Activity.RESULT_CANCELED, null,
-                "no-history");
+                        "no-history");
             }
         }
 
@@ -2404,7 +2418,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));
         }
@@ -3012,7 +3026,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);
@@ -3411,6 +3426,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;
@@ -3492,6 +3508,10 @@
                 booting = mService.mBooting;
                 mService.mBooting = false;
             }
+            if (mStartingUsers.size() > 0) {
+                startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
+                mStartingUsers.clear();
+            }
         }
 
         int i;
@@ -3536,6 +3556,10 @@
 
         if (booting) {
             mService.finishBooting();
+        } else if (startingUsers != null) {
+            for (i=0; i<startingUsers.size(); i++) {
+                mService.finishUserSwitch(startingUsers.get(i));
+            }
         }
 
         mService.trimApplications();
@@ -3553,6 +3577,10 @@
         return res;
     }
 
+    final void addStartingUserLocked(UserStartedState uss) {
+        mStartingUsers.add(uss);
+    }
+
     /**
      * @return Returns true if the activity is being finished, false if for
      * some reason it is being left as-is.
@@ -3900,7 +3928,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;
         }
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..4e6d0fa 100644
--- a/services/java/com/android/server/am/BroadcastFilter.java
+++ b/services/java/com/android/server/am/BroadcastFilter.java
@@ -27,13 +27,15 @@
     final ReceiverList receiverList;
     final String packageName;
     final String requiredPermission;
+    final int owningUid;
 
     BroadcastFilter(IntentFilter _filter, ReceiverList _receiverList,
-            String _packageName, String _requiredPermission) {
+            String _packageName, String _requiredPermission, int _owningUid) {
         super(_filter);
         receiverList = _receiverList;
         packageName = _packageName;
         requiredPermission = _requiredPermission;
+        owningUid = _owningUid;
     }
     
     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..34dec3a 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;
 
@@ -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());
             }
@@ -382,7 +385,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) {
@@ -649,6 +652,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 +667,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 +690,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 +739,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 +753,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 "
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..c80d63a 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;
     }
 
@@ -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..8e70376 100644
--- a/services/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/java/com/android/server/am/PendingIntentRecord.java
@@ -25,7 +25,7 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.util.Slog;
 
 import java.io.PrintWriter;
@@ -54,11 +54,12 @@
         String[] allResolvedTypes;
         final int flags;
         final int hashCode;
+        final int userId;
         
         private static final int ODD_PRIME_NUMBER = 37;
         
         Key(int _t, String _p, ActivityRecord _a, String _w,
-                int _r, Intent[] _i, String[] _it, int _f, Bundle _o) {
+                int _r, Intent[] _i, String[] _it, int _f, Bundle _o, int _userId) {
             type = _t;
             packageName = _p;
             activity = _a;
@@ -70,10 +71,12 @@
             allResolvedTypes = _it;
             flags = _f;
             options = _o;
-            
+            userId = _userId;
+
             int hash = 23;
             hash = (ODD_PRIME_NUMBER*hash) + _f;
             hash = (ODD_PRIME_NUMBER*hash) + _r;
+            hash = (ODD_PRIME_NUMBER*hash) + _userId;
             if (_w != null) {
                 hash = (ODD_PRIME_NUMBER*hash) + _w.hashCode();
             }
@@ -102,6 +105,9 @@
                 if (type != other.type) {
                     return false;
                 }
+                if (userId != other.userId){
+                    return false;
+                }
                 if (!packageName.equals(other.packageName)) {
                     return false;
                 }
@@ -156,7 +162,7 @@
                 + " intent="
                 + (requestIntent != null
                         ? requestIntent.toShortString(false, true, false, false) : "<null>")
-                + " flags=0x" + Integer.toHexString(flags) + "}";
+                + " flags=0x" + Integer.toHexString(flags) + " u=" + userId + "}";
         }
         
         String typeName() {
@@ -259,7 +265,7 @@
                             owner.broadcastIntentInPackage(key.packageName, uid,
                                     finalIntent, resolvedType,
                                     finishedReceiver, code, null, null,
-                                requiredPermission, (finishedReceiver != null), false, UserId
+                                requiredPermission, (finishedReceiver != null), false, UserHandle
                                         .getUserId(uid));
                             sendFinish = false;
                         } catch (RuntimeException 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..15fbb98 100644
--- a/services/java/com/android/server/am/ProviderMap.java
+++ b/services/java/com/android/server/am/ProviderMap.java
@@ -20,7 +20,7 @@
 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;
 
@@ -44,9 +44,9 @@
 
     private static final boolean DBG = false;
 
-    private final HashMap<String, ContentProviderRecord> mGlobalByName
+    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
@@ -63,7 +63,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 +81,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 +95,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,19 +108,19 @@
             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)) {
+        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 (DBG)
@@ -137,10 +137,10 @@
     }
 
     void removeProviderByClass(ComponentName name, int optionalUserId) {
-        if (mGlobalByClass.containsKey(name)) {
+        if (mSingletonByClass.containsKey(name)) {
             if (DBG)
                 Slog.i(TAG, "Removing from globalByClass name=" + name);
-            mGlobalByClass.remove(name);
+            mSingletonByClass.remove(name);
         } else {
             if (DBG)
                 Slog.i(TAG,
@@ -207,37 +207,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));
             }
         }
@@ -338,6 +330,4 @@
             }
         }
     }
-
-
 }
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 828eef7..5d60b9c 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -23,6 +23,7 @@
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -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,
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..e4f1f7a 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -319,6 +319,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;
@@ -501,8 +503,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 +1142,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 +1172,7 @@
             mSetDnsForwardersErrorState = new SetDnsForwardersErrorState();
             addState(mSetDnsForwardersErrorState);
 
-            mNotifyList = new ArrayList();
+            mNotifyList = new ArrayList<TetherInterfaceSM>();
             setInitialState(mInitialState);
         }
 
@@ -1362,8 +1369,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 +1387,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 +1430,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 +1579,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..d19fe01
--- /dev/null
+++ b/services/java/com/android/server/display/DisplayAdapter.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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 devices are not thread-safe and must only be accessed
+ * on the display manager service's handler thread.
+ * </p>
+ */
+public class DisplayAdapter {
+    private final Context mContext;
+    private final String mName;
+    private final Handler mHandler;
+    private Listener mListener;
+
+    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(Context context, String name) {
+        mContext = context;
+        mName = name;
+        mHandler = new Handler();
+    }
+
+    public final Context getContext() {
+        return mContext;
+    }
+
+    public final Handler getHandler() {
+        return mHandler;
+    }
+
+    /**
+     * Gets the display adapter name for debugging purposes.
+     *
+     * @return The display adapter name.
+     */
+    public final String getName() {
+        return mName;
+    }
+
+    /**
+     * Registers the display adapter with the display manager.
+     *
+     * @param listener The listener for callbacks.  The listener will
+     * be invoked on the display manager service's handler thread.
+     */
+    public final void register(Listener listener) {
+        mListener = listener;
+        onRegister();
+    }
+
+    /**
+     * Dumps the local state of the display adapter.
+     */
+    public void dump(PrintWriter pw) {
+    }
+
+    /**
+     * Called when the display adapter is registered.
+     *
+     * 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.
+     */
+    protected void onRegister() {
+    }
+
+    /**
+     * Sends a display device event to the display adapter listener asynchronously.
+     */
+    protected void sendDisplayDeviceEvent(final DisplayDevice device, final int event) {
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mListener.onDisplayDeviceEvent(device, event);
+            }
+        });
+    }
+
+    public interface Listener {
+        public void onDisplayDeviceEvent(DisplayDevice device, int event);
+    }
+}
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..c83ce96
--- /dev/null
+++ b/services/java/com/android/server/display/DisplayDevice.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 com.android.server.display;
+
+import android.os.IBinder;
+
+/**
+ * Represents a physical display device such as the built-in display
+ * an external monitor, or a WiFi display.
+ * <p>
+ * Display devices are not thread-safe and must only be accessed
+ * on the display manager service's handler thread.
+ * </p>
+ */
+public abstract class DisplayDevice {
+    private final DisplayAdapter mDisplayAdapter;
+    private final IBinder mDisplayToken;
+
+    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 getAdapter() {
+        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 getDisplayToken() {
+        return mDisplayToken;
+    }
+
+    /**
+     * Gets information about the display device.
+     *
+     * @param outInfo The object to populate with the information.
+     */
+    public abstract void getInfo(DisplayDeviceInfo outInfo);
+
+    // For debugging purposes.
+    @Override
+    public String toString() {
+        DisplayDeviceInfo info = new DisplayDeviceInfo();
+        getInfo(info);
+        return info.toString() + ", owner=\"" + mDisplayAdapter.getName() + "\"";
+    }
+}
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..c7b8c24
--- /dev/null
+++ b/services/java/com/android/server/display/DisplayDeviceInfo.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.server.display;
+
+/**
+ * Describes the characteristics of a physical display device.
+ */
+public final class DisplayDeviceInfo {
+    public static final int FLAG_DEFAULT_DISPLAY = 1 << 0;
+    public static final int FLAG_SECURE = 1 << 1;
+
+    /**
+     * 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;
+
+    public float refreshRate;
+    public int densityDpi;
+    public float xDpi;
+    public float yDpi;
+
+    public int flags;
+
+    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;
+    }
+
+    // For debugging purposes
+    @Override
+    public String toString() {
+        return "\"" + name + "\": " + width + " x " + height + ", " + refreshRate + " fps, "
+                + "density " + densityDpi + ", " + xDpi + " x " + yDpi + " dpi"
+                + flagsToString(flags);
+    }
+
+    private static String flagsToString(int flags) {
+        StringBuilder msg = new StringBuilder();
+        if ((flags & FLAG_DEFAULT_DISPLAY) != 0) {
+            msg.append(", FLAG_DEFAULT_DISPLAY");
+        }
+        if ((flags & FLAG_SECURE) != 0) {
+            msg.append(", FLAG_SECURE");
+        }
+        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..cf835ef
--- /dev/null
+++ b/services/java/com/android/server/display/DisplayManagerService.java
@@ -0,0 +1,598 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.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 android.view.Surface;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+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.DisplayAdapterListener} 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><p>
+ * To keep things simple, display adapters and display devices are single-threaded
+ * and are only accessed on the display manager's handler thread.  Of course, the
+ * display manager must be accessible by multiple thread (especially for
+ * incoming binder calls) so all of the display manager's state is synchronized
+ * and guarded by a lock.
+ * </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 final Object mLock = new Object();
+
+    private final Context mContext;
+    private final boolean mHeadless;
+
+    private final DisplayManagerHandler mHandler;
+    private final DisplayAdapterListener mDisplayAdapterListener = new DisplayAdapterListener();
+    private 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 logical displays, indexed by logical display id.
+    private final SparseArray<LogicalDisplay> mLogicalDisplays = new SparseArray<LogicalDisplay>();
+    private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1;
+
+    // True if in safe mode.
+    // This option may disable certain display adapters.
+    private 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.
+    private boolean mOnlyCore;
+
+    // Temporary callback list, used when sending display events to applications.
+    private ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>();
+
+    public DisplayManagerService(Context context, Handler uiHandler) {
+        mContext = context;
+        mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1");
+
+        mHandler = new DisplayManagerHandler(uiHandler.getLooper());
+        mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
+    }
+
+    /**
+     * Pauses the boot process to wait for the first display to be initialized.
+     */
+    public boolean waitForDefaultDisplay() {
+        synchronized (mLock) {
+            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 {
+                    mLock.wait(delay);
+                } catch (InterruptedException ex) {
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Called when the system is ready to go.
+     */
+    public void systemReady(boolean safeMode, boolean onlyCore) {
+        synchronized (mLock) {
+            mSafeMode = safeMode;
+            mOnlyCore = onlyCore;
+        }
+        mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
+    }
+
+    // Runs on handler.
+    private void registerDefaultDisplayAdapter() {
+        // Register default display adapter.
+        if (mHeadless) {
+            registerDisplayAdapter(new HeadlessDisplayAdapter(mContext));
+        } else {
+            registerDisplayAdapter(new LocalDisplayAdapter(mContext));
+        }
+    }
+
+    // Runs on handler.
+    private void registerAdditionalDisplayAdapters() {
+        if (shouldRegisterNonEssentialDisplayAdapters()) {
+            registerDisplayAdapter(new OverlayDisplayAdapter(mContext));
+        }
+    }
+
+    private boolean shouldRegisterNonEssentialDisplayAdapters() {
+        // 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.
+        synchronized (mLock) {
+            return !mSafeMode && !mOnlyCore;
+        }
+    }
+
+    // Runs on handler.
+    private void registerDisplayAdapter(DisplayAdapter adapter) {
+        synchronized (mLock) {
+            mDisplayAdapters.add(adapter);
+        }
+
+        adapter.register(mDisplayAdapterListener);
+    }
+
+    // FIXME: this isn't the right API for the long term
+    public void getDefaultExternalDisplayDeviceInfo(DisplayDeviceInfo info) {
+        // hardcoded assuming 720p touch screen plugged into HDMI and USB
+        // need to redesign this
+        info.width = 1280;
+        info.height = 720;
+    }
+
+    /**
+     * Returns true if the device is headless.
+     *
+     * @return True if the device is headless.
+     */
+    public boolean isHeadless() {
+        return mHeadless;
+    }
+
+    /**
+     * Sets the new logical display orientation.
+     *
+     * @param displayId The logical display id.
+     * @param orientation One of the Surface.ROTATION_* constants.
+     */
+    public void setDisplayOrientation(int displayId, int orientation) {
+        synchronized (mLock) {
+            // TODO: update mirror transforms
+            LogicalDisplay display = mLogicalDisplays.get(displayId);
+            if (display != null && display.mPrimaryDisplayDevice != null) {
+                IBinder displayToken = display.mPrimaryDisplayDevice.getDisplayToken();
+                if (displayToken != null) {
+                    Surface.openTransaction();
+                    try {
+                        Surface.setDisplayOrientation(displayToken, orientation);
+                    } finally {
+                        Surface.closeTransaction();
+                    }
+                }
+
+                display.mBaseDisplayInfo.rotation = orientation;
+                sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
+            }
+        }
+    }
+
+    /**
+     * 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.
+     *
+     * @param displayId The logical display id.
+     * @param info The new data to be stored.
+     */
+    public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) {
+        synchronized (mLock) {
+            LogicalDisplay display = mLogicalDisplays.get(displayId);
+            if (display != null) {
+                if (info != null) {
+                    if (display.mOverrideDisplayInfo == null) {
+                        display.mOverrideDisplayInfo = new DisplayInfo();
+                    }
+                    display.mOverrideDisplayInfo.copyFrom(info);
+                } else {
+                    display.mOverrideDisplayInfo = null;
+                }
+
+                sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
+            }
+        }
+    }
+
+    /**
+     * Returns information about the specified logical display.
+     *
+     * @param displayId The logical display id.
+     * @param The logical display info, or null if the display does not exist.
+     */
+    @Override // Binder call
+    public DisplayInfo getDisplayInfo(int displayId) {
+        synchronized (mLock) {
+            LogicalDisplay display = mLogicalDisplays.get(displayId);
+            if (display != null) {
+                if (display.mOverrideDisplayInfo != null) {
+                    return new DisplayInfo(display.mOverrideDisplayInfo);
+                }
+                return new DisplayInfo(display.mBaseDisplayInfo);
+            }
+            return null;
+        }
+    }
+
+    @Override // Binder call
+    public int[] getDisplayIds() {
+        synchronized (mLock) {
+            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 (mLock) {
+            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 (mLock) {
+            mCallbacks.remove(pid);
+        }
+    }
+
+    // Runs on handler.
+    private void handleDisplayDeviceAdded(DisplayDevice device) {
+        synchronized (mLock) {
+            if (mDisplayDevices.contains(device)) {
+                Slog.w(TAG, "Attempted to add already added display device: " + device);
+                return;
+            }
+
+            mDisplayDevices.add(device);
+
+            LogicalDisplay display = new LogicalDisplay(device);
+            display.updateFromPrimaryDisplayDevice();
+
+            boolean isDefault = (display.mPrimaryDisplayDeviceInfo.flags
+                    & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
+            if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) {
+                Slog.w(TAG, "Attempted to add a second default device: " + device);
+                isDefault = false;
+            }
+
+            int displayId = isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++;
+            mLogicalDisplays.put(displayId, display);
+
+            sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
+
+            // Wake up waitForDefaultDisplay.
+            if (isDefault) {
+                mLock.notifyAll();
+            }
+        }
+    }
+
+    // Runs on handler.
+    private void handleDisplayDeviceChanged(DisplayDevice device) {
+        synchronized (mLock) {
+            if (!mDisplayDevices.contains(device)) {
+                Slog.w(TAG, "Attempted to change non-existent display device: " + device);
+                return;
+            }
+
+            for (int i = mLogicalDisplays.size(); i-- > 0; ) {
+                LogicalDisplay display = mLogicalDisplays.valueAt(i);
+                if (display.mPrimaryDisplayDevice == device) {
+                    final int displayId = mLogicalDisplays.keyAt(i);
+                    display.updateFromPrimaryDisplayDevice();
+                    sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
+                }
+            }
+        }
+    }
+
+    // Runs on handler.
+    private void handleDisplayDeviceRemoved(DisplayDevice device) {
+        synchronized (mLock) {
+            if (!mDisplayDevices.remove(device)) {
+                Slog.w(TAG, "Attempted to remove non-existent display device: " + device);
+                return;
+            }
+
+            for (int i = mLogicalDisplays.size(); i-- > 0; ) {
+                LogicalDisplay display = mLogicalDisplays.valueAt(i);
+                if (display.mPrimaryDisplayDevice == device) {
+                    final int displayId = mLogicalDisplays.keyAt(i);
+                    mLogicalDisplays.removeAt(i);
+                    sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
+                }
+            }
+        }
+    }
+
+    // Posts a message to send a display event at the next opportunity.
+    private void sendDisplayEventLocked(int displayId, int event) {
+        Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
+        mHandler.sendMessage(msg);
+    }
+
+    // Runs on handler.
+    // This method actually sends display event notifications.
+    // Note that it must be very careful not to be holding the lock while sending
+    // is in progress.
+    private void deliverDisplayEvent(int displayId, int event) {
+        if (DEBUG) {
+            Slog.d(TAG, "Delivering display event: displayId=" + displayId + ", event=" + event);
+        }
+
+        final int count;
+        synchronized (mLock) {
+            count = mCallbacks.size();
+            mTempCallbacks.clear();
+            for (int i = 0; i < count; i++) {
+                mTempCallbacks.add(mCallbacks.valueAt(i));
+            }
+        }
+
+        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);
+
+        mHandler.runWithScissors(new Runnable() {
+            @Override
+            public void run() {
+                dumpLocal(pw);
+            }
+        });
+    }
+
+    // Runs on handler.
+    private void dumpLocal(PrintWriter pw) {
+        synchronized (mLock) {
+            IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "    ");
+
+            pw.println();
+            pw.println("Display Adapters: size=" + mDisplayAdapters.size());
+            for (DisplayAdapter adapter : mDisplayAdapters) {
+                pw.println("  " + adapter.getName());
+                adapter.dump(ipw);
+            }
+
+            pw.println();
+            pw.println("Display Devices: size=" + mDisplayDevices.size());
+            for (DisplayDevice device : mDisplayDevices) {
+                pw.println("  " + device);
+            }
+
+            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 + ":");
+                pw.println("    mPrimaryDisplayDevice=" + display.mPrimaryDisplayDevice);
+                pw.println("    mBaseDisplayInfo=" + display.mBaseDisplayInfo);
+                pw.println("    mOverrideDisplayInfo="
+                        + display.mOverrideDisplayInfo);
+            }
+        }
+    }
+
+    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;
+            }
+        }
+    }
+
+    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;
+            }
+        }
+    }
+
+    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();
+            }
+        }
+    }
+
+    /**
+     * Each logical display is primarily associated with one display device.
+     * The primary display device is nominally responsible for the basic properties
+     * of the logical display such as its size, refresh rate, and dpi.
+     *
+     * A logical display may be mirrored onto other display devices besides its
+     * primary display device, but it always remains bound to its primary.
+     * 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 logical display's
+     * primary display device is currently mirroring content from a different logical display.
+     */
+    private final static class LogicalDisplay {
+        public final DisplayInfo mBaseDisplayInfo = new DisplayInfo();
+        public DisplayInfo mOverrideDisplayInfo; // set by the window manager
+
+        public final DisplayDevice mPrimaryDisplayDevice;
+        public final DisplayDeviceInfo mPrimaryDisplayDeviceInfo = new DisplayDeviceInfo();
+
+        public LogicalDisplay(DisplayDevice primaryDisplayDevice) {
+            mPrimaryDisplayDevice = primaryDisplayDevice;
+        }
+
+        public void updateFromPrimaryDisplayDevice() {
+            // Bootstrap the logical display using its associated primary physical display.
+            mPrimaryDisplayDevice.getInfo(mPrimaryDisplayDeviceInfo);
+
+            mBaseDisplayInfo.appWidth = mPrimaryDisplayDeviceInfo.width;
+            mBaseDisplayInfo.appHeight = mPrimaryDisplayDeviceInfo.height;
+            mBaseDisplayInfo.logicalWidth = mPrimaryDisplayDeviceInfo.width;
+            mBaseDisplayInfo.logicalHeight = mPrimaryDisplayDeviceInfo.height;
+            mBaseDisplayInfo.rotation = Surface.ROTATION_0;
+            mBaseDisplayInfo.refreshRate = mPrimaryDisplayDeviceInfo.refreshRate;
+            mBaseDisplayInfo.logicalDensityDpi = mPrimaryDisplayDeviceInfo.densityDpi;
+            mBaseDisplayInfo.physicalXDpi = mPrimaryDisplayDeviceInfo.xDpi;
+            mBaseDisplayInfo.physicalYDpi = mPrimaryDisplayDeviceInfo.yDpi;
+            mBaseDisplayInfo.smallestNominalAppWidth = mPrimaryDisplayDeviceInfo.width;
+            mBaseDisplayInfo.smallestNominalAppHeight = mPrimaryDisplayDeviceInfo.height;
+            mBaseDisplayInfo.largestNominalAppWidth = mPrimaryDisplayDeviceInfo.width;
+            mBaseDisplayInfo.largestNominalAppHeight = mPrimaryDisplayDeviceInfo.height;
+        }
+    }
+}
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..f5c78b9
--- /dev/null
+++ b/services/java/com/android/server/display/HeadlessDisplayAdapter.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display;
+
+import android.content.Context;
+import android.util.DisplayMetrics;
+
+/**
+ * Provides a fake default display for headless systems.
+ * <p>
+ * Display adapters are not thread-safe and must only be accessed
+ * on the display manager service's handler thread.
+ * </p>
+ */
+public final class HeadlessDisplayAdapter extends DisplayAdapter {
+    private static final String TAG = "HeadlessDisplayAdapter";
+
+    public HeadlessDisplayAdapter(Context context) {
+        super(context, TAG);
+    }
+
+    @Override
+    protected void onRegister() {
+        sendDisplayDeviceEvent(new HeadlessDisplayDevice(), DISPLAY_DEVICE_EVENT_ADDED);
+    }
+
+    private final class HeadlessDisplayDevice extends DisplayDevice {
+        public HeadlessDisplayDevice() {
+            super(HeadlessDisplayAdapter.this, null);
+        }
+
+        @Override
+        public void getInfo(DisplayDeviceInfo outInfo) {
+            outInfo.name = getContext().getResources().getString(
+                    com.android.internal.R.string.display_manager_built_in_display_name);
+            outInfo.width = 640;
+            outInfo.height = 480;
+            outInfo.refreshRate = 60;
+            outInfo.densityDpi = DisplayMetrics.DENSITY_DEFAULT;
+            outInfo.xDpi = 160;
+            outInfo.yDpi = 160;
+            outInfo.flags = DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
+                    | DisplayDeviceInfo.FLAG_SECURE;
+        }
+    }
+}
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..73544fc
--- /dev/null
+++ b/services/java/com/android/server/display/LocalDisplayAdapter.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.server.display;
+
+import android.content.Context;
+import android.os.IBinder;
+import android.view.Surface;
+import android.view.Surface.PhysicalDisplayInfo;
+
+/**
+ * A display adapter for the local displays managed by Surface Flinger.
+ * <p>
+ * Display adapters are not thread-safe and must only be accessed
+ * on the display manager service's handler thread.
+ * </p>
+ */
+public final class LocalDisplayAdapter extends DisplayAdapter {
+    private static final String TAG = "LocalDisplayAdapter";
+
+    public LocalDisplayAdapter(Context context) {
+        super(context, TAG);
+    }
+
+    @Override
+    protected void onRegister() {
+        // TODO: listen for notifications from Surface Flinger about
+        // built-in displays being added or removed and rescan as needed.
+        IBinder displayToken = Surface.getBuiltInDisplay(Surface.BUILT_IN_DISPLAY_ID_MAIN);
+        sendDisplayDeviceEvent(new LocalDisplayDevice(displayToken, true),
+                DISPLAY_DEVICE_EVENT_ADDED);
+    }
+
+    private final class LocalDisplayDevice extends DisplayDevice {
+        private final boolean mIsDefault;
+
+        public LocalDisplayDevice(IBinder displayToken, boolean isDefault) {
+            super(LocalDisplayAdapter.this, displayToken);
+            mIsDefault = isDefault;
+        }
+
+        @Override
+        public void getInfo(DisplayDeviceInfo outInfo) {
+            PhysicalDisplayInfo phys = new PhysicalDisplayInfo();
+            Surface.getDisplayInfo(getDisplayToken(), phys);
+
+            outInfo.name = getContext().getResources().getString(
+                    com.android.internal.R.string.display_manager_built_in_display_name);
+            outInfo.width = phys.width;
+            outInfo.height = phys.height;
+            outInfo.refreshRate = phys.refreshRate;
+            outInfo.densityDpi = (int)(phys.density * 160 + 0.5f);
+            outInfo.xDpi = phys.xDpi;
+            outInfo.yDpi = phys.yDpi;
+            if (mIsDefault) {
+                outInfo.flags = DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
+                        | DisplayDeviceInfo.FLAG_SECURE;
+            }
+        }
+    }
+}
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..476d21a
--- /dev/null
+++ b/services/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -0,0 +1,530 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.database.ContentObserver;
+import android.graphics.SurfaceTexture;
+import android.hardware.display.DisplayManager;
+import android.os.IBinder;
+import android.provider.Settings;
+import android.util.DisplayMetrics;
+import android.util.Slog;
+import android.view.Display;
+import android.view.DisplayInfo;
+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.TextureView.SurfaceTextureListener;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.TextView;
+
+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>
+ * Display adapters are not thread-safe and must only be accessed
+ * on the display manager service's handler thread.
+ * </p>
+ */
+public final class OverlayDisplayAdapter extends DisplayAdapter {
+    private static final String TAG = "OverlayDisplayAdapter";
+
+    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 ArrayList<Overlay> mOverlays = new ArrayList<Overlay>();
+    private String mCurrentOverlaySetting = "";
+
+    public OverlayDisplayAdapter(Context context) {
+        super(context, TAG);
+    }
+
+    @Override
+    public void dump(PrintWriter pw) {
+        pw.println("mCurrentOverlaySetting=" + mCurrentOverlaySetting);
+        pw.println("mOverlays: size=" + mOverlays.size());
+        for (Overlay overlay : mOverlays) {
+            overlay.dump(pw);
+        }
+    }
+
+    @Override
+    protected void onRegister() {
+        getContext().getContentResolver().registerContentObserver(
+                Settings.System.getUriFor(Settings.Secure.OVERLAY_DISPLAY_DEVICES), true,
+                new ContentObserver(getHandler()) {
+                    @Override
+                    public void onChange(boolean selfChange) {
+                        updateOverlayDisplayDevices();
+                    }
+                });
+        updateOverlayDisplayDevices();
+    }
+
+    private void updateOverlayDisplayDevices() {
+        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 (Overlay overlay : mOverlays) {
+                overlay.dismiss();
+            }
+            mOverlays.clear();
+        }
+
+        int number = 1;
+        for (String part : value.split(";")) {
+            if (number > 4) {
+                Slog.w(TAG, "Too many overlay display devices.");
+            }
+            Matcher matcher = SETTING_PATTERN.matcher(part);
+            if (matcher.matches()) {
+                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) {
+                        Slog.i(TAG, "Showing overlay display device #" + number
+                                + ": width=" + width + ", height=" + height
+                                + ", densityDpi=" + densityDpi);
+                        mOverlays.add(new Overlay(number++, width, height, densityDpi));
+                        continue;
+                    }
+                } catch (NumberFormatException ex) {
+                }
+            } else if (part.isEmpty()) {
+                continue;
+            }
+            Slog.w(TAG, "Malformed overlay display devices setting: \"" + value + "\"");
+        }
+
+        for (Overlay overlay : mOverlays) {
+            overlay.show();
+        }
+    }
+
+    // Manages an overlay window.
+    private final class Overlay {
+        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 DisplayManager mDisplayManager;
+        private final WindowManager mWindowManager;
+
+        private final int mNumber;
+        private final int mWidth;
+        private final int mHeight;
+        private final int mDensityDpi;
+
+        private final String mName;
+        private final String mTitle;
+
+        private final Display mDefaultDisplay;
+        private final DisplayInfo mDefaultDisplayInfo = new DisplayInfo();
+        private final IBinder mDisplayToken;
+        private final OverlayDisplayDevice mDisplayDevice;
+
+        private View mWindowContent;
+        private WindowManager.LayoutParams mWindowParams;
+        private TextureView mTextureView;
+        private TextView mTitleTextView;
+        private ScaleGestureDetector mScaleGestureDetector;
+
+        private boolean mWindowVisible;
+        private int mWindowX;
+        private int mWindowY;
+        private float mWindowScale;
+
+        private int mLiveTranslationX;
+        private int mLiveTranslationY;
+        private float mLiveScale = 1.0f;
+
+        private int mDragPointerId;
+        private float mDragTouchX;
+        private float mDragTouchY;
+
+        public Overlay(int number, int width, int height, int densityDpi) {
+            Context context = getContext();
+            mDisplayManager = (DisplayManager)context.getSystemService(
+                    Context.DISPLAY_SERVICE);
+            mWindowManager = (WindowManager)context.getSystemService(
+                    Context.WINDOW_SERVICE);
+
+            mNumber = number;
+            mWidth = width;
+            mHeight = height;
+            mDensityDpi = densityDpi;
+
+            mName = context.getResources().getString(
+                    com.android.internal.R.string.display_manager_overlay_display_name, number);
+            mTitle = context.getResources().getString(
+                    com.android.internal.R.string.display_manager_overlay_display_title,
+                    mNumber, mWidth, mHeight, mDensityDpi);
+
+            mDefaultDisplay = mWindowManager.getDefaultDisplay();
+            updateDefaultDisplayInfo();
+
+            mDisplayToken = Surface.createDisplay(mName);
+            mDisplayDevice = new OverlayDisplayDevice(mDisplayToken, mName,
+                    mDefaultDisplayInfo.refreshRate, mDensityDpi);
+
+            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("  #" + mNumber + ": "
+                    + mWidth + "x" + mHeight + ", " + mDensityDpi + " dpi");
+            pw.println("    mName=" + mName);
+            pw.println("    mWindowVisible=" + mWindowVisible);
+            pw.println("    mWindowX=" + mWindowX);
+            pw.println("    mWindowY=" + mWindowY);
+            pw.println("    mWindowScale=" + mWindowScale);
+            pw.println("    mWindowParams=" + mWindowParams);
+            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() {
+            Context context = getContext();
+            LayoutInflater inflater = LayoutInflater.from(context);
+
+            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.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);
+
+            mScaleGestureDetector = new ScaleGestureDetector(context, mOnScaleGestureListener);
+
+            // By default, arrange the displays in the four corners.
+            mWindowVisible = false;
+            mWindowScale = INITIAL_SCALE;
+            if (mNumber == 2 || mNumber == 3) {
+                mWindowX = mDefaultDisplayInfo.logicalWidth;
+            } else {
+                mWindowX = 0;
+            }
+            if (mNumber == 2 || mNumber == 4) {
+                mWindowY = mDefaultDisplayInfo.logicalHeight;
+            } else {
+                mWindowY = 0;
+            }
+        }
+
+        private void updateWindowParams() {
+            float scale = mWindowScale * mLiveScale;
+            if (mWidth * scale > mDefaultDisplayInfo.logicalWidth) {
+                scale = mDefaultDisplayInfo.logicalWidth / mWidth;
+            }
+            if (mHeight * scale > mDefaultDisplayInfo.logicalHeight) {
+                scale = 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 = mWindowX + mLiveTranslationX - (int)(width * offsetScale);
+            int y = mWindowY + mLiveTranslationY - (int)(height * offsetScale);
+            x = Math.max(0, Math.min(x, mDefaultDisplayInfo.logicalWidth - width));
+            y = Math.max(0, Math.min(y, mDefaultDisplayInfo.logicalHeight - 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 = 0;
+            mLiveTranslationY = 0;
+            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 surface, int width, int height) {
+                Surface.openTransaction();
+                try {
+                    Surface.setDisplaySurface(mDisplayToken, surface);
+                } finally {
+                    Surface.closeTransaction();
+                }
+
+                mDisplayDevice.setSize(width, height);
+                sendDisplayDeviceEvent(mDisplayDevice, DISPLAY_DEVICE_EVENT_ADDED);
+            }
+
+            @Override
+            public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+                sendDisplayDeviceEvent(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED);
+
+                Surface.openTransaction();
+                try {
+                    Surface.setDisplaySurface(mDisplayToken, null);
+                } finally {
+                    Surface.closeTransaction();
+                }
+                return true;
+            }
+
+            @Override
+            public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+                mDisplayDevice.setSize(width, height);
+                sendDisplayDeviceEvent(mDisplayDevice, DISPLAY_DEVICE_EVENT_CHANGED);
+            }
+
+            @Override
+            public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+            }
+        };
+
+        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());
+
+                mScaleGestureDetector.onTouchEvent(event);
+
+                switch (event.getActionMasked()) {
+                    case MotionEvent.ACTION_DOWN:
+                        resetDrag(event);
+                        break;
+
+                    case MotionEvent.ACTION_MOVE:
+                        if (event.getPointerCount() == 1) {
+                            int index = event.findPointerIndex(mDragPointerId);
+                            if (index < 0) {
+                                resetDrag(event);
+                            } else {
+                                mLiveTranslationX = (int)(event.getX(index) - mDragTouchX);
+                                mLiveTranslationY = (int)(event.getY(index) - mDragTouchY);
+                                relayout();
+                            }
+                        }
+                        break;
+
+                    case MotionEvent.ACTION_UP:
+                    case MotionEvent.ACTION_CANCEL:
+                        saveWindowParams();
+                        break;
+                }
+
+                // Revert to window coordinates.
+                event.setLocation(oldX, oldY);
+                return true;
+            }
+
+            private void resetDrag(MotionEvent event) {
+                saveWindowParams();
+                mDragPointerId = event.getPointerId(0);
+                mDragTouchX = event.getX();
+                mDragTouchY = event.getY();
+            }
+        };
+
+        private final ScaleGestureDetector.OnScaleGestureListener mOnScaleGestureListener =
+                new ScaleGestureDetector.SimpleOnScaleGestureListener() {
+            @Override
+            public boolean onScaleBegin(ScaleGestureDetector detector) {
+                saveWindowParams();
+                mDragPointerId = -1; // cause drag to be reset
+                return true;
+            }
+
+            @Override
+            public boolean onScale(ScaleGestureDetector detector) {
+                mLiveScale = detector.getScaleFactor();
+                relayout();
+                return false;
+            }
+        };
+    }
+
+    private final class OverlayDisplayDevice extends DisplayDevice {
+        private final String mName;
+        private final float mRefreshRate;
+        private final int mDensityDpi;
+        private int mWidth;
+        private int mHeight;
+
+        public OverlayDisplayDevice(IBinder displayToken, String name,
+                float refreshRate, int densityDpi) {
+            super(OverlayDisplayAdapter.this, displayToken);
+            mName = name;
+            mRefreshRate = refreshRate;
+            mDensityDpi = densityDpi;
+        }
+
+        public void setSize(int width, int height) {
+            mWidth = width;
+            mHeight = height;
+        }
+
+        @Override
+        public void getInfo(DisplayDeviceInfo outInfo) {
+            outInfo.name = mName;
+            outInfo.width = mWidth;
+            outInfo.height = mHeight;
+            outInfo.refreshRate = mRefreshRate;
+            outInfo.densityDpi = mDensityDpi;
+            outInfo.xDpi = mDensityDpi;
+            outInfo.yDpi = mDensityDpi;
+            outInfo.flags = DisplayDeviceInfo.FLAG_SECURE;
+        }
+    }
+}
diff --git a/services/java/com/android/server/input/InputManagerService.java b/services/java/com/android/server/input/InputManagerService.java
index bdd0aa4..29c68eb 100644
--- a/services/java/com/android/server/input/InputManagerService.java
+++ b/services/java/com/android/server/input/InputManagerService.java
@@ -42,8 +42,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 +57,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;
@@ -108,7 +109,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,7 +137,7 @@
 
     // 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,
@@ -236,11 +236,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;
@@ -425,9 +425,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 +436,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 +1218,12 @@
     }
 
     // Native callback.
-    private void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
-        mCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
+    private void notifySwitch(long whenNanos, int switchCode, int switchValue) {
+        switch (switchCode) {
+            case SW_LID:
+                mCallbacks.notifyLidSwitchChanged(whenNanos, switchValue == 0);
+                break;
+        }
     }
 
     // Native callback.
@@ -1229,7 +1241,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 +1400,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 +1438,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 +1467,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/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..c2c0a71 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;
@@ -54,17 +56,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 +85,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 +158,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 +188,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 +219,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 +250,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 +266,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 +281,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 +297,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 +311,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 +339,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 +374,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 +382,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 +419,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 +430,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 +504,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 +552,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 +577,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 +692,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 +720,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 +732,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 +777,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 +848,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 +908,7 @@
         } else {
             Log.w(TAG, "sendExtraCommand: unknown command " + command);
         }
-        
+
         Binder.restoreCallingIdentity(identity);
         return result;
     }
@@ -992,18 +943,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 +989,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 +1005,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 +1026,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 +1053,7 @@
             mLocation.setExtras(mLocationExtras);
 
             try {
-                mLocationManager.reportLocation(mLocation, false);
+                mILocationManager.reportLocation(mLocation, false);
             } catch (RemoteException e) {
                 Log.e(TAG, "RemoteException calling reportLocation");
             }
@@ -1110,17 +1061,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 +1082,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
@@ -1161,7 +1109,7 @@
     private void reportStatus(int status) {
         if (DEBUG) Log.v(TAG, "reportStatus status: " + status);
 
-        synchronized(mListeners) {
+        synchronized (mListeners) {
             boolean wasNavigating = mNavigating;
 
             switch (status) {
@@ -1199,20 +1147,6 @@
                     }
                 }
 
-                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);
@@ -1227,15 +1161,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 +1185,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") +
@@ -1339,7 +1273,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 +1320,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 +1480,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 +1503,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 +1518,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 +1541,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 +1593,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..57bc1c5
--- /dev/null
+++ b/services/java/com/android/server/location/LocationFudger.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.server.location;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.security.SecureRandom;
+import android.location.Location;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.os.SystemClock;
+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";
+
+    /**
+     * This is the main control: Best location accuracy allowed for coarse applications.
+     */
+    private static final float ACCURACY_METERS = 200.0f;
+
+    /**
+     * The distance between grids for snap-to-grid. See {@link #createCoarse}.
+     */
+    private static final double GRID_SIZE_METERS = ACCURACY_METERS;
+
+    /**
+     * 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.
+     */
+    private static final double STANDARD_DEVIATION_METERS = GRID_SIZE_METERS / 4.0;
+
+    /**
+     * 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();
+
+    // all fields below protected by mLock
+    private double mOffsetLatitudeMeters;
+    private double mOffsetLongitudeMeters;
+    private long mNextInterval;
+
+    public LocationFudger() {
+        mOffsetLatitudeMeters = nextOffset();
+        mOffsetLongitudeMeters = nextOffset();
+        mNextInterval = SystemClock.elapsedRealtime() + CHANGE_INTERVAL_MS;
+    }
+
+    /**
+     * Get the cached coarse location, or generate a new one and cache it.
+     */
+    public Location getOrCreate(Location location) {
+        Bundle extras = location.getExtras();
+        if (extras == null) {
+            return addCoarseLocationExtra(location);
+        }
+        Parcelable parcel = extras.getParcelable(EXTRA_COARSE_LOCATION);
+        if (parcel == null) {
+            return addCoarseLocationExtra(location);
+        }
+        if (!(parcel instanceof Location)) {
+            return addCoarseLocationExtra(location);
+        }
+        Location coarse = (Location) parcel;
+        if (coarse.getAccuracy() < ACCURACY_METERS) {
+            return addCoarseLocationExtra(location);
+        }
+        return coarse;
+    }
+
+    private Location addCoarseLocationExtra(Location location) {
+        Bundle extras = location.getExtras();
+        if (extras == null) extras = new Bundle();
+        Location coarse = createCoarse(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 createCoarse(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.
+        synchronized (mLock) {
+            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(GRID_SIZE_METERS);
+        lat = Math.round(lat / latGranularity) * latGranularity;
+        double lonGranularity = metersToDegreesLongitude(GRID_SIZE_METERS, 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(ACCURACY_METERS, 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 * nextOffset();
+        mOffsetLongitudeMeters *= PREVIOUS_WEIGHT;
+        mOffsetLongitudeMeters += NEW_WEIGHT * nextOffset();
+
+        if (D) Log.d(TAG, String.format("new offset: %.0f, %.0f (meters)",
+                mOffsetLongitudeMeters, mOffsetLatitudeMeters));
+    }
+
+    private double nextOffset() {
+        return mRandom.nextGaussian() * STANDARD_DEVIATION_METERS;
+    }
+
+    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));
+    }
+}
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/NetworkAlertObserver.java b/services/java/com/android/server/net/BaseNetworkObserver.java
similarity index 66%
rename from services/java/com/android/server/net/NetworkAlertObserver.java
rename to services/java/com/android/server/net/BaseNetworkObserver.java
index 0d1c3b2..8b2aa5d 100644
--- a/services/java/com/android/server/net/NetworkAlertObserver.java
+++ b/services/java/com/android/server/net/BaseNetworkObserver.java
@@ -19,26 +19,39 @@
 import android.net.INetworkManagementEventObserver;
 
 /**
+ * Base {@link INetworkManagementEventObserver} that provides no-op
+ * implementations which can be overridden.
+ *
  * @hide
  */
-public abstract class NetworkAlertObserver extends INetworkManagementEventObserver.Stub {
+public class BaseNetworkObserver extends INetworkManagementEventObserver.Stub {
     @Override
     public void interfaceStatusChanged(String iface, boolean up) {
-        // ignored; interface changes come through ConnectivityService
+        // default no-op
     }
 
     @Override
     public void interfaceRemoved(String iface) {
-        // ignored; interface changes come through ConnectivityService
+        // default no-op
     }
 
     @Override
     public void interfaceLinkStateChanged(String iface, boolean up) {
-        // ignored; interface changes come through ConnectivityService
+        // default no-op
     }
 
     @Override
     public void interfaceAdded(String iface) {
-        // ignored; interface changes come through ConnectivityService
+        // 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..dabcf2f
--- /dev/null
+++ b/services/java/com/android/server/net/LockdownVpnTracker.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.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;
+
+        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");
+                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);
+            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/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index fe43d11..a7cba5a 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -112,11 +112,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 +129,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;
@@ -425,7 +426,7 @@
 
             final String action = intent.getAction();
             final int uid = intent.getIntExtra(EXTRA_UID, 0);
-            final int appId = UserId.getAppId(uid);
+            final int appId = UserHandle.getAppId(uid);
             synchronized (mRulesLock) {
                 if (ACTION_PACKAGE_ADDED.equals(action)) {
                     // NOTE: PACKAGE_ADDED is currently only sent once, and is
@@ -570,7 +571,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
@@ -1187,8 +1188,8 @@
                         final int uid = readIntAttribute(in, ATTR_UID);
                         final int policy = readIntAttribute(in, ATTR_POLICY);
 
-                        final int appId = UserId.getAppId(uid);
-                        if (UserId.isApp(appId)) {
+                        final int appId = UserHandle.getAppId(uid);
+                        if (UserHandle.isApp(appId)) {
                             setAppPolicyUnchecked(appId, policy, false);
                         } else {
                             Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
@@ -1197,7 +1198,7 @@
                         final int appId = readIntAttribute(in, ATTR_APP_ID);
                         final int policy = readIntAttribute(in, ATTR_POLICY);
 
-                        if (UserId.isApp(appId)) {
+                        if (UserHandle.isApp(appId)) {
                             setAppPolicyUnchecked(appId, policy, false);
                         } else {
                             Slog.w(TAG, "unable to apply policy to appId " + appId + "; ignoring");
@@ -1303,7 +1304,7 @@
     public void setAppPolicy(int appId, int policy) {
         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
 
-        if (!UserId.isApp(appId)) {
+        if (!UserHandle.isApp(appId)) {
             throw new IllegalArgumentException("cannot apply policy to appId " + appId);
         }
 
@@ -1697,7 +1698,7 @@
         final PackageManager pm = mContext.getPackageManager();
         final List<ApplicationInfo> apps = pm.getInstalledApplications(0);
         for (ApplicationInfo app : apps) {
-            final int appId = UserId.getAppId(app.uid);
+            final int appId = UserHandle.getAppId(app.uid);
             updateRulesForAppLocked(appId);
         }
 
@@ -1707,8 +1708,9 @@
     }
 
     private void updateRulesForAppLocked(int appId) {
-        for (UserInfo user : mContext.getPackageManager().getUsers()) {
-            final int uid = UserId.getUid(user.id, appId);
+        UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        for (UserInfo user : um.getUsers()) {
+            final int uid = UserHandle.getUid(user.id, appId);
             updateRulesForUidLocked(uid);
         }
     }
@@ -1716,7 +1718,7 @@
     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,7 +1728,7 @@
     private void updateRulesForUidLocked(int uid) {
         if (!isUidValidForRules(uid)) return;
 
-        final int appId = UserId.getAppId(uid);
+        final int appId = UserHandle.getAppId(uid);
         final int appPolicy = getAppPolicy(appId);
         final boolean uidForeground = isUidForeground(uid);
 
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..ffe2a3d 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -763,7 +763,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
diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java
index 48004bb..d4fe3fb 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/java/com/android/server/pm/Installer.java
@@ -338,12 +338,14 @@
         return execute(builder.toString());
     }
 
-    public int getSizeInfo(String pkgName, String apkPath, String fwdLockApkPath,
+    public int getSizeInfo(String pkgName, int persona, String apkPath, String fwdLockApkPath,
             String asecPath, PackageStats pStats) {
         StringBuilder builder = new StringBuilder("getsize");
         builder.append(' ');
         builder.append(pkgName);
         builder.append(' ');
+        builder.append(persona);
+        builder.append(' ');
         builder.append(apkPath);
         builder.append(' ');
         builder.append(fwdLockApkPath != null ? fwdLockApkPath : "!");
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index f914271..48a4b74 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -64,10 +64,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 +79,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 +103,7 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.os.UserId;
+import android.os.UserHandle;
 import android.provider.Settings.Secure;
 import android.security.SystemKeyStore;
 import android.util.DisplayMetrics;
@@ -165,6 +168,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 +179,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;
 
@@ -210,7 +215,15 @@
      * 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";
 
@@ -388,6 +401,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 +424,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 +470,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 +555,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 +680,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 +710,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 +839,28 @@
                     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);
+                            try {
+                                ret = args.copyApk(mContainerService, true);
+                            } catch (RemoteException e) {
+                                Slog.e(TAG, "Could not contact the ContainerService");
+                            }
+                        }
+
+                        processPendingInstall(args, ret);
                         mHandler.sendEmptyMessage(MCS_UNBIND);
                     }
-
                     break;
                 }
                 case PACKAGE_VERIFIED: {
@@ -874,12 +960,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) {
@@ -916,11 +1003,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,
@@ -1110,8 +1198,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()) {
@@ -1160,9 +1247,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 +1382,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 +1612,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;
@@ -1602,14 +1679,14 @@
         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 +1789,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 +1807,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;
+                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;
     }
@@ -1760,13 +1841,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 +1862,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 +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(pi != null) {
                     try {
@@ -1833,8 +1917,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;
@@ -1853,8 +1937,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;
@@ -1870,8 +1954,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;
@@ -1887,8 +1971,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 +2017,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 +2046,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)) {
@@ -1996,7 +2080,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 +2283,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 +2342,7 @@
     }
 
     public String[] getPackagesForUid(int uid) {
-        uid = UserId.getAppId(uid);
+        uid = UserHandle.getAppId(uid);
         // reader
         synchronized (mPackages) {
             Object obj = mSettings.getUserIdLPr(uid);
@@ -2283,7 +2367,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;
@@ -2394,6 +2478,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;
                     }
@@ -2763,7 +2850,7 @@
         final ParceledListSlice<PackageInfo> list = new ParceledListSlice<PackageInfo>();
         final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
         final String[] keys;
-        int userId = UserId.getCallingUserId();
+        int userId = UserHandle.getCallingUserId();
 
         // writer
         synchronized (mPackages) {
@@ -2838,8 +2925,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 +2949,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 +2979,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 +2998,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 +3026,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 +3077,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 +3108,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 +3176,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 +3242,7 @@
 
                     InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
                             ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString);
-                    synchronized (mInstaller) {
+                    synchronized (mInstallLock) {
                         args.cleanUpResourcesLI();
                     }
                     synchronized (mPackages) {
@@ -3183,7 +3276,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 +3298,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 +3329,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
@@ -3439,8 +3532,38 @@
         }
     }
 
+    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;
+            }
+        }
+        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 +3755,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 +3914,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 +3928,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 +3937,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 +3974,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();
@@ -3992,7 +4106,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) {
@@ -4716,14 +4832,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 +4910,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 +4924,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 +4948,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 +5034,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 +5107,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 +5121,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 +5146,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 +5247,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 +5266,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 +5295,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 +5305,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) {
             }
         }
@@ -5196,8 +5380,10 @@
         public void onEvent(int event, String path) {
             String removedPackage = null;
             int removedUid = -1;
+            int[] removedUsers = null;
             String addedPackage = null;
             int addedUid = -1;
+            int[] addedUsers = null;
 
             // TODO post a message to the handler to obtain serial ordering
             synchronized (mInstallLock) {
@@ -5226,6 +5412,15 @@
                 // reader
                 synchronized (mPackages) {
                     p = mAppDirs.get(fullPathStr);
+                    if (p != null) {
+                        PackageSetting 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) {
@@ -5243,7 +5438,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
@@ -5272,13 +5467,13 @@
                 extras.putInt(Intent.EXTRA_UID, removedUid);
                 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);
                 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,
-                        extras, null, null, UserId.USER_ALL);
+                        extras, null, null, addedUsers);
             }
         }
 
@@ -5304,9 +5499,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;
 
@@ -5321,12 +5532,57 @@
 
         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 +5591,36 @@
         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 < 0)) {
+            throw new IllegalArgumentException("millisecondsToDelay is out of bounds.");
+        }
+        if ((verificationCodeAtTimeout != PackageManager.VERIFICATION_ALLOW)
+              || (verificationCodeAtTimeout != PackageManager.VERIFICATION_REJECT)) {
+            throw new IllegalArgumentException("verificationCodeAtTimeout is unknown.");
+        }
+
+        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 ComponentName matchComponentForVerifier(String packageName,
             List<ResolveInfo> receivers) {
         ActivityInfo targetReceiver = null;
@@ -5453,6 +5739,17 @@
     }
 
     /**
+     * Get the default verification agent response code.
+     *
+     * @return default verification response code
+     */
+    private int getDefaultVerificationResponse() {
+        return android.provider.Settings.Secure.getInt(mContext.getContentResolver(),
+                android.provider.Settings.Secure.PACKAGE_VERIFIER_DEFAULT_RESPONSE,
+                DEFAULT_VERIFICATION_RESPONSE);
+    }
+
+    /**
      * Check whether or not package verification has been enabled.
      *
      * @return true if verification should be performed
@@ -5463,6 +5760,17 @@
                 DEFAULT_VERIFY_ENABLE ? 1 : 0) == 1 ? true : false;
     }
 
+    /**
+     * 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.INSTALL_NON_MARKET_APPS,
+                -1);
+    }
+
     public void setInstallerPackageName(String targetPackage, String installerPackageName) {
         final int uid = Binder.getCallingUid();
         // writer
@@ -5615,6 +5923,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 +5975,7 @@
         private final IPackageStatsObserver mObserver;
 
         public MeasureParams(PackageStats stats, IPackageStatsObserver observer) {
+            super(new UserHandle(stats.userHandle));
             mObserver = observer;
             mStats = stats;
         }
@@ -5663,7 +5983,7 @@
         @Override
         void handleStartCopy() throws RemoteException {
             synchronized (mInstallLock) {
-                mSuccess = getPackageSizeInfoLI(mStats.packageName, mStats);
+                mSuccess = getPackageSizeInfoLI(mStats.packageName, mStats.userHandle, mStats);
             }
 
             final boolean mounted;
@@ -5729,8 +6049,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 +6057,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 +6084,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) {
@@ -5884,6 +6220,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 +6257,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 +6276,19 @@
 
                     verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS, flags);
 
-                    if (verificationURI != null) {
-                        verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI,
-                                verificationURI);
+                    if (verificationParams != null) {
+                        if (verificationParams.getVerificationURI() != null) {
+                           verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI,
+                                 verificationParams.getVerificationURI());
+                        }
+                        if (verificationParams.getOriginatingURI() != null) {
+                            verification.putExtra(Intent.EXTRA_ORIGINATING_URI,
+                                  verificationParams.getOriginatingURI());
+                        }
+                        if (verificationParams.getReferrer() != null) {
+                            verification.putExtra(Intent.EXTRA_REFERRER,
+                                  verificationParams.getReferrer());
+                        }
                     }
 
                     final PackageVerificationState verificationState = new PackageVerificationState(
@@ -6064,7 +6413,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 +6567,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 +6628,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,7 +6642,7 @@
         }
 
         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();
@@ -6562,13 +6916,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 +6935,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;
         }
 
@@ -6910,6 +7268,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 +7281,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 +7309,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 +7326,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 +7351,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 +7375,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 +7384,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 +7405,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 +7421,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 +7439,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;
@@ -7130,7 +7488,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) {
@@ -7153,7 +7511,7 @@
                 removePackageLI(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 +7667,7 @@
                     systemApp = (ps.pkg.applicationInfo.flags &
                             ApplicationInfo.FLAG_SYSTEM) != 0;
                 }
+                res.origUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
             }
         }
 
@@ -7327,11 +7686,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);
+            }
         }
     }
 
@@ -7423,10 +7788,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 +7818,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 +7833,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 +7865,7 @@
         // other processes clean up before deleting resources.
         if (info.args != null) {
             synchronized (mInstallLock) {
-                info.args.doPostDeleteLI(deleteCodeAndResources);
+                info.args.doPostDeleteLI(true);
             }
         }
 
@@ -7507,29 +7875,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);
             }
         }
     }
@@ -7543,34 +7912,29 @@
     private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
             int flags, boolean writeSettings) {
         String packageName = p.packageName;
-        if (outInfo != null) {
-            outInfo.removedPackage = packageName;
-        }
         removePackageLI(p, (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 +7943,7 @@
                             mSettings.updateSharedUserPermsLPw(deletedPs, mGlobalGids);
                         }
                     }
-                    clearPackagePreferredActivitiesLPw(deletedPs.name);
+                    clearPackagePreferredActivitiesLPw(deletedPs.name, UserHandle.USER_ALL);
                 }
             }
             // can downgrade to reader
@@ -7619,10 +7983,10 @@
         outInfo.isRemovedPackageSystemUpdate = true;
         if (ps.versionCode < p.mVersionCode) {
             // 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,
                 writeSettings);
@@ -7639,7 +8003,7 @@
         // Install the system package
         PackageParser.Package newPkg = scanPackageLI(ps.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);
@@ -7686,7 +8050,7 @@
     /*
      * 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) {
@@ -7695,6 +8059,8 @@
         }
         PackageParser.Package p;
         boolean dataOnly = false;
+        int removeUser = -1;
+        int appId = -1;
         synchronized (mPackages) {
             p = mPackages.get(packageName);
             if (p == null) {
@@ -7702,15 +8068,53 @@
                 dataOnly = true;
                 PackageSetting ps = mSettings.mPackages.get(packageName);
                 if (ps == null) {
-                    Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
+                    Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
                     return false;
                 }
                 p = ps.pkg;
             }
+            if (p == null) {
+                Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
+                return false;
+            }
+            final PackageSetting ps = (PackageSetting)p.mExtras;
+            if (!isSystemApp(p) && ps != null && 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());
+                }
+            }
         }
-        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) {
@@ -7755,7 +8159,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 +8175,52 @@
         }
 
         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 File externalCacheDir = Environment
+                            .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 = Environment
+                                .getExternalStorageAppDataDirectory(packageName);
+                        try {
+                            conn.mContainerService.clearDirectory(externalDataDir.toString());
+                        } catch (RemoteException e) {
+                        }
+                        final File externalMediaDir = Environment
+                                .getExternalStorageAppMediaDirectory(packageName);
+                        try {
+                            conn.mContainerService.clearDirectory(externalMediaDir.toString());
+                        } catch (RemoteException e) {
+                        }
                     }
+                } finally {
+                    mContext.unbindService(conn);
                 }
-            } finally {
-                mContext.unbindService(conn);
             }
         }
     }
@@ -7827,7 +8239,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 +8305,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 +8313,7 @@
                 synchronized (mInstallLock) {
                     succeded = deleteApplicationCacheFilesLI(packageName, userId);
                 }
-                clearExternalStorageDataSync(packageName, false);
+                clearExternalStorageDataSync(packageName, userId, false);
                 if(observer != null) {
                     try {
                         observer.onRemoveCompleted(packageName, succeded);
@@ -7941,12 +8353,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 +8369,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 +8407,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 +8459,28 @@
     }
     
     public void addPreferredActivity(IntentFilter filter, int match,
-            ComponentName[] set, ComponentName activity) {
+            ComponentName[] set, ComponentName activity, int userId) {
         // writer
+        int callingUid = Binder.getCallingUid();
+        checkValidCaller(callingUid, userId);
         synchronized (mPackages) {
             if (mContext.checkCallingOrSelfPermission(
                     android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
                     != PackageManager.PERMISSION_GRANTED) {
-                if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
+                if (getUidTargetSdkVersionLockedLPr(callingUid)
                         < Build.VERSION_CODES.FROYO) {
                     Slog.w(TAG, "Ignoring addPreferredActivity() from uid "
-                            + Binder.getCallingUid());
+                            + callingUid);
                     return;
                 }
                 mContext.enforceCallingOrSelfPermission(
                         android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
             }
-            
-            Slog.i(TAG, "Adding preferred activity " + activity + ":");
+
+            Slog.i(TAG, "Adding preferred activity " + activity + " for user " + userId + " :");
             filter.dump(new LogPrinter(Log.INFO, TAG), "  ");
             mSettings.mPreferredActivities.addFilter(
-                    new PreferredActivity(filter, match, set, activity));
+                    new PreferredActivity(filter, match, set, activity, userId));
             scheduleWriteSettingsLocked();            
         }
     }
@@ -8101,13 +8516,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 +8540,7 @@
                     mSettings.mPreferredActivities.removeFilter(pa);
                 }
             }
-            addPreferredActivity(filter, match, set, activity);
+            addPreferredActivity(filter, match, set, activity, callingUserId);
         }
     }
 
@@ -8147,17 +8564,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 +8600,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) {
@@ -8248,7 +8673,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 +8722,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 +8771,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) {
@@ -8951,7 +9376,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 +9397,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 +9442,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 +9551,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 {
@@ -9164,9 +9589,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 +9645,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);
             }
@@ -9415,48 +9844,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 +9890,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..68b594a 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -34,21 +34,24 @@
 
 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 +82,7 @@
     private static final String TAG = "PackageSettings";
 
     private static final boolean DEBUG_STOPPED = false;
+    private static final boolean DEBUG_MU = false;
 
     private static final String TAG_READ_EXTERNAL_STORAGE = "read-external-storage";
     private static final String ATTR_ENFORCEMENT = "enforcement";
@@ -90,9 +94,12 @@
     private static final String TAG_PACKAGE = "pkg";
 
     private static final String ATTR_NAME = "name";
+    private static final String ATTR_USER = "user";
+    private static final String ATTR_CODE = "code";
     private static final String ATTR_NOT_LAUNCHED = "nl";
     private static final String ATTR_ENABLED = "enabled";
     private static final String ATTR_STOPPED = "stopped";
+    private static final String ATTR_INSTALLED = "inst";
 
     private final File mSettingsFilename;
     private final File mBackupSettingsFilename;
@@ -121,6 +128,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 +161,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 +181,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 +206,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 +371,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 +415,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 +448,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 +487,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 +511,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;
     }
@@ -735,6 +776,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 +810,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 +859,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 +885,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 +917,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 +932,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 +943,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 +980,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 +1257,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(i);
+                        serializer.attribute(null, ATTR_NAME, item.packageName);
+                        serializer.attribute(null, ATTR_CODE, item.andCode ? "true" : "false");
+                        serializer.attribute(null, ATTR_USER, userStr);
+                        serializer.endTag(null, "cleaning-package");
+                    }
                 }
             }
             
@@ -1452,6 +1523,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 +1611,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 +1675,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 +1702,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 +1737,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 +2372,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 +2386,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 +2439,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 +2464,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 +2476,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 +2513,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",
     };
@@ -2523,22 +2622,28 @@
             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(" 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/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..fb04d0f
--- /dev/null
+++ b/services/java/com/android/server/pm/UserManagerService.java
@@ -0,0 +1,653 @@
+/*
+ * 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.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 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;
+            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);
+            }
+        }
+    }
+
+    @Override
+    public ParcelFileDescriptor setUserIcon(int userId) {
+        checkManageUsersPermission("update users");
+        synchronized (mPackagesLock) {
+            UserInfo info = mUsers.get(userId);
+            if (info == null) return null;
+            ParcelFileDescriptor fd = updateIconBitmapLocked(info);
+            if (fd != null) {
+                writeUserLocked(info);
+            }
+            return fd;
+        }
+    }
+
+    @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:
+    }
+
+    /**
+     * 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 ParcelFileDescriptor updateIconBitmapLocked(UserInfo info) {
+        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);
+            }
+            ParcelFileDescriptor fd = ParcelFileDescriptor.open(file,
+                    MODE_CREATE|MODE_READ_WRITE);
+            info.iconPath = file.getAbsolutePath();
+            return fd;
+        } catch (FileNotFoundException e) {
+            Slog.w(LOG_TAG, "Error setting photo for user ", e);
+        }
+        return null;
+    }
+
+    /**
+     * 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() {
+        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");
+        int userId = getNextAvailableId();
+        UserInfo userInfo = new UserInfo(userId, name, null, flags);
+        File userPath = new File(mBaseUserPath, Integer.toString(userId));
+        synchronized (mInstallLock) {
+            synchronized (mPackagesLock) {
+                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.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_USERS);
+            mContext.sendBroadcastAsUser(new Intent(Intent.ACTION_BOOT_COMPLETED),
+                    new UserHandle(userInfo.id));
+        }
+        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();
+            }
+        }
+
+        // Let other services shutdown any activity
+        Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED);
+        addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userHandle);
+        mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_USERS);
+    }
+
+    @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 getNextAvailableId() {
+        synchronized (mPackagesLock) {
+            int i = 0;
+            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..6b6d899
--- /dev/null
+++ b/services/java/com/android/server/power/DisplayPowerController.java
@@ -0,0 +1,1159 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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 = false;
+
+    // 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);
+            }
+        });
+    }
+
+    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..3524a08
--- /dev/null
+++ b/services/java/com/android/server/power/DisplayPowerState.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.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) {
+                PowerManagerService.nativeSetScreenState(false);
+            }
+
+            if ((mDirty & DIRTY_ELECTRON_BEAM) != 0) {
+                mElectronBeam.draw(mElectronBeamLevel);
+            }
+
+            if ((mDirty & (DIRTY_BRIGHTNESS | DIRTY_SCREEN_ON | DIRTY_ELECTRON_BEAM)) != 0) {
+                mScreenBrightnessModulator.setBrightness(mScreenOn ?
+                        (int)(mScreenBrightness * mElectronBeamLevel) : 0);
+            }
+
+            if ((mDirty & DIRTY_SCREEN_ON) != 0 && mScreenOn) {
+                PowerManagerService.nativeSetScreenState(true);
+            }
+
+            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..75f8445
--- /dev/null
+++ b/services/java/com/android/server/power/Notifier.java
@@ -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.
+ */
+
+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.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.sendOrderedBroadcast(mScreenOnIntent, 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.sendOrderedBroadcast(mScreenOffIntent, 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..f7c9c7d
--- /dev/null
+++ b/services/java/com/android/server/power/PhotonicModulator.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.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;
+    }
+
+    /**
+     * Asynchronously sets the backlight brightness.
+     *
+     * @param lightValue The new light value, from 0 to 255.
+     */
+    public void setBrightness(int lightValue) {
+        synchronized (mLock) {
+            if (lightValue != mPendingLightValue) {
+                mPendingLightValue = lightValue;
+                if (!mPendingChange) {
+                    mPendingChange = true;
+                    mSuspendBlocker.acquire();
+                    mExecutor.execute(mTask);
+                }
+            }
+        }
+    }
+
+    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;
+                        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..59d0954
--- /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.System.getUriFor(
+                    Settings.System.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.System.getInt(resolver,
+                Settings.System.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.System.putInt(mContext.getContentResolver(),
+                Settings.System.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/pm/ShutdownThread.java b/services/java/com/android/server/power/ShutdownThread.java
similarity index 96%
rename from services/java/com/android/server/pm/ShutdownThread.java
rename to services/java/com/android/server/power/ShutdownThread.java
index 3675d41..a3770d7 100644
--- a/services/java/com/android/server/pm/ShutdownThread.java
+++ b/services/java/com/android/server/power/ShutdownThread.java
@@ -15,7 +15,7 @@
  */
 
  
-package com.android.server.pm;
+package com.android.server.power;
 
 import android.app.ActivityManagerNative;
 import android.app.AlertDialog;
@@ -23,7 +23,7 @@
 import android.app.IActivityManager;
 import android.app.ProgressDialog;
 import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.IBluetooth;
+import android.bluetooth.IBluetoothManager;
 import android.nfc.NfcAdapter;
 import android.nfc.INfcAdapter;
 import android.content.BroadcastReceiver;
@@ -43,7 +43,6 @@
 import android.os.storage.IMountShutdownObserver;
 
 import com.android.internal.telephony.ITelephony;
-import com.android.server.PowerManagerService;
 
 import android.util.Log;
 import android.view.WindowManager;
@@ -385,9 +384,9 @@
                         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));
+                final IBluetoothManager bluetooth =
+                        IBluetoothManager.Stub.asInterface(ServiceManager.checkService(
+                                BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE));
 
                 try {
                     nfcOff = nfc == null ||
@@ -402,8 +401,7 @@
                 }
 
                 try {
-                    bluetoothOff = bluetooth == null ||
-                                   bluetooth.getBluetoothState() == BluetoothAdapter.STATE_OFF;
+                    bluetoothOff = bluetooth == null || !bluetooth.isEnabled();
                     if (!bluetoothOff) {
                         Log.w(TAG, "Disabling Bluetooth...");
                         bluetooth.disable(false);  // disable but don't persist new state
@@ -429,8 +427,7 @@
                 while (SystemClock.elapsedRealtime() < endTime) {
                     if (!bluetoothOff) {
                         try {
-                            bluetoothOff =
-                                    bluetooth.getBluetoothState() == BluetoothAdapter.STATE_OFF;
+                            bluetoothOff = !bluetooth.isEnabled();
                         } catch (RemoteException ex) {
                             Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
                             bluetoothOff = true;
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/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 a115345..ddecf14 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -114,6 +114,7 @@
     private boolean mAudioSourceEnabled;
     private Map<String, List<Pair<String, String>>> mOemModeMap;
     private String[] mAccessoryStrings;
+    private UsbDebuggingManager mDebuggingManager;
 
     private class AdbSettingsObserver extends ContentObserver {
         public AdbSettingsObserver() {
@@ -166,6 +167,10 @@
             if (DEBUG) Slog.d(TAG, "accessory attached at boot");
             startAccessoryMode();
         }
+
+        if ("1".equals(SystemProperties.get("ro.adb.secure"))) {
+            mDebuggingManager = new UsbDebuggingManager(context);
+        }
     }
 
     public void systemReady() {
@@ -425,6 +430,9 @@
                 setEnabledFunctions(mDefaultFunctions, true);
                 updateAdbNotification();
             }
+            if (mDebuggingManager != null) {
+                mDebuggingManager.setAdbEnabled(mAdbEnabled);
+            }
         }
 
         private void setEnabledFunctions(String functions, boolean makeDefault) {
@@ -601,6 +609,9 @@
                     if (mCurrentAccessory != null) {
                         mSettingsManager.accessoryAttached(mCurrentAccessory);
                     }
+                    if (mDebuggingManager != null) {
+                        mDebuggingManager.setAdbEnabled(mAdbEnabled);
+                    }
                     break;
             }
         }
@@ -802,10 +813,25 @@
         return usbFunctions;
     }
 
+    public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
+        if (mDebuggingManager != null) {
+            mDebuggingManager.allowUsbDebugging(alwaysAllow, publicKey);
+        }
+    }
+
+    public void denyUsbDebugging() {
+        if (mDebuggingManager != null) {
+            mDebuggingManager.denyUsbDebugging();
+        }
+    }
+
     public void dump(FileDescriptor fd, PrintWriter pw) {
         if (mHandler != null) {
             mHandler.dump(fd, pw);
         }
+        if (mDebuggingManager != null) {
+            mDebuggingManager.dump(fd, pw);
+        }
     }
 
     private native String[] nativeGetAccessoryStrings();
diff --git a/services/java/com/android/server/usb/UsbService.java b/services/java/com/android/server/usb/UsbService.java
index 0205ef8..bebcd56 100644
--- a/services/java/com/android/server/usb/UsbService.java
+++ b/services/java/com/android/server/usb/UsbService.java
@@ -164,6 +164,16 @@
         }
     }
 
+    public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+        mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey);
+    }
+
+    public void denyUsbDebugging() {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+        mDeviceManager.denyUsbDebugging();
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
diff --git a/services/java/com/android/server/wm/AppWindowAnimator.java b/services/java/com/android/server/wm/AppWindowAnimator.java
index 13e8bc5..c25f010 100644
--- a/services/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/java/com/android/server/wm/AppWindowAnimator.java
@@ -10,10 +10,8 @@
 import android.view.animation.Transformation;
 
 import java.io.PrintWriter;
+import java.util.ArrayList;
 
-/**
- *
- */
 public class AppWindowAnimator {
     static final String TAG = "AppWindowAnimator";
 
@@ -48,12 +46,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 +124,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);
             }
         }
@@ -168,7 +169,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;
@@ -255,9 +256,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 +267,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..afcf339c 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);
             }
@@ -212,4 +213,4 @@
             mDimTarget = dimTarget;
         }
     }
-}
\ 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..6e5bbcb
--- /dev/null
+++ b/services/java/com/android/server/wm/DisplayContent.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.view.Display;
+import android.view.DisplayInfo;
+
+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();
+
+
+    // 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;
+
+    DisplayContent(Display display) {
+        mDisplay = display;
+        mDisplayId = display.getDisplayId();
+        display.getDisplayInfo(mDisplayInfo);
+    }
+
+    int getDisplayId() {
+        return mDisplayId;
+    }
+
+    WindowList getWindowList() {
+        return mWindows;
+    }
+
+    Display getDisplay() {
+        return mDisplay;
+    }
+
+    DisplayInfo getDisplayInfo() {
+        return mDisplayInfo;
+    }
+
+    public void dump(PrintWriter pw) {
+        pw.print("  Display: mDisplayId="); pw.println(mDisplayId);
+        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.println();
+    }
+}
diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java
index b2cf3e0..3fcf680 100644
--- a/services/java/com/android/server/wm/DragState.java
+++ b/services/java/com/android/server/wm/DragState.java
@@ -29,6 +29,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.util.Slog;
+import android.view.DisplayInfo;
 import android.view.DragEvent;
 import android.view.InputChannel;
 import android.view.Surface;
@@ -58,6 +59,7 @@
     WindowState mTargetWindow;
     ArrayList<WindowState> mNotifiedWindows;
     boolean mDragInProgress;
+    DisplayContent mDisplayContent;
 
     private final Region mTmpRegion = new Region();
 
@@ -84,7 +86,11 @@
         mNotifiedWindows = null;
     }
 
-    void register() {
+    /**
+     * @param displayContent The display parameters associated with the window being dragged.
+     */
+    void register(DisplayContent displayContent) {
+        mDisplayContent = displayContent;
         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 +107,8 @@
             mDragApplicationHandle.dispatchingTimeoutNanos =
                     WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
 
-            mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null);
+            mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null,
+                    mDisplayContent.getDisplayId());
             mDragWindowHandle.name = "drag";
             mDragWindowHandle.inputChannel = mServerChannel;
             mDragWindowHandle.layer = getDragLayerLw();
@@ -125,8 +132,9 @@
             // The drag window covers the entire display
             mDragWindowHandle.frameLeft = 0;
             mDragWindowHandle.frameTop = 0;
-            mDragWindowHandle.frameRight = mService.mCurDisplayWidth;
-            mDragWindowHandle.frameBottom = mService.mCurDisplayHeight;
+            DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
+            mDragWindowHandle.frameRight = displayInfo.logicalWidth;
+            mDragWindowHandle.frameBottom = displayInfo.logicalHeight;
 
             // Pause rotations before a drag.
             if (WindowManagerService.DEBUG_ORIENTATION) {
@@ -179,9 +187,10 @@
             Slog.d(WindowManagerService.TAG, "broadcasting DRAG_STARTED at (" + touchX + ", " + touchY + ")");
         }
 
-        final int N = mService.mWindows.size();
+        final WindowList windows = mDisplayContent.getWindowList();
+        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 +389,8 @@
         WindowState touchedWin = null;
         final int x = (int) xf;
         final int y = (int) yf;
-        final ArrayList<WindowState> windows = mService.mWindows;
+
+        final WindowList windows = mDisplayContent.getWindowList();
         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..5ff8a9b 100644
--- a/services/java/com/android/server/wm/InputMonitor.java
+++ b/services/java/com/android/server/wm/InputMonitor.java
@@ -128,7 +128,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 +139,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 +201,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,8 +225,9 @@
             addInputWindowHandleLw(mService.mFakeWindows.get(i).mWindowHandle);
         }
 
-        final int N = windows.size();
-        for (int i = N - 1; i >= 0; i--) {
+        // TODO(multidisplay): Input only occurs on the default display.
+        final WindowList windows = mService.getDefaultWindowList();
+        for (int i = windows.size() - 1; i >= 0; i--) {
             final WindowState child = windows.get(i);
             final InputChannel inputChannel = child.mInputChannel;
             final InputWindowHandle inputWindowHandle = child.mInputWindowHandle;
@@ -209,39 +250,20 @@
                 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) {
+                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/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index 938db9e..acf3249 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,6 +42,7 @@
     static final int FREEZE_LAYER = WindowManagerService.TYPE_LAYER_MULTIPLIER * 200;
 
     final Context mContext;
+    final Display mDisplay;
     Surface mSurface;
     BlackFrame mCustomBlackFrame;
     BlackFrame mExitingBlackFrame;
@@ -185,9 +187,10 @@
                 pw.println();
     }
 
-    public ScreenRotationAnimation(Context context, SurfaceSession session,
+    public ScreenRotationAnimation(Context context, Display display, SurfaceSession session,
             boolean inTransaction, int originalWidth, int originalHeight, int originalRotation) {
         mContext = context;
+        mDisplay = display;
 
         // Screenshot does NOT include rotation!
         if (originalRotation == Surface.ROTATION_90
@@ -212,17 +215,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();
@@ -472,6 +478,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 +497,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);
@@ -520,7 +528,8 @@
                 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);
@@ -542,7 +551,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 {
diff --git a/services/java/com/android/server/wm/Session.java b/services/java/com/android/server/wm/Session.java
index 61c0e9c..1ffbecc 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);
             mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
             if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel,
                     mService.mDragState.mServerChannel)) {
@@ -389,6 +408,20 @@
         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);
+            }
+        }
+    }
+
     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..580f00d 100644
--- a/services/java/com/android/server/wm/WindowAnimator.java
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -8,19 +8,22 @@
 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.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,22 +35,16 @@
 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>();
+    ArrayList<WinAnimatorList> mWinAnimatorLists = new ArrayList<WinAnimatorList>();
 
     boolean mAnimating;
-    WindowState mWindowAnimationBackground;
-    int mWindowAnimationBackgroundColor;
+
+    final Runnable mAnimationRunnable;
+
     int mAdjResult;
 
     int mPendingLayoutChanges;
@@ -71,11 +68,14 @@
     // 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;
@@ -84,18 +84,132 @@
     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;
+        int 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;
+
+    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 initializeLocked(final int layerStack) {
+        mWindowAnimationBackgroundSurface =
+                new DimSurface(mService.mFxSession, layerStack);
+        mDimAnimator = new DimAnimator(mService.mFxSession, layerStack);
+        mInitialized = true;
+    }
+
+    /** Locked on mAnimToLayout */
+    void updateAnimToLayoutLocked() {
+        final AnimatorToLayoutParams animToLayout = mAnimToLayout;
+        synchronized (animToLayout) {
+            animToLayout.mBulkUpdateParams = mBulkUpdateParams;
+            animToLayout.mPendingLayoutChanges = mPendingLayoutChanges;
+            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);
+            }
+
+            mWinAnimatorLists =
+                    new ArrayList<WinAnimatorList>(layoutToAnim.mWinAnimatorLists);
+            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.
+            DimAnimator.Parameters dimParams = layoutToAnim.mDimParams;
+            if (dimParams == null) {
+                mDimParams = dimParams;
+            } else {
+                final WindowStateAnimator newWinAnimator = dimParams.mDimWinAnimator;
+
+                // Only set dim params on the highest dimmed layer.
+                final WindowStateAnimator existingDimWinAnimator = mDimParams == null
+                        ? null : mDimParams.mDimWinAnimator;
+                // Don't turn on for an unshown surface, or for any layer but the highest dimmed one.
+                if (newWinAnimator.mSurfaceShown &&
+                        (existingDimWinAnimator == null || !existingDimWinAnimator.mSurfaceShown
+                        || existingDimWinAnimator.mAnimLayer < newWinAnimator.mAnimLayer)) {
+                    mDimParams = 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();
@@ -108,51 +222,11 @@
         }
     }
 
-    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;
         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)) {
@@ -199,15 +273,22 @@
         }
     }
 
-    private void updateWindowsAndWallpaperLocked() {
+    private void updateWindowsLocked(final WinAnimatorList winAnimatorList) {
         ++mAnimTransactionSequence;
 
         ArrayList<WindowStateAnimator> unForceHiding = null;
         boolean wallpaperInUnForceHiding = false;
 
-        for (int i = mService.mWindows.size() - 1; i >= 0; i--) {
-            WindowState win = mService.mWindows.get(i);
-            WindowStateAnimator winAnimator = win.mWinAnimator;
+        // forceHiding states.
+        final int KEYGUARD_NOT_SHOWN     = 0;
+        final int KEYGUARD_ANIMATING_IN  = 1;
+        final int KEYGUARD_SHOWN         = 2;
+        final int KEYGUARD_ANIMATING_OUT = 3;
+        int forceHiding = KEYGUARD_NOT_SHOWN;
+
+        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,51 +300,7 @@
                             ", 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;
                     if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
@@ -288,16 +325,16 @@
                     if (win.isReadyForDisplay()) {
                         if (nowAnimating) {
                             if (winAnimator.mAnimationIsEntrance) {
-                                mForceHiding = KEYGUARD_ANIMATING_IN;
+                                forceHiding = KEYGUARD_ANIMATING_IN;
                             } else {
-                                mForceHiding = KEYGUARD_ANIMATING_OUT;
+                                forceHiding = KEYGUARD_ANIMATING_OUT;
                             }
                         } else {
-                            mForceHiding = KEYGUARD_SHOWN;
+                            forceHiding = KEYGUARD_SHOWN;
                         }
                     }
                     if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
-                            "Force hide " + mForceHiding
+                            "Force hide " + forceHiding
                             + " hasSurface=" + win.mHasSurface
                             + " policyVis=" + win.mPolicyVisibility
                             + " destroying=" + win.mDestroying
@@ -309,9 +346,9 @@
                     final boolean hideWhenLocked =
                             (winAnimator.mAttrFlags & FLAG_SHOW_WHEN_LOCKED) == 0;
                     final boolean changed;
-                    if (((mForceHiding == KEYGUARD_ANIMATING_IN)
+                    if (((forceHiding == KEYGUARD_ANIMATING_IN)
                                 && (!winAnimator.isAnimating() || hideWhenLocked))
-                            || ((mForceHiding == KEYGUARD_SHOWN) && hideWhenLocked)) {
+                            || ((forceHiding == KEYGUARD_SHOWN) && hideWhenLocked)) {
                         changed = win.hideLw(false, false);
                         if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
                                 "Now policy hidden: " + win);
@@ -326,7 +363,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,7 +375,7 @@
                             }
                         }
                     }
-                    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;
                         if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
@@ -361,8 +398,7 @@
                     }
                 }
             }
-            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,21 +424,112 @@
         }
     }
 
+    private void updateWallpaperLocked(final WinAnimatorList winAnimatorList) {
+        WindowStateAnimator windowAnimationBackground = null;
+        int windowAnimationBackgroundColor = 0;
+        WindowState detachedWallpaper = null;
+
+        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;
+                    }
+                }
+            }
+
+            mWindowAnimationBackgroundSurface.show(mDw, mDh,
+                    animLayer - WindowManagerService.LAYER_OFFSET_DIM,
+                    windowAnimationBackgroundColor);
+        } else {
+            mWindowAnimationBackgroundSurface.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 "
@@ -419,7 +546,7 @@
 
                         // We can now show all of the drawn windows!
                         if (!mService.mOpeningApps.contains(wtoken)) {
-                            mAnimating |= wtoken.mAppAnimator.showAllWindowsLocked();
+                            mAnimating |= appAnimator.showAllWindowsLocked();
                         }
                     }
                 }
@@ -427,13 +554,10 @@
         }
     }
 
-    private void performAnimationsLocked() {
-        mForceHiding = KEYGUARD_NOT_SHOWN;
-        mDetachedWallpaper = null;
-        mWindowAnimationBackground = null;
-        mWindowAnimationBackgroundColor = 0;
+    private void performAnimationsLocked(final WinAnimatorList winAnimatorList) {
+        updateWindowsLocked(winAnimatorList);
+        updateWallpaperLocked(winAnimatorList);
 
-        updateWindowsAndWallpaperLocked();
         if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
             mPendingActions |= WALLPAPER_ACTION_PENDING;
         }
@@ -441,10 +565,21 @@
         testTokenMayBeDrawnLocked();
     }
 
-    synchronized void animate() {
+    // TODO(cmautner): Change the following comment when no longer locked on mWindowMap */
+    /** Locked on mService.mWindowMap and this. */
+    private void animateLocked() {
+        if (!mInitialized) {
+            return;
+        }
+        for (int i = mWinAnimatorLists.size() - 1; i >= 0; i--) {
+            animateLocked(mWinAnimatorLists.get(i));
+        }
+    }
+
+    private void animateLocked(final WinAnimatorList winAnimatorList) {
         mPendingLayoutChanges = 0;
         mCurrentTime = SystemClock.uptimeMillis();
-        mBulkUpdateParams = 0;
+        mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
         boolean wasAnimating = mAnimating;
         mAnimating = false;
         if (WindowManagerService.DEBUG_WINDOW_TRACE) {
@@ -457,8 +592,7 @@
 
         try {
             updateWindowsAppsAndRotationAnimationsLocked();
-            performAnimationsLocked();
-            testWallpaperAndBackgroundLocked();
+            performAnimationsLocked(winAnimatorList);
 
             // THIRD LOOP: Update the surfaces of all windows.
 
@@ -466,9 +600,9 @@
                 mScreenRotationAnimation.updateSurfaces();
             }
 
-            final int N = mWinAnimators.size();
+            final int N = winAnimatorList.size();
             for (int i = 0; i < N; i++) {
-                mWinAnimators.get(i).prepareSurfaceLocked(true);
+                winAnimatorList.get(i).prepareSurfaceLocked(true);
             }
 
             if (mDimParams != null) {
@@ -497,10 +631,14 @@
             Surface.closeTransaction();
         }
 
-        mService.bulkSetParameters(mBulkUpdateParams, mPendingLayoutChanges);
+        if (mBulkUpdateParams != 0 || mPendingLayoutChanges != 0) {
+            updateAnimToLayoutLocked();
+        }
 
         if (mAnimating) {
-            mService.scheduleAnimationLocked();
+            synchronized (mService.mLayoutToAnim) {
+                mService.scheduleAnimationLocked();
+            }
         } else if (wasAnimating) {
             mService.requestTraversalLocked();
         }
@@ -524,28 +662,6 @@
         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)));
-        }
-    }
-
-    // TODO(cmautner): Move into Handler
-    void stopDimming() {
-        mService.mH.sendMessage(mService.mH.obtainMessage(SET_DIM_PARAMETERS, null));
-    }
-
     boolean isDimming() {
         return mDimParams != null;
     }
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 7011343..0d9db90 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,13 @@
 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.DisplayDeviceInfo;
+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 +57,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,15 +72,15 @@
 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;
@@ -89,22 +92,25 @@
 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.LogPrinter;
 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.IInputFilter;
 import android.view.IOnKeyguardExitResult;
 import android.view.IRotationWatcher;
 import android.view.IWindow;
@@ -119,8 +125,9 @@
 import android.view.Surface;
 import android.view.SurfaceSession;
 import android.view.View;
+import android.view.ViewTreeObserver;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
+import android.view.WindowManagerGlobal;
 import android.view.WindowManagerPolicy;
 import android.view.WindowManager.LayoutParams;
 import android.view.WindowManagerPolicy.FakeWindow;
@@ -131,6 +138,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,6 +159,7 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.NoSuchElementException;
 
 /** {@hide} */
 public class WindowManagerService extends IWindowManager.Stub
@@ -267,58 +276,31 @@
 
     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);
+                Slog.v(TAG, "Switching user from " + mCurrentUserId + " to " + newUserId);
+                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 +365,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.
      */
@@ -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,6 +452,7 @@
 
     final Rect mSystemDecorRect = new Rect();
     int mSystemDecorLayer = 0;
+    final Rect mScreenRect = new Rect();
 
     int mPendingLayoutChanges = 0;
     boolean mLayoutNeeded = true;
@@ -512,9 +469,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 +486,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,7 +503,7 @@
     final ArrayList<AppWindowToken> mOpeningApps = new ArrayList<AppWindowToken>();
     final ArrayList<AppWindowToken> mClosingApps = new ArrayList<AppWindowToken>();
 
-    Display mDisplay;
+    Display mDefaultDisplay;
 
     boolean mIsTouchDevice;
 
@@ -583,10 +541,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 +569,8 @@
     float mAnimatorDurationScale = 1.0f;
 
     final InputManagerService mInputManager;
+    final DisplayManagerService mDisplayManagerService;
+    final DisplayManager mDisplayManager;
 
     // Who is holding the screen on.
     Session mHoldingScreenOn;
@@ -626,7 +586,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 +601,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 wtoken = appAnimator.mAppToken;
+            mWinAnimators = new ArrayList<WindowStateAnimator>();
+            final int N = wtoken.allAppWindows.size();
+            for (int i = 0; i < N; i++) {
+                mWinAnimators.add(wtoken.allAppWindows.get(i).mWinAnimator);
+            }
+        }
+    }
+
+    static class LayoutToAnimatorParams {
+        boolean mParamsModified;
+
+        static final long WALLPAPER_TOKENS_CHANGED = 1 << 0;
+        long mChanges;
+
+        boolean mAnimationScheduled;
+        ArrayList<WinAnimatorList> mWinAnimatorLists = new ArrayList<WinAnimatorList>();
+        WindowState mWallpaperTarget;
+        WindowState mLowerWallpaperTarget;
+        WindowState mUpperWallpaperTarget;
+        DimAnimator.Parameters mDimParams;
+        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 +648,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 {
@@ -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;
-        }
+        });
+        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();
-        }
+        });
     }
 
     private WindowManagerService(Context context, PowerManagerService pm,
+            DisplayManagerService displayManager, Handler uiHandler,
             boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
         mContext = context;
         mHaveInputMethods = haveInputMethods;
@@ -880,7 +778,11 @@
         mOnlyCore = onlyCore;
         mLimitedAlphaCompositing = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_sf_limitedAlpha);
-        mHeadless = "1".equals(SystemProperties.get(SYSTEM_HEADLESS, "0"));
+        mDisplayManagerService = displayManager;
+        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
+        mHeadless = displayManager.isHeadless();
+
+        mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
 
         mPowerManager = pm;
         mPowerManager.setPolicy(mPolicy);
@@ -897,38 +799,30 @@
                 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();
@@ -955,34 +849,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;
             }
@@ -993,9 +884,9 @@
     private void addWindowToListInOrderLocked(WindowState win, boolean addToToken) {
         final IWindow client = win.mClient;
         final WindowToken token = win.mToken;
-        final ArrayList<WindowState> localmWindows = mWindows;
 
-        final int N = localmWindows.size();
+        final WindowList windows = win.getWindowList();
+        final int N = windows.size();
         final WindowState attached = win.mAttachedWindow;
         int i;
         if (attached == null) {
@@ -1027,7 +918,7 @@
                                     Slog.v(TAG, "Adding window " + win + " at "
                                             + (newIdx+1) + " of " + N);
                                 }
-                                localmWindows.add(newIdx+1, win);
+                                windows.add(newIdx+1, win);
                                 mWindowsChanged = true;
                             }
                         }
@@ -1100,7 +991,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 +1000,7 @@
                                 Slog.v(TAG, "Adding window " + win + " at "
                                         + i + " of " + N);
                             }
-                            localmWindows.add(i, win);
+                            windows.add(i, win);
                             mWindowsChanged = true;
                         }
                     }
@@ -1118,7 +1009,7 @@
                 // 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) {
+                    if (windows.get(i).mBaseLayer <= myLayer) {
                         i++;
                         break;
                     }
@@ -1127,9 +1018,10 @@
                 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);
@@ -1157,8 +1049,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 {
@@ -1226,13 +1117,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 = getDefaultWindowList();
+        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 +1141,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 +1161,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 +1176,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 +1234,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 +1247,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 +1261,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.
+            getDefaultWindowList().add(pos, win);
             mWindowsChanged = true;
             moveInputMethodDialogsLocked(pos+1);
             return;
@@ -1418,22 +1300,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 +1328,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 = getDefaultWindowList();
         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 +1358,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 +1377,7 @@
             }
             if (DEBUG_INPUT_METHOD) {
                 Slog.v(TAG, "Final window list:");
-                logWindowList("  ");
+                logWindowList(windows, "  ");
             }
             return;
         }
@@ -1502,7 +1387,7 @@
             reAddWindowToListInOrderLocked(win);
             if (DEBUG_INPUT_METHOD) {
                 Slog.v(TAG, "No IM target, final list:");
-                logWindowList("  ");
+                logWindowList(windows, "  ");
             }
         }
     }
@@ -1514,6 +1399,9 @@
             return false;
         }
 
+        // TODO(multidisplay): IMEs are only supported on the default display.
+        WindowList windows = getDefaultWindowList();
+
         int imPos = findDesiredInputMethodWindowIndexLocked(true);
         if (imPos >= 0) {
             // In this case, the input method windows are to be placed
@@ -1521,9 +1409,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 +1427,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 +1435,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 +1449,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 +1478,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 +1519,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 = getDefaultDisplayContent().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 = getDefaultWindowList();
+        int N = windows.size();
         WindowState w = null;
         WindowState foundW = null;
         int foundI = 0;
@@ -1647,7 +1537,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 +1546,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 +1572,7 @@
                     continue;
                 }
                 break;
-            } else if (w == mAnimator.mWindowDetachedWallpaper) {
+            } else if (w == mWindowDetachedWallpaper) {
                 windowDetachedI = i;
             }
         }
@@ -1741,7 +1631,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 +1650,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 +1715,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 +1741,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) {
@@ -1901,18 +1791,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 +1815,7 @@
                             + " from " + oldIndex + " to " + foundI);
                 }
 
-                localmWindows.add(foundI, wallpaper);
+                windows.add(foundI, wallpaper);
                 mWindowsChanged = true;
                 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED;
             }
@@ -2040,14 +1930,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 +1966,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 +1996,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) {
@@ -2146,12 +2024,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 +2039,13 @@
         long origId;
 
         synchronized(mWindowMap) {
-            if (mDisplay == null) {
+            if (mDefaultDisplay == null) {
                 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 +2053,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 +2070,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 +2095,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 = getDisplayContent(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();
 
@@ -2322,10 +2201,10 @@
             mPolicy.getContentInsetHintLw(attrs, outContentInsets);
 
             if (mInTouchMode) {
-                res |= WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE;
+                res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
             }
             if (win.mAppToken == null || !win.mAppToken.clientHidden) {
-                res |= WindowManagerImpl.ADD_FLAG_APP_VISIBLE;
+                res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
             }
 
             mInputMonitor.setUpdateInputWindowsNeededLw();
@@ -2343,7 +2222,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 +2236,7 @@
             if (localLOGV) Slog.v(
                 TAG, "New client " + client.asBinder()
                 + ": window=" + win);
-            
+
             if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
                 reportNewConfig = true;
             }
@@ -2485,7 +2364,9 @@
 
         if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win);
         mWindowMap.remove(win.mClient.asBinder());
-        mWindows.remove(win);
+
+        final WindowList windows = win.getWindowList();
+        windows.remove(win);
         mPendingRemove.remove(win);
         mWindowsChanged = true;
         if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win);
@@ -2543,14 +2424,14 @@
         }
 
         if (!mInLayout) {
-            assignLayersLocked();
+            assignLayersLocked(windows);
             mLayoutNeeded = true;
             performLayoutAndPlaceSurfacesLocked();
             if (win.mAppToken != null) {
                 win.mAppToken.updateReportedVisibilityLocked();
             }
         }
-        
+
         mInputMonitor.updateInputWindowsLw(true /*force*/);
     }
 
@@ -2683,6 +2564,32 @@
         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;
+        mLayoutNeeded = true;
+        performLayoutAndPlaceSurfacesLocked();
+    }
+
     public int relayoutWindow(Session session, IWindow client, int seq,
             WindowManager.LayoutParams attrs, int requestedWidth,
             int requestedHeight, int viewVisibility, int flags,
@@ -2729,7 +2636,7 @@
             }
 
             winAnimator.mSurfaceDestroyDeferred =
-                    (flags&WindowManagerImpl.RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
+                    (flags&WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
 
             int attrChanges = 0;
             int flagChanges = 0;
@@ -2848,7 +2755,7 @@
                     }
                 } catch (Exception e) {
                     mInputMonitor.updateInputWindowsLw(true /*force*/);
-                    
+
                     Slog.w(TAG, "Exception thrown when creating surface for client "
                              + client + " (" + win.mAttrs.getTitle() + ")",
                              e);
@@ -2948,14 +2855,16 @@
             }
 
             mLayoutNeeded = true;
-            win.mGivenInsetsPending = (flags&WindowManagerImpl.RELAYOUT_INSETS_PENDING) != 0;
+            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 = getDefaultDisplayInfo();
+                updateWallpaperOffsetLocked(win,
+                        displayInfo.appWidth, displayInfo.appHeight, false);
             }
             if (win.mAppToken != null) {
                 win.mAppToken.updateReportedVisibilityLocked();
@@ -2989,10 +2898,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) {
@@ -3042,7 +2951,12 @@
         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;
@@ -3128,12 +3042,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 +3083,12 @@
                 duration = 300;
                 break;
         }
+        // TODO(multidisplay): For now assume all app animation is on main display.
+        final DisplayInfo displayInfo = getDefaultDisplayInfo();
         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 +3108,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 +3124,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,62 +3131,102 @@
                         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 = getDefaultDisplayInfo();
         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;
     }
 
@@ -3299,14 +3253,14 @@
                         "applyAnimation: wtoken=" + wtoken
                         + " 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);
+            } 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";
+                    String animName = scaleUp ? "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN";
                     Slog.v(TAG, "applyAnimation: wtoken=" + wtoken
                             + " anim=" + a + " nextAppTransition=" + animName
                             + " transit=" + transit + " Callers " + Debug.getCallers(3));
@@ -3440,7 +3394,7 @@
         Slog.w(TAG, msg);
         return false;
     }
-    
+
     boolean okToDisplay() {
         return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully();
     }
@@ -3470,10 +3424,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,7 +3455,8 @@
                         }
 
                         if (win.isVisibleNow()) {
-                            win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT, false);
+                            win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT,
+                                    false);
                             changed = true;
                         }
                     }
@@ -3515,6 +3472,7 @@
                         mExitingTokens.add(wtoken);
                     } else if (wtoken.windowType == TYPE_WALLPAPER) {
                         mWallpaperTokens.remove(wtoken);
+                        updateLayoutToAnimWallpaperTokens();
                     }
                 }
 
@@ -3591,6 +3549,7 @@
         }
     }
 
+    @Override
     public void setAppGroupId(IBinder token, int groupId) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "setAppGroupId()")) {
@@ -3617,9 +3576,11 @@
             return mLastWindowForcedOrientation;
         }
 
-        int pos = mWindows.size() - 1;
+        // TODO(multidisplay): Change to the correct display.
+        final WindowList windows = getDefaultWindowList();
+        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 +3594,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);
     }
@@ -3685,7 +3646,7 @@
                 haveGroup = true;
                 curGroup = wtoken.groupId;
                 lastOrientation = wtoken.requestedOrientation;
-            } 
+            }
 
             int or = wtoken.requestedOrientation;
             // If this application is fullscreen, and didn't explicitly say
@@ -3712,6 +3673,7 @@
         return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
     }
 
+    @Override
     public Configuration updateOrientationFromAppTokens(
             Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
@@ -3721,7 +3683,7 @@
 
         Configuration config = null;
         long ident = Binder.clearCallingIdentity();
-        
+
         synchronized(mWindowMap) {
             config = updateOrientationFromAppTokensLocked(currentConfig,
                     freezeThisOneIfNeeded);
@@ -3762,7 +3724,7 @@
                 }
             }
         }
-        
+
         return config;
     }
 
@@ -3773,7 +3735,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 +3772,7 @@
         return req;
     }
 
+    @Override
     public void setNewConfiguration(Configuration config) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "setNewConfiguration()")) {
@@ -3822,7 +3785,8 @@
             performLayoutAndPlaceSurfacesLocked();
         }
     }
-    
+
+    @Override
     public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "setAppOrientation()")) {
@@ -3971,14 +3935,14 @@
     }
 
     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);
@@ -4075,7 +4039,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);
@@ -4612,14 +4576,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 +4602,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 +4627,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 +4646,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 +4655,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 +4668,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 +4677,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, token.windows.get(i));
+            }
         }
         return index;
     }
@@ -4779,7 +4751,13 @@
                 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);
+                        reAddAppWindowsLocked(displayContent, pos, wtoken);
+                    }
                     if (DEBUG_REORDER) Slog.v(TAG, "Final window list:");
                     if (DEBUG_REORDER) dumpWindowsLocked();
                     updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
@@ -4818,18 +4796,25 @@
         // 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);
+            reAddAppWindowsLocked(displayContent, pos, wtoken);
+
+            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();
-            }
+
+            // Note that the above updateFocusedWindowLocked conditional used to sit here.
+
             mLayoutNeeded = true;
             if (!mInLayout) {
                 performLayoutAndPlaceSurfacesLocked();
@@ -4849,22 +4834,29 @@
             }
         }
 
-        // 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) {
+                    pos = reAddAppWindowsLocked(displayContent, pos, token);
+                }
+            }
+            if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+                    false /*updateInputWindows*/)) {
+                assignLayersLocked(windows);
             }
         }
 
         mInputMonitor.setUpdateInputWindowsNeededLw();
-        if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
-                false /*updateInputWindows*/)) {
-            assignLayersLocked();
-        }
+
+        // Note that the above updateFocusedWindowLocked used to sit here.
+
         mLayoutNeeded = true;
         performLayoutAndPlaceSurfacesLocked();
         mInputMonitor.updateInputWindowsLw(false /*force*/);
@@ -4946,59 +4938,26 @@
     // 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;
-            }
-        }
-        return mAllowDisableKeyguard == ALLOW_DISABLE_YES;
-    }
-
+    @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 +5003,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 +5055,7 @@
                 mTransitionAnimationScale = fixScale(scales[1]);
             }
             if (scales.length >= 3) {
-                mAnimatorDurationScale = fixScale(scales[2]);
+                setAnimatorDurationScale(fixScale(scales[2]));
             }
         }
 
@@ -5103,6 +5063,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 +5113,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 +5215,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 = getDefaultWindowList();
+                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 +5371,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;
@@ -5418,7 +5389,7 @@
             Surface.openTransaction();
             try {
                 if (mStrictModeFlash == null) {
-                    mStrictModeFlash = new StrictModeFlash(mDisplay, mFxSession);
+                    mStrictModeFlash = new StrictModeFlash(mDefaultDisplay, mFxSession);
                 }
                 mStrictModeFlash.setVisibility(on);
             } finally {
@@ -5438,10 +5409,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 +5431,10 @@
         synchronized(mWindowMap) {
             long ident = Binder.clearCallingIdentity();
 
-            dw = mCurDisplayWidth;
-            dh = mCurDisplayHeight;
+            final DisplayContent displayContent = getDisplayContent(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 +5448,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 +5502,7 @@
             }
 
             // The screenshot API does not apply the current screen rotation.
-            rot = mDisplay.getRotation();
+            rot = mDefaultDisplay.getRotation();
             int fw = frame.width();
             int fh = frame.height();
 
@@ -5562,10 +5537,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);
@@ -5687,6 +5663,7 @@
         Binder.restoreCallingIdentity(origId);
     }
 
+    // TODO(multidisplay): Rotate any display?
     /**
      * Updates the current rotation.
      *
@@ -5754,8 +5731,7 @@
         mWaitingForConfig = true;
         mLayoutNeeded = true;
         startFreezingDisplayLocked(inTransaction);
-        mInputManager.setDisplayOrientation(0, rotation,
-                mDisplay != null ? mDisplay.getExternalRotation() : Surface.ROTATION_0);
+        mInputManager.setDisplayOrientation(0, rotation, Surface.ROTATION_0);
 
         // We need to update our screen size information to match the new
         // rotation.  Note that this is redundant with the later call to
@@ -5770,6 +5746,8 @@
                     ">>> OPEN TRANSACTION setRotationUnchecked");
             Surface.openTransaction();
         }
+        final DisplayContent displayContent = getDefaultDisplayContent();
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
         try {
             // NOTE: We disable the rotation in the emulator because
             //       it doesn't support hardware OpenGL emulation yet.
@@ -5777,11 +5755,12 @@
                     && mAnimator.mScreenRotationAnimation.hasScreenshot()) {
                 if (mAnimator.mScreenRotationAnimation.setRotation(rotation, mFxSession,
                         MAX_ANIMATION_DURATION, mTransitionAnimationScale,
-                        mCurDisplayWidth, mCurDisplayHeight)) {
-                    scheduleAnimationLocked();
+                        displayInfo.logicalWidth, displayInfo.logicalHeight)) {
+                    updateLayoutToAnimationLocked();
                 }
             }
-            Surface.setOrientation(0, rotation);
+            mDisplayManagerService.setDisplayOrientation(
+                    displayContent.getDisplayId(), rotation);
         } finally {
             if (!inTransaction) {
                 Surface.closeTransaction();
@@ -5790,10 +5769,11 @@
             }
         }
 
-        rebuildBlackFrame();
+        rebuildBlackFrameLocked();
 
-        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;
@@ -5864,7 +5844,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 = getDefaultDisplayContent();
+            if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
                 // On devices with a natural orientation of portrait
                 switch (rotation) {
                     default:
@@ -5875,7 +5857,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 +5868,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 +5982,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 +5998,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 +6024,7 @@
         return result;
     }
 
+    // TODO(multidisplay): Extend to multiple displays.
     /**
      * Returns the focused window in the following format:
      * windowHashCodeInHexadecimal windowName
@@ -6224,15 +6210,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,20 +6259,20 @@
         return config;
     }
 
-    private void adjustDisplaySizeRanges(int rotation, int dw, int dh) {
+    private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) {
         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;
         }
     }
 
@@ -6370,8 +6355,8 @@
         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) {
         // 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,21 +6369,21 @@
             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.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
         outConfig.screenLayout = sl;
     }
 
@@ -6433,42 +6418,39 @@
     }
 
     boolean computeScreenConfigurationLocked(Configuration config) {
-        if (mDisplay == null) {
+        if (mDefaultDisplay == null) {
             return false;
         }
 
+        // TODO(multidisplay): For now, apply Configuration to main screen only.
+        final DisplayContent displayContent = getDefaultDisplayContent();
+
         // 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) {
@@ -6479,25 +6461,29 @@
             config.orientation = orientation;
         }
 
-        // 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 +6492,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 +6625,9 @@
             synchronized (mWindowMap) {
                 try {
                     if (mDragState == null) {
-                        Surface surface = new Surface(session, callerPid, "drag surface", 0,
+                        Surface surface = new Surface(session, "drag surface",
                                 width, height, PixelFormat.TRANSLUCENT, Surface.HIDDEN);
+                        surface.setLayerStack(mDefaultDisplay.getLayerStack());
                         if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DRAG "
                                 + surface + ": CREATE");
                         outSurface.copyFrom(surface);
@@ -6720,8 +6708,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,8 +6722,11 @@
         }
     }
 
-    // TODO: This is a workaround - remove when 6623031 is fixed.
     public boolean getWindowFrame(IBinder token, Rect outBounds) {
+        if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
+                "getWindowFrame()")) {
+            throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission.");
+        }
         synchronized (mWindowMap) {
             WindowState windowState = mWindowMap.get(token);
             if (windowState != null) {
@@ -6790,45 +6784,60 @@
     }
 
     public void displayReady() {
+        WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
+        final Display display = wm.getDefaultDisplay();
+        displayReady(display.getDisplayId());
+
         synchronized(mWindowMap) {
-            if (mDisplay != null) {
-                throw new IllegalStateException("Display already initialized");
-            }
-            WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
-            mDisplay = wm.getDefaultDisplay();
+            readForcedDisplaySizeAndDensityLocked(getDefaultDisplayContent());
+
+            mDefaultDisplay = display;
             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);
+                PackageManager.FEATURE_TOUCHSCREEN);
+
+            mAnimator.initializeLocked(display.getLayerStack());
+
+            final DisplayInfo displayInfo = getDefaultDisplayInfo();
+            mAnimator.setDisplayDimensions(displayInfo.logicalWidth, displayInfo.logicalHeight,
+                displayInfo.appWidth, displayInfo.appHeight);
+
+            DisplayDeviceInfo info = new DisplayDeviceInfo();
+            mDisplayManagerService.getDefaultExternalDisplayDeviceInfo(info);
+
+            final DisplayContent displayContent = getDefaultDisplayContent();
+            mInputManager.setDisplaySize(displayContent.getDisplayId(),
+                    displayContent.mInitialDisplayWidth, displayContent.mInitialDisplayHeight,
+                    info.width, info.height);
+            mInputManager.setDisplayOrientation(displayContent.getDisplayId(),
+                    mDefaultDisplay.getRotation(), Surface.ROTATION_0);
+            mPolicy.setInitialDisplaySize(mDefaultDisplay, 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 = getDisplayContent(displayId);
+            final DisplayInfo displayInfo;
+            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 +6845,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 +6872,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 +6885,13 @@
         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 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 +7126,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 = getDefaultWindowList();
+                        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 +7144,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 +7170,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();
@@ -7306,42 +7289,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 +7314,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;
@@ -7416,13 +7352,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 = getDefaultWindowList().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,141 +7388,191 @@
                             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 = getDisplayContent(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 longDimen, int shortDimen) {
         synchronized(mWindowMap) {
+            final DisplayContent displayContent = getDisplayContent(displayId);
             int width, height;
-            if (mInitialDisplayWidth < mInitialDisplayHeight) {
-                width = shortDimen < mInitialDisplayWidth
-                        ? shortDimen : mInitialDisplayWidth;
-                height = longDimen < mInitialDisplayHeight
-                        ? longDimen : mInitialDisplayHeight;
+            if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
+                width = shortDimen < displayContent.mInitialDisplayWidth
+                        ? shortDimen : displayContent.mInitialDisplayWidth;
+                height = longDimen < displayContent.mInitialDisplayHeight
+                        ? longDimen : displayContent.mInitialDisplayHeight;
             } else {
-                width = longDimen < mInitialDisplayWidth
-                        ? longDimen : mInitialDisplayWidth;
-                height = shortDimen < mInitialDisplayHeight
-                        ? shortDimen : mInitialDisplayHeight;
+                width = longDimen < displayContent.mInitialDisplayWidth
+                        ? longDimen : displayContent.mInitialDisplayWidth;
+                height = shortDimen < displayContent.mInitialDisplayHeight
+                        ? shortDimen : displayContent.mInitialDisplayHeight;
             }
-            setForcedDisplaySizeLocked(width, height);
+            setForcedDisplaySizeLocked(displayContent, width, height);
             Settings.Secure.putString(mContext.getContentResolver(),
                     Settings.Secure.DISPLAY_SIZE_FORCED, width + "," + height);
         }
     }
 
-    private void rebuildBlackFrame() {
+    private void rebuildBlackFrameLocked() {
         if (mBlackFrame != null) {
             mBlackFrame.kill();
             mBlackFrame = null;
         }
-        if (mBaseDisplayWidth < mInitialDisplayWidth
-                || mBaseDisplayHeight < mInitialDisplayHeight) {
+        // TODO(multidisplay): For now rotations are only main screen.
+        final DisplayContent displayContent = getDefaultDisplayContent();
+        if (displayContent.mBaseDisplayWidth < displayContent.mInitialDisplayWidth
+                || displayContent.mBaseDisplayHeight < displayContent.mInitialDisplayHeight) {
             int initW, initH, baseW, baseH;
             final boolean rotated = (mRotation == Surface.ROTATION_90
                     || mRotation == Surface.ROTATION_270);
+            if (DEBUG_BOOT) {
+                Slog.i(TAG, "BLACK FRAME: rotated=" + rotated + " init="
+                        + displayContent.mInitialDisplayWidth + "x"
+                        + displayContent.mInitialDisplayHeight + " base="
+                        + displayContent.mBaseDisplayWidth + "x"
+                        + displayContent.mBaseDisplayHeight);
+            }
             if (rotated) {
-                initW = mInitialDisplayHeight;
-                initH = mInitialDisplayWidth;
-                baseW = mBaseDisplayHeight;
-                baseH = mBaseDisplayWidth;
+                initW = displayContent.mInitialDisplayHeight;
+                initH = displayContent.mInitialDisplayWidth;
+                baseW = displayContent.mBaseDisplayHeight;
+                baseH = displayContent.mBaseDisplayWidth;
             } else {
-                initW = mInitialDisplayWidth;
-                initH = mInitialDisplayHeight;
-                baseW = mBaseDisplayWidth;
-                baseH = mBaseDisplayHeight;
+                initW = displayContent.mInitialDisplayWidth;
+                initH = displayContent.mInitialDisplayHeight;
+                baseW = displayContent.mBaseDisplayWidth;
+                baseH = displayContent.mBaseDisplayHeight;
             }
             Rect outer = new Rect(0, 0, initW, initH);
             Rect inner = new Rect(0, 0, baseW, baseH);
             try {
-                mBlackFrame = new BlackFrame(mFxSession, outer, inner, MASK_LAYER);
+                mBlackFrame = new BlackFrame(mFxSession, outer, inner, MASK_LAYER,
+                        mDefaultDisplay.getLayerStack());
             } catch (Surface.OutOfResourcesException e) {
             }
         }
     }
 
-    private void readForcedDisplaySizeLocked() {
-        final String str = Settings.Secure.getString(mContext.getContentResolver(),
+    private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) {
+        boolean changed = false;
+        final String sizeStr = Settings.Secure.getString(mContext.getContentResolver(),
                 Settings.Secure.DISPLAY_SIZE_FORCED);
-        if (str == null || str.length() == 0) {
-            return;
+        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) {
+                            changed = true;
+                            Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height);
+                            displayContent.mBaseDisplayWidth = width;
+                            displayContent.mBaseDisplayHeight = height;
+                        }
+                    }
+                } catch (NumberFormatException ex) {
+                }
+            }
         }
-        final int pos = str.indexOf(',');
-        if (pos <= 0 || str.lastIndexOf(',') != pos) {
-            return;
+        final String densityStr = Settings.Secure.getString(mContext.getContentResolver(),
+                Settings.Secure.DISPLAY_DENSITY_FORCED);
+        if (densityStr != null && densityStr.length() > 0) {
+            int density;
+            try {
+                density = Integer.parseInt(densityStr);
+                synchronized(displayContent.mDisplaySizeLock) {
+                    if (displayContent.mBaseDisplayDensity != density) {
+                        changed = true;
+                        Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density);
+                        displayContent.mBaseDisplayDensity = density;
+                    }
+                }
+            } catch (NumberFormatException ex) {
+            }
         }
-        int width, height;
-        try {
-            width = Integer.parseInt(str.substring(0, pos));
-            height = Integer.parseInt(str.substring(pos+1));
-        } catch (NumberFormatException ex) {
-            return;
+        if (changed) {
+            rebuildBlackFrameLocked();
         }
-        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);
+    }
+
+    public void clearForcedDisplaySize(int displayId) {
+        synchronized(mWindowMap) {
+            final DisplayContent displayContent = getDisplayContent(displayId);
+            setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
+                    displayContent.mInitialDisplayHeight);
+            Settings.Secure.putString(mContext.getContentResolver(),
+                    Settings.Secure.DISPLAY_SIZE_FORCED, "");
+        }
+    }
+
+    public void setForcedDisplayDensity(int displayId, int density) {
+        synchronized(mWindowMap) {
+            final DisplayContent displayContent = getDisplayContent(displayId);
+            setForcedDisplayDensityLocked(displayContent, density);
+            Settings.Secure.putString(mContext.getContentResolver(),
+                    Settings.Secure.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 = getDisplayContent(displayId);
+            setForcedDisplayDensityLocked(displayContent, displayContent.mInitialDisplayDensity);
+            Settings.Secure.putString(mContext.getContentResolver(),
+                    Settings.Secure.DISPLAY_DENSITY_FORCED, "");
+        }
+    }
+
+    private void reconfigureDisplayLocked(DisplayContent displayContent) {
+        mPolicy.setInitialDisplaySize(mDefaultDisplay, displayContent.mBaseDisplayWidth,
+                displayContent.mBaseDisplayHeight, displayContent.mBaseDisplayDensity);
 
         mLayoutNeeded = true;
 
@@ -7605,19 +7591,11 @@
             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
         }
 
-        rebuildBlackFrame();
+        rebuildBlackFrameLocked();
 
         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 +7638,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 +7658,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 +7669,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 +7689,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 +7721,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 +7734,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;
@@ -7781,7 +7769,7 @@
             }
             if (layerChanged && mAnimator.isDimming(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 +7796,7 @@
             return;
         }
         
-        if (mDisplay == null) {
+        if (mDefaultDisplay == null) {
             // Not yet initialized, nothing to do.
             return;
         }
@@ -7839,34 +7827,32 @@
         } catch (RuntimeException e) {
             Log.wtf(TAG, "Unhandled exception while force removing for memory", e);
         }
-        
+
         try {
-            performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
+            DisplayContentsIterator iterator = new DisplayContentsIterator();
+            while (iterator.hasNext()) {
+                final DisplayContent displayContent = iterator.next();
+                performLayoutAndPlaceSurfacesLockedInner(displayContent, recoveringMemory);
 
-            final int N = mPendingRemove.size();
-            if (N > 0) {
-                if (mPendingRemoveTmp.length < N) {
-                    mPendingRemoveTmp = new WindowState[N+10];
+                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);
+                    }
+
+                    assignLayersLocked(displayContent.getWindowList());
+                    mLayoutNeeded = true;
                 }
-                mPendingRemove.toArray(mPendingRemoveTmp);
-                mPendingRemove.clear();
-                for (int i=0; i<N; i++) {
-                    WindowState w = mPendingRemoveTmp[i];
-                    removeWindowInnerLocked(w.mSession, w);
-                }
-
-                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;
             }
 
+            mInLayout = false;
+
             if (mLayoutNeeded) {
                 if (++mLayoutRepeatCount < 6) {
                     requestTraversalLocked();
@@ -7890,22 +7876,24 @@
         Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
     }
 
-    private final void performLayoutLockedInner(boolean initial, boolean updateInputWindows) {
+    private final void performLayoutLockedInner(final DisplayContent displayContent,
+                                    boolean initial, boolean updateInputWindows) {
         if (!mLayoutNeeded) {
             return;
         }
-        
+        WindowList windows = displayContent.getWindowList();
         mLayoutNeeded = false;
-        
-        final int dw = mCurDisplayWidth;
-        final int dh = mCurDisplayHeight;
+
+        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) {
@@ -7913,9 +7901,12 @@
             Slog.v(TAG, "performLayout: needed="
                     + mLayoutNeeded + " dw=" + dw + " dh=" + dh);
         }
-        
+
+        WindowStateAnimator universeBackground = null;
+
         mPolicy.beginLayoutLw(dw, dh, mRotation);
         mSystemDecorLayer = mPolicy.getSystemDecorRectLw(mSystemDecorRect);
+        mScreenRect.set(0, 0, dw, dh);
 
         int seq = mLayoutSeq+1;
         if (seq < 0) seq = 0;
@@ -7925,7 +7916,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
@@ -7956,7 +7947,8 @@
             // 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 +7966,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 +7983,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 +8044,11 @@
 
     /**
      * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
+     * @param windows TODO(cmautner):
      *
      * @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 +8203,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 +8259,11 @@
                 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(),
+                    Surface surface = new Surface(mFxSession,
+                            "thumbnail anim",
+                            dirty.width(), dirty.height(),
                             PixelFormat.TRANSLUCENT, Surface.HIDDEN);
+                    surface.setLayerStack(mDefaultDisplay.getLayerStack());
                     topOpeningApp.mAppAnimator.thumbnail = surface;
                     if (SHOW_TRANSACTIONS) Slog.i(TAG, "  THUMBNAIL "
                             + surface + ": CREATE");
@@ -8262,7 +8275,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);
@@ -8289,11 +8302,12 @@
             changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT
                     | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
             mLayoutNeeded = true;
-            if (!moveInputMethodWindowsIfNeededLocked(true)) {
-                assignLayersLocked();
+
+            // TODO(multidisplay): IMEs are only supported on the default display.
+            if (windows == getDefaultWindowList() && !moveInputMethodWindowsIfNeededLocked(true)) {
+                assignLayersLocked(windows);
             }
-            updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
-                    false /*updateInputWindows*/);
+            updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/);
             mFocusMayChange = false;
         }
 
@@ -8302,7 +8316,6 @@
 
     /**
      * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
-     *
      * @return bitmap indicating if another pass through layout must be made.
      */
     private int handleAnimatingStoppedAndTransitionLocked() {
@@ -8476,14 +8489,14 @@
                 if (!mAnimator.isDimming(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);
+                    startDimming(winAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount, width, height);
                 }
             }
         }
@@ -8511,21 +8524,23 @@
 
     // "Something has changed!  Let's make it correct now."
     private final void performLayoutAndPlaceSurfacesLockedInner(
-            boolean recoveringMemory) {
+            final DisplayContent displayContent, boolean recoveringMemory) {
         if (DEBUG_WINDOW_TRACE) {
             Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by "
                     + Debug.getCallers(3));
         }
-        if (mDisplay == null) {
+        if (mDefaultDisplay == null) {
             Slog.i(TAG, "skipping performLayoutAndPlaceSurfacesLockedInner with no mDisplay");
             return;
         }
 
+        final WindowList windows = displayContent.getWindowList();
         final long currentTime = SystemClock.uptimeMillis();
-        final int dw = mCurDisplayWidth;
-        final int dh = mCurDisplayHeight;
-        final int innerDw = mAppDisplayWidth;
-        final int innerDh = mAppDisplayHeight;
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+        final int dw = displayInfo.logicalWidth;
+        final int dh = displayInfo.logicalHeight;
+        final int innerDw = displayInfo.appWidth;
+        final int innerDh = displayInfo.appHeight;
 
         int i;
 
@@ -8577,8 +8592,8 @@
                     mPendingLayoutChanges);
 
                 if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
-                    if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
-                        assignLayersLocked();
+                    if ((adjustWallpaperWindowsLocked() & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
+                        assignLayersLocked(windows);
                         mLayoutNeeded = true;
                     }
                 }
@@ -8597,7 +8612,7 @@
 
                 // FIRST LOOP: Perform a layout, if needed.
                 if (repeats < 4) {
-                    performLayoutLockedInner(repeats == 1, false /*updateInputWindows*/);
+                    performLayoutLockedInner(displayContent, repeats == 1, false /*updateInputWindows*/);
                 } else {
                     Slog.w(TAG, "Layout repeat skipped after too many iterations");
                 }
@@ -8608,8 +8623,8 @@
                 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);
+                for (i = windows.size() - 1; i >= 0; i--) {
+                    WindowState w = windows.get(i);
                     if (w.mHasSurface) {
                         mPolicy.animatingWindowLw(w, w.mAttrs);
                     }
@@ -8627,9 +8642,9 @@
 
             boolean focusDisplayed = false;
             boolean updateAllDrawn = false;
-            final int N = mWindows.size();
+            final int N = windows.size();
             for (i=N-1; i>=0; i--) {
-                WindowState w = mWindows.get(i);
+                WindowState w = windows.get(i);
 
                 final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured;
 
@@ -8660,6 +8675,10 @@
                     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) {
+                    }
                 }
 
                 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
@@ -8676,7 +8695,7 @@
                             mInnerFields.mWallpaperMayChange = true;
                             mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
                             if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
-                                debugLayoutRepeats("updateWindowsAndWallpaperLocked 1",
+                                debugLayoutRepeats("wallpaper and commitFinishDrawingLocked true",
                                     mPendingLayoutChanges);
                             }
                         }
@@ -8690,7 +8709,8 @@
                             + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
                             + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
                     }
-                    if (atoken != null && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
+                    if (atoken != null
+                            && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
                         if (atoken.lastTransactionSequence != mTransactionSequence) {
                             atoken.lastTransactionSequence = mTransactionSequence;
                             atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
@@ -8748,7 +8768,7 @@
             }
 
             if (!mInnerFields.mDimming && mAnimator.isDimming()) {
-                mAnimator.stopDimming();
+                stopDimming();
             }
         } catch (RuntimeException e) {
             Log.wtf(TAG, "Unhandled exception in Window Manager", e);
@@ -8760,7 +8780,7 @@
         // all of the app tokens to be shown and see if they are ready
         // to go.
         if (mAppTransitionReady) {
-            mPendingLayoutChanges |= handleAppTransitionReadyLocked();
+            mPendingLayoutChanges |= handleAppTransitionReadyLocked(windows);
             if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked",
                 mPendingLayoutChanges);
         }
@@ -8803,7 +8823,7 @@
             if (DEBUG_WALLPAPER) Slog.v(TAG,
                     "Wallpaper layer changed: assigning layers + relayout");
             mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
-            assignLayersLocked();
+            assignLayersLocked(windows);
         } else if ((mInnerFields.mAdjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) {
             if (DEBUG_WALLPAPER) Slog.v(TAG,
                     "Wallpaper visibility changed: relayout");
@@ -8847,9 +8867,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 +8917,7 @@
                 mExitingTokens.remove(i);
                 if (token.windowType == TYPE_WALLPAPER) {
                     mWallpaperTokens.remove(token);
+                    updateLayoutToAnimWallpaperTokens();
                 }
             }
         }
@@ -8940,31 +8959,25 @@
         // 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;
         }
 
@@ -8986,7 +8999,7 @@
         // be enabled, because the window obscured flags have changed.
         enableScreenIfNeededLocked();
 
-        scheduleAnimationLocked();
+        updateLayoutToAnimationLocked();
 
         if (DEBUG_WINDOW_TRACE) {
             Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: mPendingLayoutChanges="
@@ -8995,6 +9008,10 @@
         }
     }
 
+    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 +9057,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 {
@@ -9063,13 +9084,118 @@
         }
     }
 
+    /** 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.
+            ArrayList<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.add(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(DimAnimator.Parameters params) {
+        synchronized (mLayoutToAnim) {
+            mLayoutToAnim.mDimParams = params;
+            scheduleAnimationLocked();
+        }
+    }
+
+    void startDimming(final WindowStateAnimator winAnimator, final float target,
+                      final int width, final int height) {
+        setAnimDimParams(new DimAnimator.Parameters(winAnimator, width, height, target));
+    }
+
+    void stopDimming() {
+        setAnimDimParams(null);
+    }
+
+    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;
+            }
+
+            mPendingLayoutChanges |= animToLayout.mPendingLayoutChanges;
+            if (mPendingLayoutChanges != 0) {
+                doRequest = true;
+            }
+
+            mWindowDetachedWallpaper = animToLayout.mWindowDetachedWallpaper;
+        }
+        return doRequest;
+    }
+
     boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
                                            boolean secure) {
         final Surface surface = winAnimator.mSurface;
@@ -9088,10 +9214,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 +9233,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 +9251,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,6 +9317,9 @@
             mLosingFocus.remove(newFocus);
             int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
 
+            // TODO(multidisplay): Focused windows on default display only.
+            final DisplayContent displayContent = getDefaultDisplayContent();
+
             final WindowState imWindow = mInputMethodWindow;
             if (newFocus != imWindow && oldFocus != imWindow) {
                 if (moveInputMethodWindowsIfNeededLocked(
@@ -9195,12 +9328,12 @@
                     mLayoutNeeded = 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());
                 }
             }
 
@@ -9208,7 +9341,7 @@
                 // The change in focus caused us to need to do a layout.  Okay.
                 mLayoutNeeded = true;
                 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
-                    performLayoutLockedInner(true /*initial*/, updateInputWindows);
+                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
                 }
             }
 
@@ -9232,12 +9365,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 = getDefaultWindowList();
+        for (int i = windows.size() - 1; i >= 0; i--) {
+            win = windows.get(i);
 
             if (localLOGV || DEBUG_FOCUS) Slog.v(
                 TAG, "Looking for focus: " + i
@@ -9300,7 +9440,7 @@
             return;
         }
 
-        if (mDisplay == null || !mPolicy.isScreenOnFully()) {
+        if (mDefaultDisplay == null || !mPolicy.isScreenOnFully()) {
             // No need to freeze the screen before the system is ready or if
             // the screen is off.
             return;
@@ -9331,15 +9471,11 @@
                 mAnimator.mScreenRotationAnimation = null;
             }
 
+            // TODO(multidisplay): rotation on main screen only.
+            DisplayInfo displayInfo = getDefaultDisplayContent().getDisplayInfo();
             mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext,
-                    mFxSession, inTransaction, mCurDisplayWidth, mCurDisplayHeight,
-                    mDisplay.getRotation());
-
-            if (!mAnimator.mScreenRotationAnimation.hasScreenshot()) {
-                Surface.freezeDisplay(0);
-            }
-        } else {
-            Surface.freezeDisplay(0);
+                    mDefaultDisplay, mFxSession, inTransaction, displayInfo.logicalWidth,
+                    displayInfo.logicalHeight, mDefaultDisplay.getRotation());
         }
     }
 
@@ -9363,13 +9499,16 @@
         }
 
         boolean updateRotation = false;
-        
+
         if (CUSTOM_SCREEN_ROTATION && mAnimator.mScreenRotationAnimation != null
                 && mAnimator.mScreenRotationAnimation.hasScreenshot()) {
             if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation");
+            // TODO(multidisplay): rotation on main screen only.
+            DisplayInfo displayInfo = getDefaultDisplayContent().getDisplayInfo();
             if (mAnimator.mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
-                    mTransitionAnimationScale, mCurDisplayWidth, mCurDisplayHeight)) {
-                scheduleAnimationLocked();
+                    mTransitionAnimationScale, displayInfo.logicalWidth,
+                        displayInfo.logicalHeight)) {
+                updateLayoutToAnimationLocked();
             } else {
                 mAnimator.mScreenRotationAnimation.kill();
                 mAnimator.mScreenRotationAnimation = null;
@@ -9382,7 +9521,6 @@
             }
             updateRotation = true;
         }
-        Surface.unfreezeDisplay(0);
 
         mInputMonitor.thawInputDispatchingLw();
 
@@ -9448,7 +9586,8 @@
             if (line != null) {
                 String[] toks = line.split("%");
                 if (toks != null && toks.length > 0) {
-                    mWatermark = new Watermark(mRealDisplayMetrics, mFxSession, toks);
+                    mWatermark =
+                            new Watermark(mDefaultDisplay, mRealDisplayMetrics, mFxSession, toks);
                 }
             }
         } catch (FileNotFoundException e) {
@@ -9478,11 +9617,13 @@
         }
     }
 
+    // TOOD(multidisplay): StatusBar on multiple screens?
     void updateStatusBarVisibilityLocked(int visibility) {
         mInputManager.setSystemUiVisibility(visibility);
-        final int N = mWindows.size();
+        final WindowList windows = getDefaultWindowList();
+        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 +9690,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 = getDefaultDisplayContent();
             if (mInputMethodWindow != null) {
                 mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
             }
@@ -9699,10 +9842,12 @@
 
     void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
             ArrayList<WindowState> windows) {
-        for (int i=mWindows.size()-1; i>=0; i--) {
-            WindowState w = mWindows.get(i);
+        int j = 0;
+        final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
+        while (iterator.hasNext()) {
+            final WindowState w = iterator.next();
             if (windows == null || windows.contains(w)) {
-                pw.print("  Window #"); pw.print(i); pw.print(' ');
+                pw.print("  Window #"); pw.print(j++); pw.print(' ');
                         pw.print(w); pw.println(":");
                 w.dump(pw, "    ", dumpAll || windows != null);
             }
@@ -9810,27 +9955,11 @@
             }
         }
         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);
+        if (mDefaultDisplay != null) {
+            DisplayContentsIterator dCIterator = new DisplayContentsIterator();
+            while (dCIterator.hasNext()) {
+                dCIterator.next().dump(pw);
+            }
         } else {
             pw.println("  NO DISPLAY");
         }
@@ -9847,7 +9976,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));
@@ -9916,15 +10046,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) {
@@ -9943,8 +10073,9 @@
         ArrayList<WindowState> windows = new ArrayList<WindowState>();
         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 +10090,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 +10265,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 +10278,108 @@
         }
     }
 
-    void bulkSetParameters(final int bulkUpdateParams, int pendingLayoutChanges) {
-        mH.sendMessage(mH.obtainMessage(H.BULK_UPDATE_PARAMETERS, bulkUpdateParams,
-                pendingLayoutChanges));
+    public DisplayContent getDisplayContent(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");
+        }
+    }
+
+    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 getDefaultDisplayContent() {
+        final int displayId = mDefaultDisplay == null
+                ? Display.DEFAULT_DISPLAY : mDefaultDisplay.getDisplayId();
+        return getDisplayContent(displayId);
+    }
+
+    public WindowList getDefaultWindowList() {
+        return getDefaultDisplayContent().getWindowList();
+    }
+
+    public DisplayInfo getDefaultDisplayInfo() {
+        return getDefaultDisplayContent().getDisplayInfo();
+    }
+
 }
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index a00e8a5..a52e1d7 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) {
@@ -544,6 +562,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,13 +577,13 @@
             // 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);
         }
     }
 
@@ -884,6 +903,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 +931,7 @@
             mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_ENTER, true);
         }
         if (requestAnim) {
-            mService.scheduleAnimationLocked();
+            mService.updateLayoutToAnimationLocked();
         }
         return true;
     }
@@ -950,7 +974,7 @@
             }
         }
         if (requestAnim) {
-            mService.scheduleAnimationLocked();
+            mService.updateLayoutToAnimationLocked();
         }
         return true;
     }
@@ -960,6 +984,17 @@
         return mClient.asBinder().isBinderAlive();
     }
 
+    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 +1023,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,6 +1100,9 @@
             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);
         }
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index 03e52fe..1bda22a 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -3,9 +3,8 @@
 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 +16,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 +31,9 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 
+class WinAnimatorList extends ArrayList<WindowStateAnimator> {
+}
+
 /**
  * Keep track of animations and surface operations for a single WindowState.
  **/
@@ -48,13 +51,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 +148,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 +196,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 +229,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 +256,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 +274,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 +322,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
@@ -460,22 +477,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 +543,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 +590,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 +608,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 +652,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 +701,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 +811,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);
@@ -870,6 +879,9 @@
             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());
@@ -913,6 +925,9 @@
                 if (appTransformation != null) {
                     mShownAlpha *= appTransformation.getAlpha();
                 }
+                if (mAnimator.mUniverseBackground != null) {
+                    mShownAlpha *= mAnimator.mUniverseBackground.mUniverseTransform.getAlpha();
+                }
                 if (screenAnimation) {
                     mShownAlpha *=
                         mService.mAnimator.mScreenRotationAnimation.getEnterTransformation().getAlpha();
@@ -921,7 +936,7 @@
                 //Slog.i(TAG, "Not applying alpha transform");
             }
 
-            if (WindowManagerService.localLOGV && (mShownAlpha == 1.0 || mShownAlpha == 0.0)) Slog.v(
+            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") +
@@ -930,7 +945,7 @@
                 " screen=" + (screenAnimation ? mService.mAnimator.mScreenRotationAnimation.getEnterTransformation().getAlpha()
                         : "null"));
             return;
-        } else if (mWin.mIsWallpaper &&
+        } else if (mIsWallpaper &&
                     (mAnimator.mPendingActions & WindowAnimator.WALLPAPER_ACTION_PENDING) != 0) {
             return;
         }
@@ -938,16 +953,64 @@
         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);
+        if (mAnimator.mUniverseBackground != null &&
+                mWin.mAttrs.type != WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND
+                && mWin.mBaseLayer < mAnimator.mAboveUniverseLayer) {
+            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);
+            tmpMatrix.postConcat(mAnimator.mUniverseBackground.mUniverseTransform.getMatrix());
+            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 * 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) {
@@ -960,31 +1023,21 @@
             w.mSystemDecorRect.set(0, 0, w.mRequestedWidth, w.mRequestedHeight);
         } 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)) {
@@ -1056,8 +1109,9 @@
                 mAnimator.mPendingLayoutChanges |=
                         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.startDimming(this, w.mExiting ? 0 : w.mAttrs.dimAmount,
+                            displayInfo.appWidth, displayInfo.appHeight);
                 }
             } catch (RuntimeException e) {
                 // If something goes wrong with the surface (such
@@ -1092,7 +1146,7 @@
 
         setSurfaceBoundaries(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 +1205,7 @@
                                 + " during relayout");
                         if (showSurfaceRobustlyLocked()) {
                             mLastHidden = false;
-                            if (w.mIsWallpaper) {
+                            if (mIsWallpaper) {
                                 mService.dispatchWallpaperVisibility(w, true);
                             }
                         } else {
@@ -1169,8 +1223,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 +1232,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 +1293,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 +1317,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 +1333,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 +1345,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) {
@@ -1483,6 +1542,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 9ed4951..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_input_InputManagerService.cpp b/services/jni/com_android_server_input_InputManagerService.cpp
index 0e1ce51..495d4ab 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,
 };
 
@@ -578,14 +578,9 @@
 
     JNIEnv* env = jniEnv();
 
-    switch (switchCode) {
-    case SW_LID:
-        // When switch value is set indicates lid is closed.
-        env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyLidSwitchChanged,
-                when, switchValue == 0 /*lidOpen*/);
-        checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged");
-        break;
-    }
+    env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifySwitch,
+            when, switchCode, switchValue);
+    checkAndClearExceptionFromCallback(env, "notifySwitch");
 }
 
 void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
@@ -899,11 +894,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) {
@@ -1410,8 +1405,8 @@
     GET_METHOD_ID(gServiceClassInfo.notifyInputDevicesChanged, clazz,
             "notifyInputDevicesChanged", "([Landroid/view/InputDevice;)V");
 
-    GET_METHOD_ID(gServiceClassInfo.notifyLidSwitchChanged, clazz,
-            "notifyLidSwitchChanged", "(JZ)V");
+    GET_METHOD_ID(gServiceClassInfo.notifySwitch, clazz,
+            "notifySwitch", "(JII)V");
 
     GET_METHOD_ID(gServiceClassInfo.notifyInputChannelBroken, clazz,
             "notifyInputChannelBroken", "(Lcom/android/server/input/InputWindowHandle;)V");
diff --git a/services/jni/com_android_server_PowerManagerService.cpp b/services/jni/com_android_server_power_PowerManagerService.cpp
similarity index 65%
rename from services/jni/com_android_server_PowerManagerService.cpp
rename to services/jni/com_android_server_power_PowerManagerService.cpp
index 0904bdd..3f3970b 100644
--- a/services/jni/com_android_server_PowerManagerService.cpp
+++ b/services/jni/com_android_server_power_PowerManagerService.cpp
@@ -21,6 +21,8 @@
 #include "JNIHelp.h"
 #include "jni.h"
 
+#include <ScopedUtfChars.h>
+
 #include <limits.h>
 
 #include <android_runtime/AndroidRuntime.h>
@@ -28,6 +30,7 @@
 #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>
@@ -35,15 +38,16 @@
 
 #include <private/gui/ComposerService.h>
 
-#include "com_android_server_PowerManagerService.h"
+#include "com_android_server_power_PowerManagerService.h"
 
 namespace android {
 
 // ----------------------------------------------------------------------------
 
 static struct {
-    jmethodID goToSleep;
-    jmethodID userActivity;
+    jmethodID wakeUpFromNative;
+    jmethodID goToSleepFromNative;
+    jmethodID userActivityFromNative;
 } gPowerManagerServiceClassInfo;
 
 // ----------------------------------------------------------------------------
@@ -55,7 +59,7 @@
 static bool gScreenOn;
 static bool gScreenBright;
 
-static nsecs_t gLastEventTime[POWER_MANAGER_LAST_EVENT + 1];
+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
@@ -92,7 +96,7 @@
         // 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) {
+        if (eventType >= 0 && eventType <= USER_ACTIVITY_EVENT_LAST) {
             nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
             if (eventTime > now) {
                 eventTime = now;
@@ -106,9 +110,21 @@
 
         JNIEnv* env = AndroidRuntime::getJNIEnv();
 
-        env->CallVoidMethod(gPowerManagerServiceObj, gPowerManagerServiceClassInfo.userActivity,
-                nanoseconds_to_milliseconds(eventTime), false, eventType, false);
-        checkAndClearExceptionFromCallback(env, "userActivity");
+        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");
     }
 }
 
@@ -116,9 +132,10 @@
     if (gPowerManagerServiceObj) {
         JNIEnv* env = AndroidRuntime::getJNIEnv();
 
-        env->CallVoidMethod(gPowerManagerServiceObj, gPowerManagerServiceClassInfo.goToSleep,
-                nanoseconds_to_milliseconds(eventTime));
-        checkAndClearExceptionFromCallback(env, "goToSleep");
+        env->CallVoidMethod(gPowerManagerServiceObj,
+                gPowerManagerServiceClassInfo.goToSleepFromNative,
+                nanoseconds_to_milliseconds(eventTime), 0);
+        checkAndClearExceptionFromCallback(env, "goToSleepFromNative");
     }
 }
 
@@ -137,66 +154,62 @@
 }
 
 static void nativeSetPowerState(JNIEnv* env,
-        jobject serviceObj, jboolean screenOn, jboolean screenBright) {
+        jclass clazz, jboolean screenOn, jboolean screenBright) {
     AutoMutex _l(gPowerManagerLock);
     gScreenOn = screenOn;
     gScreenBright = screenBright;
 }
 
-static void nativeStartSurfaceFlingerAnimation(JNIEnv* env,
-        jobject obj, jint mode) {
+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());
-    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();
+        {
+            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);
         }
-        autosuspend_enable();
-    }
 
-    return 0;
+        {
+            ALOGD_IF_SLOW(50, "Excessive delay in autosuspend_enable() while turning screen off");
+            autosuspend_enable();
+        }
+    }
 }
 
-static void nativeShutdown(JNIEnv *env, jobject clazz) {
+static void nativeShutdown(JNIEnv *env, jclass clazz) {
     android_reboot(ANDROID_RB_POWEROFF, 0, 0);
 }
 
-static void nativeReboot(JNIEnv *env, jobject clazz, jstring reason) {
+static void nativeReboot(JNIEnv *env, jclass clazz, jstring reason) {
     if (reason == NULL) {
         android_reboot(ANDROID_RB_RESTART, 0, 0);
     } else {
@@ -216,13 +229,11 @@
             (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",
+    { "nativeAcquireSuspendBlocker", "(Ljava/lang/String;)V",
+            (void*) nativeAcquireSuspendBlocker },
+    { "nativeReleaseSuspendBlocker", "(Ljava/lang/String;)V",
+            (void*) nativeReleaseSuspendBlocker },
+    { "nativeSetScreenState", "(Z)V",
             (void*) nativeSetScreenState },
     { "nativeShutdown", "()V",
             (void*) nativeShutdown },
@@ -243,23 +254,26 @@
         LOG_FATAL_IF(! var, "Unable to find field " fieldName);
 
 int register_android_server_PowerManagerService(JNIEnv* env) {
-    int res = jniRegisterNativeMethods(env, "com/android/server/PowerManagerService",
+    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/PowerManagerService");
+    FIND_CLASS(clazz, "com/android/server/power/PowerManagerService");
 
-    GET_METHOD_ID(gPowerManagerServiceClassInfo.goToSleep, clazz,
-            "goToSleep", "(J)V");
+    GET_METHOD_ID(gPowerManagerServiceClassInfo.wakeUpFromNative, clazz,
+            "wakeUpFromNative", "(J)V");
 
-    GET_METHOD_ID(gPowerManagerServiceClassInfo.userActivity, clazz,
-            "userActivity", "(JZIZ)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 < POWER_MANAGER_LAST_EVENT; i++) {
+    for (int i = 0; i <= USER_ACTIVITY_EVENT_LAST; i++) {
         gLastEventTime[i] = LLONG_MIN;
     }
     gScreenOn = true;
diff --git a/services/jni/com_android_server_PowerManagerService.h b/services/jni/com_android_server_power_PowerManagerService.h
similarity index 93%
rename from services/jni/com_android_server_PowerManagerService.h
rename to services/jni/com_android_server_power_PowerManagerService.h
index cc3b5ef5..0808b80 100644
--- a/services/jni/com_android_server_PowerManagerService.h
+++ b/services/jni/com_android_server_power_PowerManagerService.h
@@ -27,6 +27,7 @@
 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
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..3373fd4 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -71,7 +71,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;
@@ -138,10 +138,10 @@
     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 UID_A_GUEST = UserHandle.getUid(USER_ID_GUEST, APP_ID_A);
+    private static final int UID_B_GUEST = UserHandle.getUid(USER_ID_GUEST, APP_ID_B);
 
     private static final int PID_1 = 400;
     private static final int PID_2 = 401;
@@ -176,13 +176,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;
-                    }
                 };
             }
 
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/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..dead049
--- /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..6047cda 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,8 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.UserHandle;
+import android.view.CompatibilityInfoHolder;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -284,12 +287,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 +306,18 @@
     }
 
     @Override
+    public void sendBroadcastAsUser(Intent intent, UserHandle user) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
+            BroadcastReceiver resultReceiver, Handler scheduler,
+            int initialCode, String initialData, Bundle initialExtras) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public void sendStickyBroadcast(Intent intent) {
         throw new UnsupportedOperationException();
     }
@@ -351,6 +360,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 +492,18 @@
     }
 
     @Override
+    public Context createConfigurationContext(Configuration overrideConfiguration) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public boolean isRestricted() {
         throw new UnsupportedOperationException();        
     }
+
+    /** @hide */
+    @Override
+    public CompatibilityInfoHolder getCompatibilityInfo() {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 86689f3..562f286 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;
@@ -479,7 +481,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 +516,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..9599b19 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,79 @@
                 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), 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 +217,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/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..c783ad6 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -33,6 +33,24 @@
         <meta-data android:name="android.graphics.renderThread" android:value="true" />
 
         <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 +60,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 +177,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 +313,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/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/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..f26edc6
--- /dev/null
+++ b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tests.memoryusage;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.ProcessErrorStateInfo;
+import android.app.ActivityManager.RunningAppProcessInfo;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.os.Debug.MemoryInfo;
+import android.test.InstrumentationTestCase;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This test is intended to measure the amount of memory applications use when
+ * they start. Names of the applications are passed in command line, and the
+ * test starts each application, waits until its memory usage is stabilized and
+ * reports the total PSS in kilobytes of each processes.
+ * The instrumentation expects the following key to be passed on the command line:
+ * apps - A list of applications to start and their corresponding result keys
+ * in the following format:
+ * -e apps <app name>^<result key>|<app name>^<result key>
+ */
+public class MemoryUsageTest extends InstrumentationTestCase {
+
+    private static final int SLEEP_TIME = 1000;
+    private static final int THRESHOLD = 1024;
+    private static final int MAX_ITERATIONS = 10;
+    private static final int MIN_ITERATIONS = 4;
+
+    private static final String TAG = "MemoryUsageInstrumentation";
+    private static final String KEY_APPS = "apps";
+
+    private Map<String, Intent> nameToIntent;
+    private Map<String, String> nameToProcess;
+    private Map<String, String> nameToResultKey;
+
+    public void testMemory() {
+        MemoryUsageInstrumentation instrumentation =
+                    (MemoryUsageInstrumentation) getInstrumentation();
+        Bundle args = instrumentation.getBundle();
+
+        createMappings();
+        parseArgs(args);
+
+        Bundle results = new Bundle();
+        for (String app : nameToResultKey.keySet()) {
+            String processName;
+            try {
+                processName = startApp(app);
+                measureMemory(app, processName, results);
+            } catch (NameNotFoundException e) {
+                Log.i(TAG, "Application " + app + " not found");
+            }
+
+        }
+        instrumentation.sendStatus(0, results);
+    }
+
+    private void parseArgs(Bundle args) {
+        nameToResultKey = new HashMap<String, String>();
+        String appList = args.getString(KEY_APPS);
+
+        if (appList == null)
+            return;
+
+        String appNames[] = appList.split("\\|");
+        for (String pair : appNames) {
+            String[] parts = pair.split("\\^");
+            if (parts.length != 2) {
+                Log.e(TAG, "The apps key is incorectly formatted");
+                fail();
+            }
+
+            nameToResultKey.put(parts[0], parts[1]);
+        }
+    }
+
+    private void createMappings() {
+        nameToIntent = new HashMap<String, Intent>();
+        nameToProcess = new HashMap<String, String>();
+
+        PackageManager pm = getInstrumentation().getContext()
+                .getPackageManager();
+        Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
+        intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
+        List<ResolveInfo> ris = pm.queryIntentActivities(intentToResolve, 0);
+        if (ris == null || ris.isEmpty()) {
+            Log.i(TAG, "Could not find any apps");
+        } else {
+            for (ResolveInfo ri : ris) {
+                Log.i(TAG, "Name: " + ri.loadLabel(pm).toString()
+                        + " package: " + ri.activityInfo.packageName
+                        + " name: " + ri.activityInfo.name);
+                Intent startIntent = new Intent(intentToResolve);
+                startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                        | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+                startIntent.setClassName(ri.activityInfo.packageName,
+                        ri.activityInfo.name);
+                nameToIntent.put(ri.loadLabel(pm).toString(), startIntent);
+                nameToProcess.put(ri.loadLabel(pm).toString(),
+                        ri.activityInfo.processName);
+            }
+        }
+    }
+
+    private String startApp(String appName) throws NameNotFoundException {
+        Log.i(TAG, "Starting " + appName);
+
+        if (!nameToProcess.containsKey(appName))
+            throw new NameNotFoundException("Could not find: " + appName);
+
+        String process = nameToProcess.get(appName);
+        Intent startIntent = nameToIntent.get(appName);
+        getInstrumentation().getContext().startActivity(startIntent);
+        return process;
+    }
+
+    private void measureMemory(String appName, String processName,
+            Bundle results) {
+        List<Integer> pssData = new ArrayList<Integer>();
+        int pss = 0;
+        int iteration = 0;
+        while (iteration < MAX_ITERATIONS) {
+            sleep();
+            pss = getPss(processName);
+            Log.i(TAG, appName + "=" + pss);
+            if (pss < 0) {
+                reportError(appName, processName, results);
+                return;
+            }
+            pssData.add(pss);
+            if (iteration >= MIN_ITERATIONS && stabilized(pssData)) {
+                results.putInt(nameToResultKey.get(appName), pss);
+                return;
+            }
+            iteration++;
+        }
+
+        Log.w(TAG, appName + " memory usage did not stabilize");
+        results.putInt(appName, average(pssData));
+    }
+
+    private int average(List<Integer> pssData) {
+        int sum = 0;
+        for (int sample : pssData) {
+            sum += sample;
+        }
+
+        return sum / pssData.size();
+    }
+
+    private boolean stabilized(List<Integer> pssData) {
+        if (pssData.size() < 3)
+            return false;
+        int diff1 = Math.abs(pssData.get(pssData.size() - 1) - pssData.get(pssData.size() - 2));
+        int diff2 = Math.abs(pssData.get(pssData.size() - 2) - pssData.get(pssData.size() - 3));
+
+        Log.i(TAG, "diff1=" + diff1 + " diff2=" + diff2);
+
+        return (diff1 + diff2) < THRESHOLD;
+    }
+
+    private void sleep() {
+        try {
+            Thread.sleep(SLEEP_TIME);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+    }
+
+    private void reportError(String appName, String processName, Bundle results) {
+        ActivityManager am = (ActivityManager) getInstrumentation()
+                .getContext().getSystemService(Context.ACTIVITY_SERVICE);
+        List<ProcessErrorStateInfo> crashes = am.getProcessesInErrorState();
+        if (crashes != null) {
+            for (ProcessErrorStateInfo crash : crashes) {
+                if (!crash.processName.equals(processName))
+                    continue;
+
+                Log.w(TAG, appName + " crashed: " + crash.shortMsg);
+                results.putString(nameToResultKey.get(appName), crash.shortMsg);
+                return;
+            }
+        }
+
+        results.putString(nameToResultKey.get(appName),
+                "Crashed for unknown reason");
+        Log.w(TAG, appName
+                + " not found in process list, most likely it is crashed");
+    }
+
+    private int getPss(String processName) {
+        ActivityManager am = (ActivityManager) getInstrumentation()
+                .getContext().getSystemService(Context.ACTIVITY_SERVICE);
+        List<RunningAppProcessInfo> apps = am.getRunningAppProcesses();
+
+        for (RunningAppProcessInfo proc : apps) {
+            if (!proc.processName.equals(processName)) {
+                continue;
+            }
+
+            int[] pids = {
+                proc.pid };
+
+            MemoryInfo meminfo = am.getProcessMemoryInfo(pids)[0];
+            return meminfo.getTotalPss();
+
+        }
+        return -1;
+    }
+}
diff --git a/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/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..697bbb1
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Blur25.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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 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/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..07626a3 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,6 +97,131 @@
     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, false);
+            break;
+        case 8:
+            mTest = new Fisheye(false, true);
+            break;
+        case 9:
+            mTest = new Fisheye(true, false);
+            break;
+        case 10:
+            mTest = new Fisheye(true, true);
+            break;
+        case 11:
+            mTest = new Vignette(false, false);
+            break;
+        case 12:
+            mTest = new Vignette(false, true);
+            break;
+        case 13:
+            mTest = new Vignette(true, false);
+            break;
+        case 14:
+            mTest = new Vignette(true, true);
+            break;
+        case 15:
+            mTest = new GroupTest(true);
+            break;
+        case 16:
+            mTest = new GroupTest(false);
+            break;
+        case 17:
+            mTest = new Intrinsics(0);
+            break;
+        }
+
+        mTest.createBaseTest(this, mBitmapIn);
+        setupBars();
+
+        mTest.runTest();
+        mTest.updateBitmap(mBitmapOut);
+        mDisplayView.invalidate();
+        mBenchmarkResult.setText("Result: not run");
+    }
+
+    void setupTests() {
+        mTestNames = new String[18];
+        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] = "Fisheye Approximate Full";
+        mTestNames[10] = "Fisheye Approximate Relaxed";
+        mTestNames[11] = "Vignette Full";
+        mTestNames[12] = "Vignette Relaxed";
+        mTestNames[13] = "Vignette Approximate Full";
+        mTestNames[14] = "Vignette Approximate Relaxed";
+        mTestNames[15] = "Group Test (emulated)";
+        mTestNames[16] = "Group Test (native)";
+        mTestNames[17] = "Intrinsics Convolve 3x3";
+        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);
@@ -165,94 +231,38 @@
         mBitmapOut = loadBitmap(R.drawable.city);
 
         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();
@@ -278,26 +288,29 @@
 
     // 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");
-        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();
+        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);
 
-        mScript.invoke_filter();
-        mOutPixelsAllocation.copyTo(mBitmapOut);
+        Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t);
+        mTest.exitBenchmark();
+        mDoingBenchmark = false;
+
         return t;
     }
 }
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Intrinsics.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Intrinsics.java
new file mode 100644
index 0000000..dab8111
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Intrinsics.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.Script;
+import android.renderscript.ScriptIntrinsicConvolve3x3;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Intrinsics extends TestBase {
+    private ScriptIntrinsicConvolve3x3 mScript;
+
+    Intrinsics(int id) {
+    }
+
+    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;
+        float v[] = new float[9];
+        v[0] = 0.f;     v[1] = -s;      v[2] = 0.f;
+        v[3] = -s;      v[4] = s*4+1;   v[5] = -s;
+        v[6] = 0.f;     v[7] = -s;      v[8] = 0.f;
+        mScript.setColorMatrix(v);
+    }
+
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = ScriptIntrinsicConvolve3x3.create(mRS, Element.RGBA_8888(mRS));
+    }
+
+    public void runTest() {
+        mScript.setInput(mInPixelsAllocation);
+        mScript.forEach(mOutPixelsAllocation);
+    }
+
+}
+
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..b6b4a0f
--- /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);
+    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/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/cmds/sensorservice/main_sensorservice.cpp b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_full.rs
similarity index 69%
copy from cmds/sensorservice/main_sensorservice.cpp
copy to tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_full.rs
index 8610627..1ea37db 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_full.rs
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,12 +14,8 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
 
-using namespace android;
+#include "fisheye_approx.rsh"
 
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
-}
diff --git a/cmds/sensorservice/main_sensorservice.cpp b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_relaxed.rs
similarity index 69%
copy from cmds/sensorservice/main_sensorservice.cpp
copy to tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_relaxed.rs
index 8610627..3e76368 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_relaxed.rs
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,12 +14,9 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+#pragma rs_fp_relaxed
 
-using namespace android;
+#include "fisheye_approx.rsh"
 
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
-}
diff --git a/cmds/sensorservice/main_sensorservice.cpp b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_full.rs
similarity index 69%
copy from cmds/sensorservice/main_sensorservice.cpp
copy to tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_full.rs
index 8610627..20f27e2 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_full.rs
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,12 +14,8 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
 
-using namespace android;
+#include "fisheye.rsh"
 
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
-}
diff --git a/cmds/sensorservice/main_sensorservice.cpp b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_relaxed.rs
similarity index 69%
copy from cmds/sensorservice/main_sensorservice.cpp
copy to tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_relaxed.rs
index 8610627..dc3ffcb 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_relaxed.rs
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,12 +14,9 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+#pragma rs_fp_relaxed
 
-using namespace android;
+#include "fisheye.rsh"
 
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
-}
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..7d9d3ac
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/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.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);
+    uint32_t x2 = max((int32_t)x-1, (int32_t)0);
+    uint32_t y1 = min((int32_t)y+1, (int32_t)gHeight);
+    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;
+
+    *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/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/cmds/sensorservice/main_sensorservice.cpp b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_full.rs
similarity index 69%
copy from cmds/sensorservice/main_sensorservice.cpp
copy to tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_full.rs
index 8610627..da6a291 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_full.rs
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,12 +14,8 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
 
-using namespace android;
+#include "levels.rsh"
 
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
-}
diff --git a/cmds/sensorservice/main_sensorservice.cpp b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_relaxed.rs
similarity index 69%
copy from cmds/sensorservice/main_sensorservice.cpp
copy to tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_relaxed.rs
index 8610627..b115445 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_relaxed.rs
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,12 +14,9 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+#pragma rs_fp_relaxed
 
-using namespace android;
+#include "levels.rsh"
 
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
-}
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/cmds/sensorservice/main_sensorservice.cpp b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx_full.rs
similarity index 69%
copy from cmds/sensorservice/main_sensorservice.cpp
copy to tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx_full.rs
index 8610627..c83c6e1 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx_full.rs
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,12 +14,8 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
 
-using namespace android;
+#include "vignette_approx.rsh"
 
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
-}
diff --git a/cmds/sensorservice/main_sensorservice.cpp b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx_relaxed.rs
similarity index 69%
copy from cmds/sensorservice/main_sensorservice.cpp
copy to tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx_relaxed.rs
index 8610627..9120612 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx_relaxed.rs
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,12 +14,9 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+#pragma rs_fp_relaxed
 
-using namespace android;
+#include "vignette_approx.rsh"
 
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
-}
diff --git a/cmds/sensorservice/main_sensorservice.cpp b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_full.rs
similarity index 69%
copy from cmds/sensorservice/main_sensorservice.cpp
copy to tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_full.rs
index 8610627..64942d9 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_full.rs
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,12 +14,8 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
 
-using namespace android;
+#include "vignette.rsh"
 
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
-}
diff --git a/cmds/sensorservice/main_sensorservice.cpp b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_relaxed.rs
similarity index 69%
copy from cmds/sensorservice/main_sensorservice.cpp
copy to tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_relaxed.rs
index 8610627..8e47ea9 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_relaxed.rs
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,12 +14,9 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
+#pragma rs_fp_relaxed
 
-using namespace android;
+#include "vignette.rsh"
 
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
-}
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/ImageProcessing2/res/drawable-nodpi/city.png b/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/city.png
new file mode 100644
index 0000000..856eeff
--- /dev/null
+++ b/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/cmds/sensorservice/main_sensorservice.cpp b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_full.rs
similarity index 69%
copy from cmds/sensorservice/main_sensorservice.cpp
copy to tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_full.rs
index 8610627..e42df13 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_full.rs
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,12 +14,8 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
 
-using namespace android;
+#include "fisheye.rsh"
 
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
-}
diff --git a/cmds/sensorservice/main_sensorservice.cpp b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.rs
similarity index 69%
copy from cmds/sensorservice/main_sensorservice.cpp
copy to tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.rs
index 8610627..990310b 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.rs
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,12 +14,9 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+#pragma rs_fp_relaxed
 
-using namespace android;
+#include "fisheye.rsh"
 
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
-}
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/cmds/sensorservice/main_sensorservice.cpp b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_full.rs
similarity index 69%
copy from cmds/sensorservice/main_sensorservice.cpp
copy to tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_full.rs
index 8610627..a4aa388 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_full.rs
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,12 +14,8 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
 
-using namespace android;
+#include "levels.rsh"
 
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
-}
diff --git a/cmds/sensorservice/main_sensorservice.cpp b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs
similarity index 69%
copy from cmds/sensorservice/main_sensorservice.cpp
copy to tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs
index 8610627..ffdcfe3 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,12 +14,9 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+#pragma rs_fp_relaxed
 
-using namespace android;
+#include "levels.rsh"
 
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
-}
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/cmds/sensorservice/main_sensorservice.cpp b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_full.rs
similarity index 69%
copy from cmds/sensorservice/main_sensorservice.cpp
copy to tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_full.rs
index 8610627..5fc2dda 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_full.rs
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,12 +14,8 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
 
-using namespace android;
+#include "vignette.rsh"
 
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
-}
diff --git a/cmds/sensorservice/main_sensorservice.cpp b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.rs
similarity index 69%
copy from cmds/sensorservice/main_sensorservice.cpp
copy to tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.rs
index 8610627..430b685 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.rs
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 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.
@@ -14,12 +14,9 @@
  * limitations under the License.
  */
 
-#include <binder/BinderService.h>
-#include <SensorService.h>
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+#pragma rs_fp_relaxed
 
-using namespace android;
+#include "vignette.rsh"
 
-int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
-    return 0;
-}
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/LivePreview/res/drawable-nodpi/city.png b/tests/RenderScriptTests/LivePreview/res/drawable-nodpi/city.png
new file mode 100644
index 0000000..856eeff
--- /dev/null
+++ b/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..a641ce5 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,8 @@
         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_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_math_agree.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_agree.java
new file mode 100644
index 0000000..ca49344
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_agree.java
@@ -0,0 +1,540 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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, mRes,
+                R.raw.math_agree);
+        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_min.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_min.java
new file mode 100644
index 0000000..8287f02
--- /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, mRes, R.raw.min);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_min_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
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..2164766
--- /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, mRes, R.raw.unsigned);
+        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/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/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/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/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..76033d4 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,12 @@
 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.Surface;
 import android.view.View;
 import android.view.ViewGroup;
@@ -440,7 +442,7 @@
         }
 
         if (POWER_SERVICE.equals(service)) {
-            return new PowerManager(new BridgePowerManager(), new Handler());
+            return new PowerManager(this, new BridgePowerManager(), new Handler());
         }
 
         throw new UnsupportedOperationException("Unsupported Service: " + service);
@@ -917,6 +919,12 @@
     }
 
     @Override
+    public Context createConfigurationContext(Configuration overrideConfiguration) {
+        // pass
+        return null;
+    }
+
+    @Override
     public String[] databaseList() {
         // pass
         return null;
@@ -1187,6 +1195,18 @@
     }
 
     @Override
+    public void sendBroadcastAsUser(Intent intent, UserHandle user) {
+        // pass
+    }
+
+    @Override
+    public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
+            BroadcastReceiver resultReceiver, Handler scheduler,
+            int initialCode, String initialData, Bundle initialExtras) {
+        // pass
+    }
+
+    @Override
     public void sendStickyBroadcast(Intent arg0) {
         // pass
 
@@ -1261,6 +1281,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 +1331,10 @@
         Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "OBB not supported", null);
         return null;
     }
+
+    @Override
+    public CompatibilityInfoHolder getCompatibilityInfo() {
+        // 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..5516339 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
@@ -23,23 +23,21 @@
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.Point;
+import android.graphics.Rect;
 import android.os.IBinder;
 import android.os.IRemoteCallback;
 import android.os.RemoteException;
 import android.util.DisplayMetrics;
 import android.view.Display;
+import android.view.DisplayInfo;
 import android.view.Display_Delegate;
 import android.view.Gravity;
 import android.view.IApplicationToken;
+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 java.util.List;
 
@@ -72,23 +70,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 +92,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
@@ -240,7 +225,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 +266,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;
     }
@@ -343,9 +329,13 @@
     }
 
     @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
@@ -455,4 +445,27 @@
     public void lockNow() {
         // TODO Auto-generated method stub
     }
+
+    @Override
+    public IBinder getFocusedWindowToken() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public boolean getWindowFrame(IBinder token, Rect outBounds) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @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
+    }
 }
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..691eca7 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,6 +184,12 @@
     }
 
     @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;
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..3e20756 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -47,19 +47,37 @@
     public int frequency;
 
     /**
+     * Time Synchronization Function (tsf) timestamp in microseconds when
+     * this result was last seen.
+     */
+     public long timestamp;
+
+    /**
      * We'd like to obtain the following attributes,
      * but they are not reported via the socket
      * interface, even though they are known
      * internally by wpa_supplicant.
      * {@hide}
      */
-    public ScanResult(String SSID, String BSSID, String caps, int level, int frequency) {
+    public ScanResult(String SSID, String BSSID, String caps, int level, int frequency, long tsf) {
         this.SSID = SSID;
         this.BSSID = BSSID;
         this.capabilities = caps;
         this.level = level;
         this.frequency = frequency;
-        //networkConfig = null;
+        this.timestamp = tsf;
+    }
+
+    /** copy constructor {@hide} */
+    public ScanResult(ScanResult source) {
+        if (source != null) {
+            SSID = source.SSID;
+            BSSID = source.BSSID;
+            capabilities = source.capabilities;
+            level = source.level;
+            frequency = source.frequency;
+            timestamp = source.timestamp;
+        }
     }
 
     @Override
@@ -76,7 +94,9 @@
             append(", level: ").
             append(level).
             append(", frequency: ").
-            append(frequency);
+            append(frequency).
+            append(", timestamp: ").
+            append(timestamp);
 
         return sb.toString();
     }
@@ -93,6 +113,7 @@
         dest.writeString(capabilities);
         dest.writeInt(level);
         dest.writeInt(frequency);
+        dest.writeLong(timestamp);
     }
 
     /** Implement the Parcelable interface {@hide} */
@@ -104,7 +125,8 @@
                     in.readString(),
                     in.readString(),
                     in.readInt(),
-                    in.readInt()
+                    in.readInt(),
+                    in.readLong()
                 );
             }
 
diff --git a/wifi/java/android/net/wifi/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/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index e520185..b9feb34 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -197,8 +197,22 @@
         return null;
     }
 
+    /**
+     * Format of results:
+     * =================
+     * bssid=68:7f:74:d7:1b:6e
+     * freq=2412
+     * level=-43
+     * tsf=1344621975160944
+     * age=2623
+     * flags=[WPA2-PSK-CCMP][WPS][ESS]
+     * ssid=zubyb
+     *
+     * RANGE=ALL gets all scan results
+     * MASK=<N> see wpa_supplicant/src/common/wpa_ctrl.h for details
+     */
     public String scanResults() {
-        return doStringCommand("SCAN_RESULTS");
+        return doStringCommand("BSS RANGE=ALL MASK=0x1986");
     }
 
     public boolean startDriver() {
@@ -368,6 +382,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");
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 15eb9b9..b52250d 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;
@@ -94,13 +91,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 +104,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;
@@ -123,7 +114,7 @@
     private final String mPrimaryDeviceType;
 
     /* Scan results handling */
-    private List<ScanResult> mScanResults;
+    private List<ScanResult> mScanResults = new ArrayList<ScanResult>();
     private static final Pattern scanResultPattern = Pattern.compile("\t+");
     private static final int SCAN_RESULT_CACHE_SIZE = 80;
     private final LruCache<String, ScanResult> mScanResultCache;
@@ -148,6 +139,8 @@
     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 user has disabled suspend optimizations through settings */
+    private AtomicBoolean mSuspendOptEnabled = new AtomicBoolean(true);
 
     private boolean mBluetoothConnectionActive = false;
 
@@ -263,6 +256,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;
@@ -466,6 +461,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 */
@@ -601,6 +598,9 @@
         mPrimaryDeviceType = mContext.getResources().getString(
                 com.android.internal.R.string.config_wifi_p2p_device_type);
 
+        mSuspendOptEnabled.set(Settings.Secure.getInt(mContext.getContentResolver(),
+                    Settings.Secure.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1);
+
         mContext.registerReceiver(
             new BroadcastReceiver() {
                 @Override
@@ -636,18 +636,25 @@
                         enableBackgroundScanCommand(false);
                     }
                     enableAllNetworks();
-                    sendMessage(CMD_CLEAR_SUSPEND_OPTIMIZATIONS);
+                    if (mSuspendOptEnabled.get()) {
+                        if (DBG) log("Clear suspend optimizations");
+                        sendMessage(CMD_CLEAR_SUSPEND_OPTIMIZATIONS);
+                    }
                 } 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);
+                    if (mSuspendOptEnabled.get()) {
+                        if (DBG) log("Enable suspend optimizations");
+                        //Allow 2s for suspend optimizations to be set
+                        mSuspendWakeLock.acquire(2000);
+                        sendMessage(CMD_SET_SUSPEND_OPTIMIZATIONS);
+                    }
                 }
             }
         };
+
         mContext.registerReceiver(
                 new BroadcastReceiver() {
                     @Override
@@ -658,6 +665,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) {
+                        mSuspendOptEnabled.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 +699,7 @@
                         addState(mL2ConnectedState, mConnectModeState);
                             addState(mObtainingIpState, mL2ConnectedState);
                             addState(mVerifyingLinkState, mL2ConnectedState);
+                            addState(mCaptivePortalCheckState, mL2ConnectedState);
                             addState(mConnectedState, mL2ConnectedState);
                         addState(mDisconnectingState, mConnectModeState);
                         addState(mDisconnectedState, mConnectModeState);
@@ -852,6 +870,10 @@
         }
     }
 
+    public void captivePortalCheckComplete() {
+        sendMessage(obtainMessage(CMD_CAPTIVE_CHECK_COMPLETE));
+    }
+
     /**
      * TODO: doc
      */
@@ -878,7 +900,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 +1171,8 @@
         sb.append("mLastNetworkId ").append(mLastNetworkId).append(LS);
         sb.append("mReconnectCount ").append(mReconnectCount).append(LS);
         sb.append("mIsScanMode ").append(mIsScanMode).append(LS);
+        sb.append("mHighPerfMode").append(mHighPerfMode).append(LS);
+        sb.append("mSuspendOptEnabled").append(mSuspendOptEnabled).append(LS);
         sb.append("Supplicant status").append(LS)
                 .append(mWifiNative.status()).append(LS).append(LS);
 
@@ -1174,7 +1204,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;
@@ -1342,131 +1372,103 @@
         mContext.sendStickyBroadcast(intent);
     }
 
+    private static final String BSSID_STR = "bssid=";
+    private static final String FREQ_STR = "freq=";
+    private static final String LEVEL_STR = "level=";
+    private static final String TSF_STR = "tsf=";
+    private static final String FLAGS_STR = "flags=";
+    private static final String SSID_STR = "ssid=";
+    private static final String DELIMITER_STR = "====";
     /**
-     * Parse the scan result line passed to us by wpa_supplicant (helper).
-     * @param line the line to parse
-     * @return the {@link ScanResult} object
-     */
-    private ScanResult parseScanResult(String line) {
-        ScanResult scanResult = null;
-        if (line != null) {
-            /*
-             * Cache implementation (LinkedHashMap) is not synchronized, thus,
-             * must synchronized here!
-             */
-            synchronized (mScanResultCache) {
-                String[] result = scanResultPattern.split(line);
-                if (3 <= result.length && result.length <= 5) {
-                    String bssid = result[0];
-                    // bssid | frequency | level | flags | ssid
-                    int frequency;
-                    int level;
-                    try {
-                        frequency = Integer.parseInt(result[1]);
-                        level = Integer.parseInt(result[2]);
-                        /* some implementations avoid negative values by adding 256
-                         * so we need to adjust for that here.
-                         */
-                        if (level > 0) level -= 256;
-                    } catch (NumberFormatException e) {
-                        frequency = 0;
-                        level = 0;
-                    }
-
-                    /*
-                     * The formatting of the results returned by
-                     * wpa_supplicant is intended to make the fields
-                     * line up nicely when printed,
-                     * not to make them easy to parse. So we have to
-                     * apply some heuristics to figure out which field
-                     * is the SSID and which field is the flags.
-                     */
-                    String ssid;
-                    String flags;
-                    if (result.length == 4) {
-                        if (result[3].charAt(0) == '[') {
-                            flags = result[3];
-                            ssid = "";
-                        } else {
-                            flags = "";
-                            ssid = result[3];
-                        }
-                    } else if (result.length == 5) {
-                        flags = result[3];
-                        ssid = result[4];
-                    } else {
-                        // Here, we must have 3 fields: no flags and ssid
-                        // set
-                        flags = "";
-                        ssid = "";
-                    }
-
-                    // bssid + ssid is the hash key
-                    String key = bssid + ssid;
-                    scanResult = mScanResultCache.get(key);
-                    if (scanResult != null) {
-                        scanResult.level = level;
-                        scanResult.SSID = ssid;
-                        scanResult.capabilities = flags;
-                        scanResult.frequency = frequency;
-                    } else {
-                        // Do not add scan results that have no SSID set
-                        if (0 < ssid.trim().length()) {
-                            scanResult =
-                                new ScanResult(
-                                    ssid, bssid, flags, level, frequency);
-                            mScanResultCache.put(key, scanResult);
-                        }
-                    }
-                } else {
-                    loge("Misformatted scan result text with " +
-                          result.length + " fields: " + line);
-                }
-            }
-        }
-
-        return scanResult;
-    }
-
-    /**
-     * scanResults input format
-     * 00:bb:cc:dd:cc:ee       2427    166     [WPA-EAP-TKIP][WPA2-EAP-CCMP]   Net1
-     * 00:bb:cc:dd:cc:ff       2412    165     [WPA-EAP-TKIP][WPA2-EAP-CCMP]   Net2
+     * Format:
+     * bssid=68:7f:76:d7:1a:6e
+     * freq=2412
+     * level=-44
+     * tsf=1344626243700342
+     * flags=[WPA2-PSK-CCMP][WPS][ESS]
+     * ssid=zfdy
+     * ====
+     * bssid=68:5f:74:d7:1a:6f
+     * freq=5180
+     * level=-73
+     * tsf=1344626243700373
+     * flags=[WPA2-PSK-CCMP][WPS][ESS]
+     * ssid=zuby
+     * ====
      */
     private void setScanResults(String scanResults) {
+        String bssid = "";
+        int level = 0;
+        int freq = 0;
+        long tsf = 0;
+        String flags = "";
+        String ssid = "";
+
         if (scanResults == null) {
             return;
         }
 
-        List<ScanResult> scanList = new ArrayList<ScanResult>();
+        synchronized(mScanResultCache) {
+            mScanResults = new ArrayList<ScanResult>();
+            String[] lines = scanResults.split("\n");
 
-        int lineCount = 0;
-
-        int scanResultsLen = scanResults.length();
-        // Parse the result string, keeping in mind that the last line does
-        // not end with a newline.
-        for (int lineBeg = 0, lineEnd = 0; lineEnd <= scanResultsLen; ++lineEnd) {
-            if (lineEnd == scanResultsLen || scanResults.charAt(lineEnd) == '\n') {
-                ++lineCount;
-
-                if (lineCount == 1) {
-                    lineBeg = lineEnd + 1;
-                    continue;
-                }
-                if (lineEnd > lineBeg) {
-                    String line = scanResults.substring(lineBeg, lineEnd);
-                    ScanResult scanResult = parseScanResult(line);
-                    if (scanResult != null) {
-                        scanList.add(scanResult);
-                    } else {
-                        //TODO: hidden network handling
+            for (String line : lines) {
+                if (line.startsWith(BSSID_STR)) {
+                    bssid = line.substring(BSSID_STR.length());
+                } else if (line.startsWith(FREQ_STR)) {
+                    try {
+                        freq = Integer.parseInt(line.substring(FREQ_STR.length()));
+                    } catch (NumberFormatException e) {
+                        freq = 0;
                     }
+                } else if (line.startsWith(LEVEL_STR)) {
+                    try {
+                        level = Integer.parseInt(line.substring(LEVEL_STR.length()));
+                        /* some implementations avoid negative values by adding 256
+                         * so we need to adjust for that here.
+                         */
+                        if (level > 0) level -= 256;
+                    } catch(NumberFormatException e) {
+                        level = 0;
+                    }
+                } else if (line.startsWith(TSF_STR)) {
+                    try {
+                        tsf = Long.parseLong(line.substring(TSF_STR.length()));
+                    } catch (NumberFormatException e) {
+                        tsf = 0;
+                    }
+                } else if (line.startsWith(FLAGS_STR)) {
+                    flags = line.substring(FLAGS_STR.length());
+                } else if (line.startsWith(SSID_STR)) {
+                    ssid = line.substring(SSID_STR.length());
+                    if (ssid == null) ssid = "";
+                } else if (line.startsWith(DELIMITER_STR)) {
+                    if (bssid != null) {
+                        String key = bssid + ssid;
+                        ScanResult scanResult = mScanResultCache.get(key);
+                        if (scanResult != null) {
+                            scanResult.level = level;
+                            scanResult.SSID = ssid;
+                            scanResult.capabilities = flags;
+                            scanResult.frequency = freq;
+                            scanResult.timestamp = tsf;
+                        } else {
+                            scanResult =
+                                new ScanResult(
+                                        ssid, bssid, flags, level, freq, tsf);
+                            mScanResultCache.put(key, scanResult);
+                        }
+                        mScanResults.add(scanResult);
+                    }
+                    bssid = null;
+                    level = 0;
+                    freq = 0;
+                    tsf = 0;
+                    flags = "";
+                    ssid = "";
                 }
-                lineBeg = lineEnd + 1;
             }
         }
-
-        mScanResults = scanList;
     }
 
     /*
@@ -1525,6 +1527,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);
@@ -1599,7 +1625,7 @@
         }
 
         if (state != mNetworkInfo.getDetailedState()) {
-            mNetworkInfo.setDetailedState(state, null, null);
+            mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID());
         }
     }
 
@@ -1624,10 +1650,7 @@
             mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID);
         }
 
-        if (state == SupplicantState.ASSOCIATING) {
-            /* BSSID is valid only in ASSOCIATING state */
-            mWifiInfo.setBSSID(stateChangeResult.BSSID);
-        }
+        mWifiInfo.setBSSID(stateChangeResult.BSSID);
         mWifiInfo.setSSID(stateChangeResult.SSID);
 
         mSupplicantStateTracker.sendMessage(Message.obtain(message));
@@ -1649,10 +1672,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 {
@@ -1794,12 +1814,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);
@@ -1905,6 +1925,9 @@
                 case CMD_CLEAR_SUSPEND_OPTIMIZATIONS:
                 case CMD_NO_NETWORKS_PERIODIC_SCAN:
                     break;
+                case DhcpStateMachine.CMD_ON_QUIT:
+                    mDhcpStateMachine = null;
+                    break;
                 case CMD_SET_SUSPEND_OPTIMIZATIONS:
                     mSuspendWakeLock.release();
                     break;
@@ -1936,8 +1959,9 @@
                     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;
                 default:
                     loge("Error! unhandled message" + message);
@@ -2474,6 +2498,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()) {
@@ -2791,7 +2818,7 @@
             if (DBG) log(getName() + "\n");
             mIsRunning = false;
             updateBatteryWorkSource(null);
-            mScanResults = null;
+            mScanResults = new ArrayList<ScanResult>();
 
             if (mP2pSupported) mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_DISABLE_P2P);
             mContext.unregisterReceiver(mScreenReceiver);
@@ -3140,10 +3167,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 +3200,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 +3268,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 +3295,6 @@
                     } catch (IllegalStateException e) {
                         loge("Failed to enable IPv6: " + e);
                     }
-
                     setNetworkDetailedState(DetailedState.CONNECTED);
                     mWifiConfigStore.updateStatus(mLastNetworkId, DetailedState.CONNECTED);
                     sendNetworkStateChangeBroadcast(mLastBssid);
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/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 0be2b27..8b8077ec 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -1349,7 +1349,7 @@
                     }
 
                     if (mGroup.isGroupOwner()) {
-                        stopDhcpServer();
+                        stopDhcpServer(mGroup.getInterface());
                     } else {
                         if (DBG) logd("stop DHCP client");
                         mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP);
@@ -1599,9 +1599,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;