Merge "Update GrContext creation calls to use sk_sp"
diff --git a/Android.bp b/Android.bp
index 82589c1..40757a9 100644
--- a/Android.bp
+++ b/Android.bp
@@ -545,6 +545,7 @@
         "core/java/android/net/EventLogTags.logtags",
         "core/java/android/webkit/EventLogTags.logtags",
         "core/java/com/android/internal/logging/EventLogTags.logtags",
+        "core/java/com/android/server/DropboxLogTags.logtags",
 
         ":framework-statslog-gen",
     ],
diff --git a/Android.mk b/Android.mk
index 10d11f3..9676958 100644
--- a/Android.mk
+++ b/Android.mk
@@ -486,6 +486,10 @@
 
 include $(BUILD_APIDIFF)
 
+# Hack to get diffs included in docs output
+out_zip := $(OUT_DOCS)/$(LOCAL_MODULE)-docs.zip
+$(out_zip): $(full_target)
+
 # ====  System API diff ===========================
 include $(CLEAR_VARS)
 
@@ -512,6 +516,10 @@
 
 include $(BUILD_APIDIFF)
 
+# Hack to get diffs included in docs output
+out_zip := $(OUT_DOCS)/$(LOCAL_MODULE)-docs.zip
+$(out_zip): $(full_target)
+
 # ====  the api stubs and current.xml ===========================
 include $(CLEAR_VARS)
 
@@ -656,10 +664,6 @@
 # Check comment when you are updating the API
 update-api: doc-comment-check-docs
 
-# Generate API diffs as part of docs builds
-docs: offline-sdk-referenceonly-diff
-docs: offline-system-sdk-referenceonly-diff
-
 # ====  static html in the sdk ==================================
 include $(CLEAR_VARS)
 
diff --git a/apct-tests/perftests/core/Android.mk b/apct-tests/perftests/core/Android.mk
index f08b402..75cb229 100644
--- a/apct-tests/perftests/core/Android.mk
+++ b/apct-tests/perftests/core/Android.mk
@@ -11,8 +11,9 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
     android-support-test \
     apct-perftests-utils \
-    guava \
-    legacy-android-test
+    guava
+
+LOCAL_JAVA_LIBRARIES := android.test.base
 
 LOCAL_PACKAGE_NAME := CorePerfTests
 
diff --git a/api/current.txt b/api/current.txt
index f56f1a1..c3dbee0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3952,6 +3952,7 @@
     field public static final android.os.Parcelable.Creator<android.app.ActivityManager.RunningAppProcessInfo> CREATOR;
     field public static final deprecated int IMPORTANCE_BACKGROUND = 400; // 0x190
     field public static final int IMPORTANCE_CACHED = 400; // 0x190
+    field public static final int IMPORTANCE_CANT_SAVE_STATE = 270; // 0x10e
     field public static final deprecated int IMPORTANCE_EMPTY = 500; // 0x1f4
     field public static final int IMPORTANCE_FOREGROUND = 100; // 0x64
     field public static final int IMPORTANCE_FOREGROUND_SERVICE = 125; // 0x7d
@@ -6393,7 +6394,7 @@
     method public deprecated boolean isCallerApplicationRestrictionsManagingPackage();
     method public boolean isDeviceOwnerApp(java.lang.String);
     method public boolean isLockTaskPermitted(java.lang.String);
-    method public boolean isLogoutButtonEnabled();
+    method public boolean isLogoutEnabled();
     method public boolean isManagedProfile(android.content.ComponentName);
     method public boolean isMasterVolumeMuted(android.content.ComponentName);
     method public boolean isNetworkLoggingEnabled(android.content.ComponentName);
@@ -6437,7 +6438,7 @@
     method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
     method public void setLockTaskFeatures(android.content.ComponentName, int);
     method public void setLockTaskPackages(android.content.ComponentName, java.lang.String[]) throws java.lang.SecurityException;
-    method public void setLogoutButtonEnabled(android.content.ComponentName, boolean);
+    method public void setLogoutEnabled(android.content.ComponentName, boolean);
     method public void setLongSupportMessage(android.content.ComponentName, java.lang.CharSequence);
     method public void setMasterVolumeMuted(android.content.ComponentName, boolean);
     method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
@@ -20558,6 +20559,7 @@
     method public int getMaxWidth();
     method public java.lang.CharSequence getTextForImeAction(int);
     method public android.app.Dialog getWindow();
+    method public void hideSoftInputFromInputMethod(int);
     method public void hideStatusIcon();
     method public void hideWindow();
     method public boolean isExtractViewShown();
@@ -20613,10 +20615,16 @@
     method public void setCandidatesViewShown(boolean);
     method public void setExtractView(android.view.View);
     method public void setExtractViewShown(boolean);
+    method public void setInputMethod(java.lang.String);
+    method public void setInputMethodAndSubtype(java.lang.String, android.view.inputmethod.InputMethodSubtype);
     method public void setInputView(android.view.View);
+    method public boolean shouldOfferSwitchingToNextInputMethod();
+    method public void showSoftInputFromInputMethod(int);
     method public void showStatusIcon(int);
     method public void showWindow(boolean);
     method public void switchInputMethod(java.lang.String);
+    method public boolean switchToLastInputMethod();
+    method public boolean switchToNextInputMethod(boolean);
     method public void updateFullscreenMode();
     method public void updateInputViewShown();
     field public static final int BACK_DISPOSITION_DEFAULT = 0; // 0x0
@@ -49034,10 +49042,10 @@
     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 deprecated 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 deprecated void hideStatusIcon(android.os.IBinder);
     method public boolean isAcceptingText();
     method public boolean isActive(android.view.View);
     method public boolean isActive();
@@ -49047,17 +49055,17 @@
     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 boolean shouldOfferSwitchingToNextInputMethod(android.os.IBinder);
+    method public deprecated void setInputMethod(android.os.IBinder, java.lang.String);
+    method public deprecated void setInputMethodAndSubtype(android.os.IBinder, java.lang.String, android.view.inputmethod.InputMethodSubtype);
+    method public deprecated boolean shouldOfferSwitchingToNextInputMethod(android.os.IBinder);
     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 deprecated void showSoftInputFromInputMethod(android.os.IBinder, int);
+    method public deprecated void showStatusIcon(android.os.IBinder, java.lang.String, int);
+    method public deprecated boolean switchToLastInputMethod(android.os.IBinder);
+    method public deprecated boolean switchToNextInputMethod(android.os.IBinder, boolean);
     method public void toggleSoftInput(int, int);
     method public void toggleSoftInputFromWindow(android.os.IBinder, int, int);
     method public deprecated void updateCursor(android.view.View, int, int, int, int);
diff --git a/api/test-current.txt b/api/test-current.txt
index 3c3521f..27e585d 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -162,6 +162,10 @@
     method public abstract boolean isPermissionReviewModeEnabled();
   }
 
+  public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+    field public static final int PROTECTION_FLAG_VENDOR_PRIVILEGED = 32768; // 0x8000
+  }
+
   public final class ShortcutInfo implements android.os.Parcelable {
     method public boolean isVisibleToPublisher();
   }
diff --git a/cmds/statsd/src/atoms_copy.proto b/cmds/statsd/src/atoms_copy.proto
index 18b2144..72bb38a 100644
--- a/cmds/statsd/src/atoms_copy.proto
+++ b/cmds/statsd/src/atoms_copy.proto
@@ -48,12 +48,14 @@
         SyncStateChanged sync_state_changed = 7;
         ScheduledJobStateChanged scheduled_job_state_changed = 8;
         ScreenBrightnessChanged screen_brightness_changed = 9;
-        // 10-20 are temporarily reserved for wakelocks etc.
         WakelockStateChanged wakelock_state_changed = 10;
-        UidWakelockStateChanged uid_wakelock_state_changed = 11;
-        LongPartialWakelockStateChanged long_partial_wakelock_state_changed = 12;
-        BatterySaverModeStateChanged battery_saver_mode_state_changed = 21;
-        DeviceIdleModeStateChanged device_idle_mode_state_changed = 22;
+        LongPartialWakelockStateChanged long_partial_wakelock_state_changed = 11;
+        MobileRadioPowerStateChanged mobile_radio_power_state_changed = 12;
+        WifiRadioPowerStateChanged wifi_radio_power_state_changed = 13;
+        // TODO: 14-19 are blank, but need not be
+        BatterySaverModeStateChanged battery_saver_mode_state_changed = 20;
+        DeviceIdleModeStateChanged device_idle_mode_state_changed = 21;
+        DeviceIdlingModeStateChanged device_idling_mode_state_changed = 22;
         AudioStateChanged audio_state_changed = 23;
         MediaCodecActivityChanged media_codec_activity_changed = 24;
         CameraStateChanged camera_state_changed = 25;
@@ -75,6 +77,8 @@
         SettingChanged setting_changed = 41;
         ActivityForegroundStateChanged activity_foreground_state_changed = 42;
         IsolatedUidChanged isolated_uid_changed = 43;
+        PacketWakeupOccurred packet_wakeup_occurred = 44;
+        DropboxErrorChanged dropbox_error_changed = 45;
         // TODO: Reorder the numbering so that the most frequent occur events occur in the first 15.
     }
 
@@ -91,6 +95,8 @@
         CpuTimePerFreqPulled cpu_time_per_freq_pulled = 1008;
         CpuTimePerUidPulled cpu_time_per_uid_pulled = 1009;
         CpuTimePerUidFreqPulled cpu_time_per_uid_freq_pulled = 1010;
+        WifiActivityEnergyInfoPulled wifi_activity_energy_info_pulled = 1011;
+        ModemActivityInfoPulled modem_activity_info_pulled = 1012;
     }
 }
 
@@ -147,6 +153,7 @@
         STATE_DOZE = 3;
         STATE_DOZE_SUSPEND = 4;
         STATE_VR = 5;
+        STATE_ON_SUSPEND = 6;
     }
     // New screen state.
     optional State display_state = 1;
@@ -179,13 +186,17 @@
     // TODO: What is this?
     optional string name = 2;
 
-    // The state.
-    // TODO: Use an enum.
-    optional int32 event = 3;
+    // What lifecycle state the process changed to.
+    // This enum is specific to atoms.proto.
+    enum Event {
+        PROCESS_FINISHED = 0;
+        PROCESS_STARTED = 1;
+        PROCESS_CRASHED = 2;
+        PROCESS_ANRED = 3;
+    }
+    optional Event event = 3;
 }
 
-
-
 /**
  * Logs when the ble scan state changes.
  *
@@ -417,31 +428,6 @@
 }
 
 /**
- * Logs when an app is holding a wakelock, regardless of the wakelock's name.
- *
- * Logged from:
- *   frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
- */
-message UidWakelockStateChanged {
-    // TODO: Add attribution instead of uid.
-    optional int32 uid = 1;
-
-    // Type of wakelock.
-    enum Type {
-        PARTIAL = 0;
-        FULL = 1;
-        WINDOW = 2;
-    }
-    optional Type type = 2;
-
-    enum State {
-        OFF = 0;
-        ON = 1;
-    }
-    optional State state = 3;
-}
-
-/**
  * Logs when a partial wakelock is considered 'long' (over 1 min).
  *
  * Logged from:
@@ -482,11 +468,33 @@
  * Logs Doze mode state change.
  *
  * Logged from:
- *   frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
+ *   frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
  */
 message DeviceIdleModeStateChanged {
     // TODO: Use the enum matching BatteryStats.DEVICE_IDLE_MODE_.
-    optional int32 state = 1;
+    enum State {
+        DEVICE_IDLE_MODE_OFF = 0;
+        DEVICE_IDLE_MODE_LIGHT = 1;
+        DEVICE_IDLE_MODE_DEEP = 2;
+    }
+    optional State state = 1;
+}
+
+
+/**
+ * Logs state change of Doze mode including maintenance windows.
+ *
+ * Logged from:
+ *   frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
+ */
+message DeviceIdlingModeStateChanged {
+    // TODO: Use the enum matching BatteryStats.DEVICE_IDLE_MODE_.
+    enum State {
+        DEVICE_IDLE_MODE_OFF = 0;
+        DEVICE_IDLE_MODE_LIGHT = 1;
+        DEVICE_IDLE_MODE_DEEP = 2;
+    }
+    optional State state = 1;
 }
 
 /**
@@ -586,6 +594,49 @@
 message WakeupAlarmOccurred {
     // TODO: Add attribution instead of uid?
     optional int32 uid = 1;
+
+    // Name of the wakeup alarm.
+    optional string tag = 2;
+}
+
+/**
+ * Logs when an an app causes the mobile radio to change state.
+ * Changing from LOW to MEDIUM or HIGH can be considered the app waking the mobile radio.
+ *
+ * Logged from:
+ *   frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
+ */
+message MobileRadioPowerStateChanged {
+    // TODO: Add attribution instead of uid?
+    optional int32 uid = 1;
+
+    // TODO: Reference telephony/java/android/telephony/DataConnectionRealTimeInfo.java states.
+    enum PowerState {
+        DC_POWER_STATE_LOW = 1;
+        DC_POWER_STATE_MEDIUM = 2;
+        DC_POWER_STATE_HIGH = 3;
+    }
+    optional PowerState power_state = 2;
+}
+
+/**
+ * Logs when an an app causes the wifi radio to change state.
+ * Changing from LOW to MEDIUM or HIGH can be considered the app waking the wifi radio.
+ *
+ * Logged from:
+ *   frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
+ */
+message WifiRadioPowerStateChanged {
+    // TODO: Add attribution instead of uid?
+    optional int32 uid = 1;
+
+    // TODO: Reference telephony/java/android/telephony/DataConnectionRealTimeInfo.java states.
+    enum PowerState {
+        DC_POWER_STATE_LOW = 1;
+        DC_POWER_STATE_MEDIUM = 2;
+        DC_POWER_STATE_HIGH = 3;
+    }
+    optional PowerState power_state = 2;
 }
 
 /**
@@ -705,7 +756,7 @@
     optional int32 user = 7;
 }
 
-/*
+/**
  * Logs activity going to foreground or background
  *
  * Logged from:
@@ -723,6 +774,34 @@
 }
 
 /**
+ * Logs when an error is written to dropbox.
+ * Logged from:
+ *      frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
+ */
+message DropboxErrorChanged {
+    // The uid if available. -1 means not available.
+    optional int32 uid = 1;
+
+    // Tag used when recording this error to dropbox. Contains data_ or system_ prefix.
+    optional string tag = 2;
+
+    // The name of the process.
+    optional string process_name = 3;
+
+    // The pid if available. -1 means not available.
+    optional int32 pid = 4;
+
+    // 1 indicates is instant app. -1 indicates Not applicable.
+    optional int32 is_instant_app = 5;
+
+    // The activity name if available.
+    optional string activity_name = 6;
+
+    // 1 indicates in foreground. -1 indicates not available.
+    optional int32 is_foreground = 7;
+}
+
+/**
  * Pulls bytes transferred via wifi (Sum of foreground and background usage).
  *
  * Pulled from:
@@ -817,7 +896,7 @@
     optional int64 time = 4;
 }
 
-/*
+/**
  * Pulls PowerStatePlatformSleepState.
  *
  * Definition here:
@@ -877,7 +956,7 @@
     optional int32 is_create = 3;
 }
 
-/*
+/**
  * Pulls Cpu time per frequency.
  * Note: this should be pulled for gauge metric only, without condition.
  * The puller keeps internal state of last values. It should not be pulled by
@@ -894,7 +973,7 @@
     optional uint64 time = 3;
 }
 
-/*
+/**
  * Pulls Cpu Time Per Uid.
  * Note that isolated process uid time should be attributed to host uids.
  */
@@ -913,4 +992,86 @@
     optional uint64 uid = 1;
     optional uint64 freq_idx = 2;
     optional uint64 time_ms = 3;
+}
+
+/*
+ * Logs the reception of an incoming network packet causing the main system to wake up for
+ * processing that packet. These events are notified by the kernel via Netlink NFLOG to Netd
+ * and processed by WakeupController.cpp.
+ */
+message PacketWakeupOccurred {
+    // The uid owning the socket into which the packet was delivered, or -1 if the packet was
+    // delivered nowhere.
+    optional int32 uid = 1;
+    // The interface name on which the packet was received.
+    optional string iface = 2;
+    // The ethertype value of the packet.
+    optional int32 ethertype = 3;
+    // String representation of the destination MAC address of the packet.
+    optional string destination_hardware_address = 4;
+    // String representation of the source address of the packet if this was an IP packet.
+    optional string source_ip = 5;
+    // String representation of the destination address of the packet if this was an IP packet.
+    optional string destination_ip = 6;
+    // The value of the protocol field if this was an IPv4 packet or the value of the Next Header
+    // field if this was an IPv6 packet. The range of possible values is the same for both IP
+    // families.
+    optional int32 ip_next_header = 7;
+    // The source port if this was a TCP or UDP packet.
+    optional int32 source_port = 8;
+    // The destination port if this was a TCP or UDP packet.
+    optional int32 destination_port = 9;
+}
+
+/**
+ * Pulls Wifi Controller Activity Energy Info
+ */
+message WifiActivityEnergyInfoPulled {
+    // timestamp(wall clock) of record creation
+    optional uint64 timestamp_ms = 1;
+    // stack reported state
+    // TODO: replace this with proto enum
+    optional int32 stack_state = 2;
+    // tx time in ms
+    optional uint64 controller_tx_time_ms = 3;
+    // rx time in ms
+    optional uint64 controller_rx_time_ms = 4;
+    // idle time in ms
+    optional uint64 controller_idle_time_ms = 5;
+    // product of current(mA), voltage(V) and time(ms)
+    optional uint64 controller_energy_used = 6;
+}
+
+/**
+ * Pulls Modem Activity Energy Info
+ */
+message ModemActivityInfoPulled {
+    // timestamp(wall clock) of record creation
+    optional uint64 timestamp_ms = 1;
+    // sleep time in ms.
+    optional uint64 sleep_time_ms = 2;
+    // idle time in ms
+    optional uint64 controller_idle_time_ms = 3;
+    /**
+     * Tx power index
+     * index 0 = tx_power < 0dBm
+     * index 1 = 0dBm < tx_power < 5dBm
+     * index 2 = 5dBm < tx_power < 15dBm
+     * index 3 = 15dBm < tx_power < 20dBm
+     * index 4 = tx_power > 20dBm
+     */
+    // tx time in ms at power level 0
+    optional uint64 controller_tx_time_pl0_ms = 4;
+    // tx time in ms at power level 1
+    optional uint64 controller_tx_time_pl1_ms = 5;
+    // tx time in ms at power level 2
+    optional uint64 controller_tx_time_pl2_ms = 6;
+    // tx time in ms at power level 3
+    optional uint64 controller_tx_time_pl3_ms = 7;
+    // tx time in ms at power level 4
+    optional uint64 controller_tx_time_pl4_ms = 8;
+    // rx time in ms at power level 5
+    optional uint64 controller_rx_time_ms = 9;
+    // product of current(mA), voltage(V) and time(ms)
+    optional uint64 energy_used = 10;
 }
\ No newline at end of file
diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java
index 5e8f26d..735a327 100644
--- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java
+++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java
@@ -110,113 +110,7 @@
                 log.getEventMetrics();
         for (StatsLog.EventMetricData event : eventMetricDataWrapper.getDataList()) {
             sb.append(getDateStr(event.getTimestampNanos())).append(": ");
-            switch (event.getAtom().getPushedCase()) {
-                case SETTING_CHANGED:
-                    sb.append("SETTING_CHANGED\n");
-                    break;
-                case SYNC_STATE_CHANGED:
-                    sb.append("SYNC_STATE_CHANGED\n");
-                    break;
-                case AUDIO_STATE_CHANGED:
-                    sb.append("AUDIO_STATE_CHANGED\n");
-                    break;
-                case CAMERA_STATE_CHANGED:
-                    sb.append("CAMERA_STATE_CHANGED\n");
-                    break;
-                case ISOLATED_UID_CHANGED:
-                    sb.append("ISOLATED_UID_CHANGED\n");
-                    break;
-                case SCREEN_STATE_CHANGED:
-                    sb.append("SCREEN_STATE_CHANGED\n");
-                    break;
-                case SENSOR_STATE_CHANGED:
-                    sb.append("SENSOR_STATE_CHANGED\n");
-                    break;
-                case BATTERY_LEVEL_CHANGED:
-                    sb.append("BATTERY_LEVEL_CHANGED\n");
-                    break;
-                case PLUGGED_STATE_CHANGED:
-                    sb.append("PLUGGED_STATE_CHANGED\n");
-                    break;
-                case WAKEUP_ALARM_OCCURRED:
-                    sb.append("WAKEUP_ALARM_OCCURRED\n");
-                    break;
-                case BLE_SCAN_STATE_CHANGED:
-                    sb.append("BLE_SCAN_STATE_CHANGED\n");
-                    break;
-                case CHARGING_STATE_CHANGED:
-                    sb.append("CHARGING_STATE_CHANGED\n");
-                    break;
-                case GPS_SCAN_STATE_CHANGED:
-                    sb.append("GPS_SCAN_STATE_CHANGED\n");
-                    break;
-                case KERNEL_WAKEUP_REPORTED:
-                    sb.append("KERNEL_WAKEUP_REPORTED\n");
-                    break;
-                case WAKELOCK_STATE_CHANGED:
-                    sb.append("WAKELOCK_STATE_CHANGED\n");
-                    break;
-                case WIFI_LOCK_STATE_CHANGED:
-                    sb.append("WIFI_LOCK_STATE_CHANGED\n");
-                    break;
-                case WIFI_SCAN_STATE_CHANGED:
-                    sb.append("WIFI_SCAN_STATE_CHANGED\n");
-                    break;
-                case BLE_SCAN_RESULT_RECEIVED:
-                    sb.append("BLE_SCAN_RESULT_RECEIVED\n");
-                    break;
-                case DEVICE_ON_STATUS_CHANGED:
-                    sb.append("DEVICE_ON_STATUS_CHANGED\n");
-                    break;
-                case FLASHLIGHT_STATE_CHANGED:
-                    sb.append("FLASHLIGHT_STATE_CHANGED\n");
-                    break;
-                case SCREEN_BRIGHTNESS_CHANGED:
-                    sb.append("SCREEN_BRIGHTNESS_CHANGED\n");
-                    break;
-                case UID_PROCESS_STATE_CHANGED:
-                    sb.append("UID_PROCESS_STATE_CHANGED\n");
-                    break;
-                case UID_WAKELOCK_STATE_CHANGED:
-                    sb.append("UID_WAKELOCK_STATE_CHANGED\n");
-                    break;
-                case DEVICE_TEMPERATURE_REPORTED:
-                    sb.append("DEVICE_TEMPERATURE_REPORTED\n");
-                    break;
-                case SCHEDULED_JOB_STATE_CHANGED:
-                    sb.append("SCHEDULED_JOB_STATE_CHANGED\n");
-                    break;
-                case MEDIA_CODEC_ACTIVITY_CHANGED:
-                    sb.append("MEDIA_CODEC_ACTIVITY_CHANGED\n");
-                    break;
-                case WIFI_SIGNAL_STRENGTH_CHANGED:
-                    sb.append("WIFI_SIGNAL_STRENGTH_CHANGED\n");
-                    break;
-                case PHONE_SIGNAL_STRENGTH_CHANGED:
-                    sb.append("PHONE_SIGNAL_STRENGTH_CHANGED\n");
-                    break;
-                case DEVICE_IDLE_MODE_STATE_CHANGED:
-                    sb.append("DEVICE_IDLE_MODE_STATE_CHANGED\n");
-                    break;
-                case BATTERY_SAVER_MODE_STATE_CHANGED:
-                    sb.append("BATTERY_SAVER_MODE_STATE_CHANGED\n");
-                    break;
-                case PROCESS_LIFE_CYCLE_STATE_CHANGED:
-                    sb.append("PROCESS_LIFE_CYCLE_STATE_CHANGED\n");
-                    break;
-                case ACTIVITY_FOREGROUND_STATE_CHANGED:
-                    sb.append("ACTIVITY_FOREGROUND_STATE_CHANGED\n");
-                    break;
-                case BLE_UNOPTIMIZED_SCAN_STATE_CHANGED:
-                    sb.append("BLE_UNOPTIMIZED_SCAN_STATE_CHANGED\n");
-                    break;
-                case LONG_PARTIAL_WAKELOCK_STATE_CHANGED:
-                    sb.append("LONG_PARTIAL_WAKELOCK_STATE_CHANGED\n");
-                    break;
-                case PUSHED_NOT_SET:
-                    sb.append("PUSHED_NOT_SET\n");
-                    break;
-            }
+            sb.append(event.getAtom().getPushedCase().toString()).append("\n");
         }
     }
 
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 7a1931718..037aeb0 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -35,23 +35,23 @@
 
     void setServiceInfo(in AccessibilityServiceInfo info);
 
-    boolean findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
+    String[] findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
         long accessibilityNodeId, int interactionId,
         IAccessibilityInteractionConnectionCallback callback, int flags, long threadId,
         in Bundle arguments);
 
-    boolean findAccessibilityNodeInfosByText(int accessibilityWindowId, long accessibilityNodeId,
+    String[] findAccessibilityNodeInfosByText(int accessibilityWindowId, long accessibilityNodeId,
         String text, int interactionId, IAccessibilityInteractionConnectionCallback callback,
         long threadId);
 
-    boolean findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
+    String[] findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
         long accessibilityNodeId, String viewId, int interactionId,
         IAccessibilityInteractionConnectionCallback callback, long threadId);
 
-    boolean findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType,
+    String[] findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType,
         int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId);
 
-    boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction,
+    String[] focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction,
         int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId);
 
     boolean performAccessibilityAction(int accessibilityWindowId, long accessibilityNodeId,
diff --git a/core/java/android/annotation/IntDef.java b/core/java/android/annotation/IntDef.java
index 3f9064e..f84a676 100644
--- a/core/java/android/annotation/IntDef.java
+++ b/core/java/android/annotation/IntDef.java
@@ -52,10 +52,12 @@
 @Target({ANNOTATION_TYPE})
 public @interface IntDef {
     /** Defines the constant prefix for this element */
-    String[] prefix() default "";
+    String[] prefix() default {};
+    /** Defines the constant suffix for this element */
+    String[] suffix() default {};
 
     /** Defines the allowed constants for this element */
-    long[] value() default {};
+    int[] value() default {};
 
     /** Defines whether the constants can be used as a flag, or just as an enum (the default) */
     boolean flag() default false;
diff --git a/core/java/android/annotation/LongDef.java b/core/java/android/annotation/LongDef.java
new file mode 100644
index 0000000..8723eef8
--- /dev/null
+++ b/core/java/android/annotation/LongDef.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+/**
+ * Denotes that the annotated long element represents
+ * a logical type and that its value should be one of the explicitly
+ * named constants. If the {@link #flag()} attribute is set to true,
+ * multiple constants can be combined.
+ * <p>
+ * <pre><code>
+ *  &#64;Retention(SOURCE)
+ *  &#64;LongDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
+ *  public @interface NavigationMode {}
+ *  public static final long NAVIGATION_MODE_STANDARD = 0;
+ *  public static final long NAVIGATION_MODE_LIST = 1;
+ *  public static final long NAVIGATION_MODE_TABS = 2;
+ *  ...
+ *  public abstract void setNavigationMode(@NavigationMode long mode);
+ *  &#64;NavigationMode
+ *  public abstract long getNavigationMode();
+ * </code></pre>
+ * For a flag, set the flag attribute:
+ * <pre><code>
+ *  &#64;LongDef(
+ *      flag = true,
+ *      value = {NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
+ * </code></pre>
+ *
+ * @hide
+ */
+@Retention(SOURCE)
+@Target({ANNOTATION_TYPE})
+public @interface LongDef {
+    /** Defines the constant prefix for this element */
+    String[] prefix() default "";
+
+    /** Defines the allowed constants for this element */
+    long[] value() default {};
+
+    /** Defines whether the constants can be used as a flag, or just as an enum (the default) */
+    boolean flag() default false;
+}
diff --git a/core/java/android/annotation/StringDef.java b/core/java/android/annotation/StringDef.java
index d5157c3..a37535b 100644
--- a/core/java/android/annotation/StringDef.java
+++ b/core/java/android/annotation/StringDef.java
@@ -46,6 +46,11 @@
 @Retention(SOURCE)
 @Target({ANNOTATION_TYPE})
 public @interface StringDef {
+    /** Defines the constant prefix for this element */
+    String[] prefix() default {};
+    /** Defines the constant suffix for this element */
+    String[] suffix() default {};
+
     /** Defines the allowed constants for this element */
     String[] value() default {};
 }
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 9241378..142630e 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2944,10 +2944,10 @@
         /**
          * Constant for {@link #importance}: This process is running an
          * application that can not save its state, and thus can't be killed
-         * while in the background.
-         * @hide
+         * while in the background.  This will be used with apps that have
+         * {@link android.R.attr#cantSaveState} set on their application tag.
          */
-        public static final int IMPORTANCE_CANT_SAVE_STATE= 270;
+        public static final int IMPORTANCE_CANT_SAVE_STATE = 270;
 
         /**
          * Constant for {@link #importance}: This process is contains services
@@ -2995,7 +2995,7 @@
                 return IMPORTANCE_CACHED;
             } else if (procState >= PROCESS_STATE_SERVICE) {
                 return IMPORTANCE_SERVICE;
-            } else if (procState > PROCESS_STATE_HEAVY_WEIGHT) {
+            } else if (procState == PROCESS_STATE_HEAVY_WEIGHT) {
                 return IMPORTANCE_CANT_SAVE_STATE;
             } else if (procState >= PROCESS_STATE_TRANSIENT_BACKGROUND) {
                 return IMPORTANCE_PERCEPTIBLE;
@@ -3051,7 +3051,7 @@
                 return PROCESS_STATE_HOME;
             } else if (importance >= IMPORTANCE_SERVICE) {
                 return PROCESS_STATE_SERVICE;
-            } else if (importance > IMPORTANCE_CANT_SAVE_STATE) {
+            } else if (importance == IMPORTANCE_CANT_SAVE_STATE) {
                 return PROCESS_STATE_HEAVY_WEIGHT;
             } else if (importance >= IMPORTANCE_PERCEPTIBLE) {
                 return PROCESS_STATE_TRANSIENT_BACKGROUND;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 8a4d29b..5369adf 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -5605,7 +5605,16 @@
 
         // Continue loading instrumentation.
         if (ii != null) {
-            final ApplicationInfo instrApp = new ApplicationInfo();
+            ApplicationInfo instrApp;
+            try {
+                instrApp = getPackageManager().getApplicationInfo(ii.packageName, 0,
+                        UserHandle.myUserId());
+            } catch (RemoteException e) {
+                instrApp = null;
+            }
+            if (instrApp == null) {
+                instrApp = new ApplicationInfo();
+            }
             ii.copyTo(instrApp);
             instrApp.initForUser(UserHandle.myUserId());
             final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index 55f9e28..382719b 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -568,9 +568,21 @@
     }
 
     /**
-     * Schedule an alarm that represents an alarm clock.
+     * Schedule an alarm that represents an alarm clock, which will be used to notify the user
+     * when it goes off.  The expectation is that when this alarm triggers, the application will
+     * further wake up the device to tell the user about the alarm -- turning on the screen,
+     * playing a sound, vibrating, etc.  As such, the system will typically also use the
+     * information supplied here to tell the user about this upcoming alarm if appropriate.
      *
-     * The system may choose to display information about this alarm to the user.
+     * <p>Due to the nature of this kind of alarm, similar to {@link #setExactAndAllowWhileIdle},
+     * these alarms will be allowed to trigger even if the system is in a low-power idle
+     * (a.k.a. doze) mode.  The system may also do some prep-work when it sees that such an
+     * alarm coming up, to reduce the amount of background work that could happen if this
+     * causes the device to fully wake up -- this is to avoid situations such as a large number
+     * of devices having an alarm set at the same time in the morning, all waking up at that
+     * time and suddenly swamping the network with pending background work.  As such, these
+     * types of alarms can be extremely expensive on battery use and should only be used for
+     * their intended purpose.</p>
      *
      * <p>
      * This method is like {@link #setExact(int, long, PendingIntent)}, but implies
@@ -783,9 +795,9 @@
 
     /**
      * Like {@link #set(int, long, PendingIntent)}, but this alarm will be allowed to execute
-     * even when the system is in low-power idle modes.  This type of alarm must <b>only</b>
-     * be used for situations where it is actually required that the alarm go off while in
-     * idle -- a reasonable example would be for a calendar notification that should make a
+     * even when the system is in low-power idle (a.k.a. doze) modes.  This type of alarm must
+     * <b>only</b> be used for situations where it is actually required that the alarm go off while
+     * in idle -- a reasonable example would be for a calendar notification that should make a
      * sound so the user is aware of it.  When the alarm is dispatched, the app will also be
      * added to the system's temporary whitelist for approximately 10 seconds to allow that
      * application to acquire further wake locks in which to complete its work.</p>
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index f831ae2..495fd3c 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -618,12 +618,13 @@
                         ConnectivityThread.getInstanceLooper());
             }});
 
-        registerService(Context.WIFI_RTT2_SERVICE, WifiRttManager.class,
+        registerService(Context.WIFI_RTT_RANGING_SERVICE, WifiRttManager.class,
                 new CachedServiceFetcher<WifiRttManager>() {
                     @Override
                     public WifiRttManager createService(ContextImpl ctx)
                             throws ServiceNotFoundException {
-                        IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_RTT2_SERVICE);
+                        IBinder b = ServiceManager.getServiceOrThrow(
+                                Context.WIFI_RTT_RANGING_SERVICE);
                         IWifiRttManager service = IWifiRttManager.Stub.asInterface(b);
                         return new WifiRttManager(ctx.getOuterContext(), service);
                     }});
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 562b981..ad21983 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -8585,32 +8585,31 @@
     }
 
     /**
-     * Called by a device owner to specify whether a logout button is enabled for all secondary
-     * users. The system may show a logout button that stops the user and switches back to the
-     * primary user.
+     * Called by a device owner to specify whether logout is enabled for all secondary users. The
+     * system may show a logout button that stops the user and switches back to the primary user.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
-     * @param enabled whether logout button should be enabled or not.
+     * @param enabled whether logout should be enabled or not.
      * @throws SecurityException if {@code admin} is not a device owner.
      */
-    public void setLogoutButtonEnabled(@NonNull ComponentName admin, boolean enabled) {
-        throwIfParentInstance("setLogoutButtonEnabled");
+    public void setLogoutEnabled(@NonNull ComponentName admin, boolean enabled) {
+        throwIfParentInstance("setLogoutEnabled");
         try {
-            mService.setLogoutButtonEnabled(admin, enabled);
+            mService.setLogoutEnabled(admin, enabled);
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
     }
 
     /**
-     * Returns whether logout button is enabled by a device owner.
+     * Returns whether logout is enabled by a device owner.
      *
-     * @return {@code true} if logout button is enabled by device owner, {@code false} otherwise.
+     * @return {@code true} if logout is enabled by device owner, {@code false} otherwise.
      */
-    public boolean isLogoutButtonEnabled() {
-        throwIfParentInstance("isLogoutButtonEnabled");
+    public boolean isLogoutEnabled() {
+        throwIfParentInstance("isLogoutEnabled");
         try {
-            return mService.isLogoutButtonEnabled();
+            return mService.isLogoutEnabled();
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index c525df7..ff869d2 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -372,6 +372,6 @@
 
     boolean clearApplicationUserData(in ComponentName admin, in String packageName, in IPackageDataObserver callback);
 
-    void setLogoutButtonEnabled(in ComponentName admin, boolean enabled);
-    boolean isLogoutButtonEnabled();
+    void setLogoutEnabled(in ComponentName admin, boolean enabled);
+    boolean isLogoutEnabled();
 }
diff --git a/core/java/android/app/slice/Slice.java b/core/java/android/app/slice/Slice.java
index ddc5760..807c47d 100644
--- a/core/java/android/app/slice/Slice.java
+++ b/core/java/android/app/slice/Slice.java
@@ -37,6 +37,8 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.Preconditions;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -53,9 +55,21 @@
     /**
      * @hide
      */
-    @StringDef({HINT_TITLE, HINT_LIST, HINT_LIST_ITEM, HINT_LARGE, HINT_ACTIONS, HINT_SELECTED,
-            HINT_NO_TINT, HINT_PARTIAL})
-    public @interface SliceHint{ }
+    @StringDef(prefix = { "HINT_" }, value = {
+            HINT_TITLE,
+            HINT_LIST,
+            HINT_LIST_ITEM,
+            HINT_LARGE,
+            HINT_ACTIONS,
+            HINT_SELECTED,
+            HINT_NO_TINT,
+            HINT_HIDDEN,
+            HINT_TOGGLE,
+            HINT_HORIZONTAL,
+            HINT_PARTIAL,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SliceHint {}
 
     /**
      * The meta-data key that allows an activity to easily be linked directly to a slice.
diff --git a/core/java/android/app/slice/SliceItem.java b/core/java/android/app/slice/SliceItem.java
index cdeee35..743d6b7 100644
--- a/core/java/android/app/slice/SliceItem.java
+++ b/core/java/android/app/slice/SliceItem.java
@@ -29,6 +29,8 @@
 
 import com.android.internal.util.ArrayUtils;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
 import java.util.List;
 
@@ -55,8 +57,16 @@
     /**
      * @hide
      */
-    @StringDef({FORMAT_SLICE, FORMAT_TEXT, FORMAT_IMAGE, FORMAT_ACTION, FORMAT_COLOR,
-            FORMAT_TIMESTAMP, FORMAT_REMOTE_INPUT})
+    @StringDef(prefix = { "FORMAT_" }, value = {
+            FORMAT_SLICE,
+            FORMAT_TEXT,
+            FORMAT_IMAGE,
+            FORMAT_ACTION,
+            FORMAT_COLOR,
+            FORMAT_TIMESTAMP,
+            FORMAT_REMOTE_INPUT,
+    })
+    @Retention(RetentionPolicy.SOURCE)
     public @interface SliceType {}
 
     /**
diff --git a/core/java/android/app/timezone/RulesManager.java b/core/java/android/app/timezone/RulesManager.java
index ad9b698..417e7d2 100644
--- a/core/java/android/app/timezone/RulesManager.java
+++ b/core/java/android/app/timezone/RulesManager.java
@@ -105,9 +105,9 @@
      */
     public RulesState getRulesState() {
         try {
-            logDebug("sIRulesManager.getRulesState()");
+            logDebug("mIRulesManager.getRulesState()");
             RulesState rulesState = mIRulesManager.getRulesState();
-            logDebug("sIRulesManager.getRulesState() returned " + rulesState);
+            logDebug("mIRulesManager.getRulesState() returned " + rulesState);
             return rulesState;
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -131,7 +131,7 @@
 
         ICallback iCallback = new CallbackWrapper(mContext, callback);
         try {
-            logDebug("sIRulesManager.requestInstall()");
+            logDebug("mIRulesManager.requestInstall()");
             return mIRulesManager.requestInstall(distroFileDescriptor, checkToken, iCallback);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -151,7 +151,7 @@
     public int requestUninstall(byte[] checkToken, Callback callback) {
         ICallback iCallback = new CallbackWrapper(mContext, callback);
         try {
-            logDebug("sIRulesManager.requestUninstall()");
+            logDebug("mIRulesManager.requestUninstall()");
             return mIRulesManager.requestUninstall(checkToken, iCallback);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -196,7 +196,7 @@
      */
     public void requestNothing(byte[] checkToken, boolean succeeded) {
         try {
-            logDebug("sIRulesManager.requestNothing() with token=" + Arrays.toString(checkToken));
+            logDebug("mIRulesManager.requestNothing() with token=" + Arrays.toString(checkToken));
             mIRulesManager.requestNothing(checkToken, succeeded);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
diff --git a/core/java/android/appwidget/AppWidgetManagerInternal.java b/core/java/android/appwidget/AppWidgetManagerInternal.java
new file mode 100644
index 0000000..7ab3d8b
--- /dev/null
+++ b/core/java/android/appwidget/AppWidgetManagerInternal.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.appwidget;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.ArraySet;
+
+import java.util.Set;
+
+/**
+ * App widget manager local system service interface.
+ *
+ * @hide Only for use within the system server.
+ */
+public abstract class AppWidgetManagerInternal {
+
+    /**
+     * Gets the packages from which the uid hosts widgets.
+     *
+     * @param uid The potential host UID.
+     * @return Whether the UID hosts widgets from the package.
+     */
+    public abstract @Nullable ArraySet<String> getHostedWidgetPackages(int uid);
+}
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java b/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java
index 55c3a73..73a2e74 100644
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java
@@ -71,7 +71,7 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(mSyncHandle);
-        dest.writeLong(mTxPower);
+        dest.writeInt(mTxPower);
         dest.writeInt(mRssi);
         dest.writeInt(mDataStatus);
         if (mData != null) {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 9800ab00..a474330 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2913,7 +2913,7 @@
             @Nullable String profileFile, @Nullable Bundle arguments);
 
     /** @hide */
-    @StringDef({
+    @StringDef(suffix = { "_SERVICE" }, value = {
             POWER_SERVICE,
             WINDOW_SERVICE,
             LAYOUT_INFLATER_SERVICE,
@@ -2947,7 +2947,7 @@
             //@hide: LOWPAN_SERVICE,
             //@hide: WIFI_RTT_SERVICE,
             //@hide: ETHERNET_SERVICE,
-            WIFI_RTT_SERVICE,
+            WIFI_RTT_RANGING_SERVICE,
             NSD_SERVICE,
             AUDIO_SERVICE,
             FINGERPRINT_SERVICE,
@@ -3496,7 +3496,7 @@
      * @see android.net.wifi.rtt.WifiRttManager
      * @hide
      */
-    public static final String WIFI_RTT2_SERVICE = "rttmanager2";
+    public static final String WIFI_RTT_RANGING_SERVICE = "rttmanager2";
 
     /**
      * Use with {@link #getSystemService} to retrieve a {@link
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index 551d53b..21bd7f0 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -17,6 +17,7 @@
 package android.content.pm;
 
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -150,6 +151,7 @@
      *
      * @hide
      */
+    @TestApi
     public static final int PROTECTION_FLAG_VENDOR_PRIVILEGED = 0x8000;
 
     /**
diff --git a/core/java/android/hardware/HardwareBuffer.java b/core/java/android/hardware/HardwareBuffer.java
index 7049628..b111ad3 100644
--- a/core/java/android/hardware/HardwareBuffer.java
+++ b/core/java/android/hardware/HardwareBuffer.java
@@ -17,6 +17,7 @@
 package android.hardware;
 
 import android.annotation.IntDef;
+import android.annotation.LongDef;
 import android.annotation.NonNull;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -70,7 +71,7 @@
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef(flag = true, value = {USAGE_CPU_READ_RARELY, USAGE_CPU_READ_OFTEN,
+    @LongDef(flag = true, value = {USAGE_CPU_READ_RARELY, USAGE_CPU_READ_OFTEN,
             USAGE_CPU_WRITE_RARELY, USAGE_CPU_WRITE_OFTEN, USAGE_GPU_SAMPLED_IMAGE,
             USAGE_GPU_COLOR_OUTPUT, USAGE_PROTECTED_CONTENT, USAGE_VIDEO_ENCODE,
             USAGE_GPU_DATA_BUFFER, USAGE_SENSOR_DIRECT_DATA})
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 223ed73..02b1c65 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -392,7 +392,7 @@
                 mWindow.setToken(token);
             }
         }
-        
+
         /**
          * {@inheritDoc}
          *
@@ -1064,7 +1064,89 @@
         }
         return mInputConnection;
     }
-    
+
+    /**
+     * Force switch to a new input method component. This can only be called
+     * from an application or a service which has a token of the currently active input method.
+     * @param id The unique identifier for the new input method to be switched to.
+     */
+    public void setInputMethod(String id) {
+        mImm.setInputMethodInternal(mToken, id);
+    }
+
+    /**
+     * Force switch to a new input method and subtype. This can only be called
+     * from an application or a service which has a token of the currently active input method.
+     * @param id The unique identifier for the new input method to be switched to.
+     * @param subtype The new subtype of the new input method to be switched to.
+     */
+    public void setInputMethodAndSubtype(String id, InputMethodSubtype subtype) {
+        mImm.setInputMethodAndSubtypeInternal(mToken, id, subtype);
+    }
+
+    /**
+     * Close/hide the input method's soft input area, so the user no longer
+     * sees it or can interact with it.  This can only be called
+     * from the currently active input method, as validated by the given token.
+     *
+     * @param flags Provides additional operating flags.  Currently may be
+     * 0 or have the {@link InputMethodManager#HIDE_IMPLICIT_ONLY},
+     * {@link InputMethodManager#HIDE_NOT_ALWAYS} bit set.
+     */
+    public void hideSoftInputFromInputMethod(int flags) {
+        mImm.hideSoftInputFromInputMethodInternal(mToken, flags);
+    }
+
+    /**
+     * Show the input method's soft input area, so the user
+     * sees the input method window and can interact with it.
+     * This can only be called from the currently active input method,
+     * as validated by the given token.
+     *
+     * @param flags Provides additional operating flags.  Currently may be
+     * 0 or have the {@link InputMethodManager#SHOW_IMPLICIT} or
+     * {@link InputMethodManager#SHOW_FORCED} bit set.
+     */
+    public void showSoftInputFromInputMethod(int flags) {
+        mImm.showSoftInputFromInputMethodInternal(mToken, flags);
+    }
+
+    /**
+     * Force switch to the last used input method and subtype. If the last input method didn't have
+     * any subtypes, the framework will simply switch to the last input method with no subtype
+     * specified.
+     * @return true if the current input method and subtype was successfully switched to the last
+     * used input method and subtype.
+     */
+    public boolean switchToLastInputMethod() {
+        return mImm.switchToLastInputMethodInternal(mToken);
+    }
+
+    /**
+     * Force switch to the next input method and subtype. If there is no IME enabled except
+     * current IME and subtype, do nothing.
+     * @param onlyCurrentIme if true, the framework will find the next subtype which
+     * belongs to the current IME
+     * @return true if the current input method and subtype was successfully switched to the next
+     * input method and subtype.
+     */
+    public boolean switchToNextInputMethod(boolean onlyCurrentIme) {
+        return mImm.switchToNextInputMethodInternal(mToken, onlyCurrentIme);
+    }
+
+    /**
+     * Returns true if the current IME needs to offer the users ways to switch to a next input
+     * method (e.g. a globe key.).
+     * When an IME sets supportsSwitchingToNextInputMethod and this method returns true,
+     * the IME has to offer ways to to invoke {@link #switchToNextInputMethod} accordingly.
+     * <p> Note that the system determines the most appropriate next input method
+     * and subtype in order to provide the consistent user experience in switching
+     * between IMEs and subtypes.
+     */
+    public boolean shouldOfferSwitchingToNextInputMethod() {
+        return mImm.shouldOfferSwitchingToNextInputMethodInternal(mToken);
+    }
+
     public boolean getCurrentInputStarted() {
         return mInputStarted;
     }
diff --git a/core/java/android/net/metrics/DefaultNetworkEvent.java b/core/java/android/net/metrics/DefaultNetworkEvent.java
index 8ff8e4f..6f383b4 100644
--- a/core/java/android/net/metrics/DefaultNetworkEvent.java
+++ b/core/java/android/net/metrics/DefaultNetworkEvent.java
@@ -74,7 +74,7 @@
             j.add("final_score=" + finalScore);
         }
         j.add(String.format("duration=%.0fs", durationMs / 1000.0));
-        j.add(String.format("validation=%4.1f%%", (validatedMs * 100.0) / durationMs));
+        j.add(String.format("validation=%04.1f%%", (validatedMs * 100.0) / durationMs));
         return j.toString();
     }
 
diff --git a/core/java/android/security/recoverablekeystore/RecoverableKeyGenerator.java b/core/java/android/security/recoverablekeystore/RecoverableKeyGenerator.java
new file mode 100644
index 0000000..4125f0ba
--- /dev/null
+++ b/core/java/android/security/recoverablekeystore/RecoverableKeyGenerator.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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.recoverablekeystore;
+
+import android.security.keystore.AndroidKeyStoreSecretKey;
+import android.security.keystore.KeyProperties;
+import android.security.keystore.KeyProtection;
+import android.util.Log;
+
+import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableEntryException;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import javax.security.auth.DestroyFailedException;
+
+/**
+ * Generates keys and stores them both in AndroidKeyStore and on disk, in wrapped form.
+ *
+ * <p>Generates 256-bit AES keys, which can be used for encrypt / decrypt with AES/GCM/NoPadding.
+ * They are synced to disk wrapped by a platform key. This allows them to be exported to a remote
+ * service.
+ *
+ * @hide
+ */
+public class RecoverableKeyGenerator {
+    private static final String TAG = "RecoverableKeyGenerator";
+    private static final String KEY_GENERATOR_ALGORITHM = "AES";
+    private static final int KEY_SIZE_BITS = 256;
+
+    /**
+     * A new {@link RecoverableKeyGenerator} instance.
+     *
+     * @param platformKey Secret key used to wrap generated keys before persisting to disk.
+     * @param recoverableKeyStorage Class that manages persisting wrapped keys to disk.
+     * @throws NoSuchAlgorithmException if "AES" key generation or "AES/GCM/NoPadding" cipher is
+     *     unavailable. Should never happen.
+     *
+     * @hide
+     */
+    public static RecoverableKeyGenerator newInstance(
+            AndroidKeyStoreSecretKey platformKey, RecoverableKeyStorage recoverableKeyStorage)
+            throws NoSuchAlgorithmException {
+        // NB: This cannot use AndroidKeyStore as the provider, as we need access to the raw key
+        // material, so that it can be synced to disk in encrypted form.
+        KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_GENERATOR_ALGORITHM);
+        return new RecoverableKeyGenerator(keyGenerator, platformKey, recoverableKeyStorage);
+    }
+
+    private final KeyGenerator mKeyGenerator;
+    private final RecoverableKeyStorage mRecoverableKeyStorage;
+    private final AndroidKeyStoreSecretKey mPlatformKey;
+
+    private RecoverableKeyGenerator(
+            KeyGenerator keyGenerator,
+            AndroidKeyStoreSecretKey platformKey,
+            RecoverableKeyStorage recoverableKeyStorage) {
+        mKeyGenerator = keyGenerator;
+        mRecoverableKeyStorage = recoverableKeyStorage;
+        mPlatformKey = platformKey;
+    }
+
+    /**
+     * Generates a 256-bit AES key with the given alias.
+     *
+     * <p>Stores in the AndroidKeyStore, as well as persisting in wrapped form to disk. It is
+     * persisted to disk so that it can be synced remotely, and then recovered on another device.
+     * The generated key allows encrypt/decrypt only using AES/GCM/NoPadding.
+     *
+     * <p>The key handle returned to the caller is a reference to the AndroidKeyStore key,
+     * meaning that the caller is never able to access the raw, unencrypted key.
+     *
+     * @param alias The alias by which the key will be known in AndroidKeyStore.
+     * @throws InvalidKeyException if the platform key cannot be used to wrap keys.
+     * @throws IOException if there was an issue writing the wrapped key to the wrapped key store.
+     * @throws UnrecoverableEntryException if could not retrieve key after putting it in
+     *     AndroidKeyStore. This should not happen.
+     * @return A handle to the AndroidKeyStore key.
+     *
+     * @hide
+     */
+    public SecretKey generateAndStoreKey(String alias) throws KeyStoreException,
+            InvalidKeyException, IOException, UnrecoverableEntryException {
+        mKeyGenerator.init(KEY_SIZE_BITS);
+        SecretKey key = mKeyGenerator.generateKey();
+
+        mRecoverableKeyStorage.importIntoAndroidKeyStore(
+                alias,
+                key,
+                new KeyProtection.Builder(
+                        KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
+                        .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+                        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+                        .build());
+        WrappedKey wrappedKey = WrappedKey.fromSecretKey(mPlatformKey, key);
+
+        try {
+            // Keep raw key material in memory for minimum possible time.
+            key.destroy();
+        } catch (DestroyFailedException e) {
+            Log.w(TAG, "Could not destroy SecretKey.");
+        }
+
+        mRecoverableKeyStorage.persistToDisk(alias, wrappedKey);
+
+        try {
+            // Reload from the keystore, so that the caller is only provided with the handle of the
+            // key, not the raw key material.
+            return mRecoverableKeyStorage.loadFromAndroidKeyStore(alias);
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException(
+                    "Impossible: NoSuchAlgorithmException when attempting to retrieve a key "
+                            + "that has only just been stored in AndroidKeyStore.", e);
+        }
+    }
+}
diff --git a/core/java/android/security/recoverablekeystore/RecoverableKeyStorage.java b/core/java/android/security/recoverablekeystore/RecoverableKeyStorage.java
new file mode 100644
index 0000000..c239e00
--- /dev/null
+++ b/core/java/android/security/recoverablekeystore/RecoverableKeyStorage.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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.recoverablekeystore;
+
+import android.security.keystore.KeyProtection;
+
+import java.io.IOException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableEntryException;
+
+import javax.crypto.SecretKey;
+
+/**
+ * Stores wrapped keys to disk, so they can be synced on the next screen unlock event.
+ *
+ * @hide
+ */
+public interface RecoverableKeyStorage {
+
+    /**
+     * Writes {@code wrappedKey} to disk, keyed by the application's uid and the {@code alias}.
+     *
+     * @throws IOException if an error occurred writing to disk.
+     *
+     * @hide
+     */
+    void persistToDisk(String alias, WrappedKey wrappedKey) throws IOException;
+
+    /**
+     * Imports {@code key} into AndroidKeyStore, keyed by the application's uid and
+     * the {@code alias}.
+     *
+     * @param alias The alias of the key.
+     * @param key The key.
+     * @param keyProtection Protection params denoting what the key can be used for. (e.g., what
+     *                      Cipher modes, whether for encrpyt/decrypt or signing, etc.)
+     * @throws KeyStoreException if an error occurred loading the key into the AndroidKeyStore.
+     *
+     * @hide
+     */
+    void importIntoAndroidKeyStore(String alias, SecretKey key, KeyProtection keyProtection) throws
+            KeyStoreException;
+
+    /**
+     * Loads a key handle from AndroidKeyStore.
+     *
+     * @param alias Alias of the key to load.
+     * @return The key handle.
+     * @throws KeyStoreException if an error occurred loading the key from AndroidKeyStore.
+     *
+     * @hide
+     */
+    SecretKey loadFromAndroidKeyStore(String alias) throws KeyStoreException,
+            NoSuchAlgorithmException,
+            UnrecoverableEntryException;
+}
diff --git a/core/java/android/security/recoverablekeystore/RecoverableKeyStorageImpl.java b/core/java/android/security/recoverablekeystore/RecoverableKeyStorageImpl.java
new file mode 100644
index 0000000..b9926dd
--- /dev/null
+++ b/core/java/android/security/recoverablekeystore/RecoverableKeyStorageImpl.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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.recoverablekeystore;
+
+import android.security.keystore.KeyProtection;
+
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableEntryException;
+import java.security.cert.CertificateException;
+
+import javax.crypto.SecretKey;
+
+/**
+ * Implementation of {@link RecoverableKeyStorage}.
+ *
+ * <p>Persists wrapped keys to disk, and loads raw keys into AndroidKeyStore.
+ *
+ * @hide
+ */
+public class RecoverableKeyStorageImpl implements RecoverableKeyStorage {
+    private static final String ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore";
+
+    private final KeyStore mKeyStore;
+
+    /**
+     * A new instance.
+     *
+     * @throws KeyStoreException if unable to load AndroidKeyStore.
+     *
+     * @hide
+     */
+    public static RecoverableKeyStorageImpl newInstance() throws KeyStoreException {
+        KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_PROVIDER);
+        try {
+            keyStore.load(/*param=*/ null);
+        } catch (CertificateException | IOException | NoSuchAlgorithmException e) {
+            // Should never happen.
+            throw new KeyStoreException("Unable to load keystore.", e);
+        }
+        return new RecoverableKeyStorageImpl(keyStore);
+    }
+
+    private RecoverableKeyStorageImpl(KeyStore keyStore) {
+        mKeyStore = keyStore;
+    }
+
+    /**
+     * Writes {@code wrappedKey} to disk, keyed by the application's uid and the {@code alias}.
+     *
+     * @throws IOException if an error occurred writing to disk.
+     *
+     * @hide
+     */
+    @Override
+    public void persistToDisk(String alias, WrappedKey wrappedKey) throws IOException {
+        // TODO(robertberry) Add implementation.
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Imports {@code key} into AndroidKeyStore, keyed by the application's uid and the
+     * {@code alias}.
+     *
+     * @param alias The alias of the key.
+     * @param key The key.
+     * @param keyProtection Protection params denoting what the key can be used for. (e.g., what
+     *                      Cipher modes, whether for encrpyt/decrypt or signing, etc.)
+     * @throws KeyStoreException if an error occurred loading the key into the AndroidKeyStore.
+     *
+     * @hide
+     */
+    @Override
+    public void importIntoAndroidKeyStore(String alias, SecretKey key, KeyProtection keyProtection)
+            throws KeyStoreException {
+        mKeyStore.setEntry(alias, new KeyStore.SecretKeyEntry(key), keyProtection);
+    }
+
+    /**
+     * Loads a key handle from AndroidKeyStore.
+     *
+     * @param alias Alias of the key to load.
+     * @return The key handle.
+     * @throws KeyStoreException if an error occurred loading the key from AndroidKeyStore.
+     *
+     * @hide
+     */
+    @Override
+    public SecretKey loadFromAndroidKeyStore(String alias)
+            throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableEntryException {
+        return ((KeyStore.SecretKeyEntry) mKeyStore.getEntry(alias, /*protParam=*/ null))
+                .getSecretKey();
+    }
+}
diff --git a/core/java/android/security/recoverablekeystore/WrappedKey.java b/core/java/android/security/recoverablekeystore/WrappedKey.java
new file mode 100644
index 0000000..51665ae
--- /dev/null
+++ b/core/java/android/security/recoverablekeystore/WrappedKey.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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.recoverablekeystore;
+
+import java.security.InvalidKeyException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+
+/**
+ * A {@link javax.crypto.SecretKey} wrapped with AES/GCM/NoPadding.
+ *
+ * @hide
+ */
+public class WrappedKey {
+    private static final String KEY_WRAP_CIPHER_ALGORITHM = "AES/GCM/NoPadding";
+
+    private final byte[] mNonce;
+    private final byte[] mKeyMaterial;
+
+    /**
+     * Returns a wrapped form of {@code key}, using {@code wrappingKey} to encrypt the key material.
+     *
+     * @throws InvalidKeyException if {@code wrappingKey} cannot be used to encrypt {@code key}, or
+     *     if {@code key} does not expose its key material. See
+     *     {@link android.security.keystore.AndroidKeyStoreKey} for an example of a key that does
+     *     not expose its key material.
+     */
+    public static WrappedKey fromSecretKey(
+            SecretKey wrappingKey, SecretKey key) throws InvalidKeyException, KeyStoreException {
+        if (key.getEncoded() == null) {
+            throw new InvalidKeyException(
+                    "key does not expose encoded material. It cannot be wrapped.");
+        }
+
+        Cipher cipher;
+        try {
+            cipher = Cipher.getInstance(KEY_WRAP_CIPHER_ALGORITHM);
+        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
+            throw new RuntimeException(
+                    "Android does not support AES/GCM/NoPadding. This should never happen.");
+        }
+
+        cipher.init(Cipher.WRAP_MODE, wrappingKey);
+        byte[] encryptedKeyMaterial;
+        try {
+            encryptedKeyMaterial = cipher.wrap(key);
+        } catch (IllegalBlockSizeException e) {
+            Throwable cause = e.getCause();
+            if (cause instanceof KeyStoreException) {
+                // If AndroidKeyStore encounters any error here, it throws IllegalBlockSizeException
+                // with KeyStoreException as the cause. This is due to there being no better option
+                // here, as the Cipher#wrap only checked throws InvalidKeyException or
+                // IllegalBlockSizeException. If this is the case, we want to propagate it to the
+                // caller, so rethrow the cause.
+                throw (KeyStoreException) cause;
+            } else {
+                throw new RuntimeException(
+                        "IllegalBlockSizeException should not be thrown by AES/GCM/NoPadding mode.",
+                        e);
+            }
+        }
+
+        return new WrappedKey(/*mNonce=*/ cipher.getIV(), /*mKeyMaterial=*/ encryptedKeyMaterial);
+    }
+
+    /**
+     * A new instance.
+     *
+     * @param nonce The nonce with which the key material was encrypted.
+     * @param keyMaterial The encrypted bytes of the key material.
+     *
+     * @hide
+     */
+    public WrappedKey(byte[] nonce, byte[] keyMaterial) {
+        mNonce = nonce;
+        mKeyMaterial = keyMaterial;
+    }
+
+    /**
+     * Returns the nonce with which the key material was encrypted.
+     *
+     * @hide
+     */
+    public byte[] getNonce() {
+        return mNonce;
+    }
+
+    /**
+     * Returns the encrypted key material.
+     *
+     * @hide
+     */
+    public byte[] getKeyMaterial() {
+        return mKeyMaterial;
+    }
+}
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index 1afa8b3..97fdcef 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -445,7 +445,7 @@
  *
  * <p>The {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)} method is called
  * without the user content. The Android system strips some properties of the
- * {@link android.app.assist.AssistStructure.ViewNode view nodes} passed to these calls, but not all
+ * {@link android.app.assist.AssistStructure.ViewNode view nodes} passed to this call, but not all
  * of them. For example, the data provided in the {@link android.view.ViewStructure.HtmlInfo}
  * objects set by {@link android.webkit.WebView} is never stripped out.
  *
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java
index 3a84224..ddc92f6 100644
--- a/core/java/android/service/autofill/FillRequest.java
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -127,12 +127,15 @@
     }
 
     /**
-     * Gets the extra client state returned from the last {@link
-     * AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)
-     * fill request}, so the service can use it for state management.
+     * Gets the latest client state bundle set by the service in a
+     * {@link FillResponse.Builder#setClientState(Bundle) fill response}.
      *
-     * <p>Once a {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)
-     * save request} is made, the client state is cleared.
+     * <p><b>Note:</b> Prior to Android {@link android.os.Build.VERSION_CODES#P}, only client state
+     * bundles set by {@link FillResponse.Builder#setClientState(Bundle)} were considered. On
+     * Android {@link android.os.Build.VERSION_CODES#P} and higher, bundles set in the result of
+     * an authenticated request through the
+     * {@link android.view.autofill.AutofillManager#EXTRA_CLIENT_STATE} extra are
+     * also considered (and take precedence when set).
      *
      * @return The client state.
      */
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index 06d2b07..04db698 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -49,14 +49,16 @@
 public final class FillResponse implements Parcelable {
 
     /**
-     * Must be set in the last response to generate
-     * {@link FillEventHistory.Event#TYPE_CONTEXT_COMMITTED} events.
+     * Flag used to generate {@link FillEventHistory.Event events} of type
+     * {@link FillEventHistory.Event#TYPE_CONTEXT_COMMITTED}&mdash;if this flag is not passed to
+     * {@link Builder#setFlags(int)}, these events are not generated.
      */
     public static final int FLAG_TRACK_CONTEXT_COMMITED = 0x1;
 
     /**
-     * Used in conjunction to {@link FillResponse.Builder#disableAutofill(long)} to disable autofill
-     * only for the activiy associated with the {@link FillResponse}, instead of the whole app.
+     * Flag used to change the behavior of {@link FillResponse.Builder#disableAutofill(long)}&mdash;
+     * when this flag is passed to {@link Builder#setFlags(int)}, autofill is disabled only for the
+     * activiy that generated the {@link FillRequest}, not the whole app.
      */
     public static final int FLAG_DISABLE_ACTIVITY_ONLY = 0x2;
 
@@ -329,19 +331,16 @@
         }
 
         /**
-         * Sets a {@link Bundle state} that will be passed to subsequent APIs that
-         * manipulate this response. For example, they are passed to subsequent
-         * calls to {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal,
-         * FillCallback)} and {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)}.
-         * You can use this to store intermediate state that is persistent across multiple
-         * fill requests and the subsequent save request.
+         * Sets a bundle with state that is passed to subsequent APIs that manipulate this response.
+         *
+         * <p>You can use this bundle to store intermediate state that is passed to subsequent calls
+         * to {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal,
+         * FillCallback)} and {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)}, and
+         * you can also retrieve it by calling {@link FillEventHistory.Event#getClientState()}.
          *
          * <p>If this method is called on multiple {@link FillResponse} objects for the same
          * screen, just the latest bundle is passed back to the service.
          *
-         * <p>Once a {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)
-         * save request} is made the client state is cleared.
-         *
          * @param clientState The custom client state.
          * @return This builder.
          */
diff --git a/core/java/android/service/autofill/SaveRequest.java b/core/java/android/service/autofill/SaveRequest.java
index f53967b..4f85e6b 100644
--- a/core/java/android/service/autofill/SaveRequest.java
+++ b/core/java/android/service/autofill/SaveRequest.java
@@ -59,10 +59,11 @@
     }
 
     /**
-     * Gets the latest client state extra returned from the service.
+     * Gets the latest client state bundle set by the service in a
+     * {@link FillResponse.Builder#setClientState(Bundle) fill response}.
      *
      * <p><b>Note:</b> Prior to Android {@link android.os.Build.VERSION_CODES#P}, only client state
-     * bundles set by {@link FillResponse.Builder#setClientState(Bundle)} where considered. On
+     * bundles set by {@link FillResponse.Builder#setClientState(Bundle)} were considered. On
      * Android {@link android.os.Build.VERSION_CODES#P} and higher, bundles set in the result of
      * an authenticated request through the
      * {@link android.view.autofill.AutofillManager#EXTRA_CLIENT_STATE} extra are
diff --git a/core/java/android/service/autofill/Validators.java b/core/java/android/service/autofill/Validators.java
index 1c83868..0f1ba98 100644
--- a/core/java/android/service/autofill/Validators.java
+++ b/core/java/android/service/autofill/Validators.java
@@ -33,6 +33,8 @@
     /**
      * Creates a validator that is only valid if all {@code validators} are valid.
      *
+     * <p>Used to represent an {@code AND} boolean operation in a chain of validators.
+     *
      * @throws IllegalArgumentException if any element of {@code validators} is an instance of a
      * class that is not provided by the Android System.
      */
@@ -44,6 +46,8 @@
     /**
      * Creates a validator that is valid if any of the {@code validators} is valid.
      *
+     * <p>Used to represent an {@code OR} boolean operation in a chain of validators.
+     *
      * @throws IllegalArgumentException if any element of {@code validators} is an instance of a
      * class that is not provided by the Android System.
      */
@@ -53,7 +57,9 @@
     }
 
     /**
-     * Creates a validator that is valid only if {@code validator} is not.
+     * Creates a validator that is valid when {@code validator} is not, and vice versa.
+     *
+     * <p>Used to represent a {@code NOT} boolean operation in a chain of validators.
      *
      * @throws IllegalArgumentException if {@code validator} is an instance of a class that is not
      * provided by the Android System.
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 80785fd..54b48b6 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -43,6 +43,7 @@
         DEFAULT_FLAGS.put("settings_app_info_v2", "false");
         DEFAULT_FLAGS.put("settings_connected_device_v2", "false");
         DEFAULT_FLAGS.put("settings_battery_v2", "false");
+        DEFAULT_FLAGS.put("settings_battery_display_app_list", "false");
     }
 
     /**
diff --git a/core/java/android/view/FrameInfo.java b/core/java/android/view/FrameInfo.java
index c79547c..6c5e048 100644
--- a/core/java/android/view/FrameInfo.java
+++ b/core/java/android/view/FrameInfo.java
@@ -16,7 +16,7 @@
 
 package android.view;
 
-import android.annotation.IntDef;
+import android.annotation.LongDef;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -48,7 +48,7 @@
     // Is this the first-draw following a window layout?
     public static final long FLAG_WINDOW_LAYOUT_CHANGED = 1;
 
-    @IntDef(flag = true, value = {
+    @LongDef(flag = true, value = {
             FLAG_WINDOW_LAYOUT_CHANGED })
     @Retention(RetentionPolicy.SOURCE)
     public @interface FrameInfoFlags {}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 420a1bb..8a7b441 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -18,11 +18,18 @@
 
 import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
+import static android.graphics.Matrix.MSCALE_X;
+import static android.graphics.Matrix.MSCALE_Y;
+import static android.graphics.Matrix.MSKEW_X;
+import static android.graphics.Matrix.MSKEW_Y;
+import static android.graphics.Matrix.MTRANS_X;
+import static android.graphics.Matrix.MTRANS_Y;
 
 import android.annotation.Size;
 import android.graphics.Bitmap;
 import android.graphics.GraphicBuffer;
 import android.graphics.PixelFormat;
+import android.graphics.Matrix;
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.os.IBinder;
@@ -862,6 +869,22 @@
         }
     }
 
+    /**
+     * Sets the transform and position of a {@link SurfaceControl} from a 3x3 transformation matrix.
+     *
+     * @param matrix The matrix to apply.
+     * @param float9 An array of 9 floats to be used to extract the values from the matrix.
+     */
+    public void setMatrix(Matrix matrix, float[] float9) {
+        checkNotReleased();
+        matrix.getValues(float9);
+        synchronized (SurfaceControl.class) {
+            sGlobalTransaction.setMatrix(this, float9[MSCALE_X], float9[MSKEW_Y],
+                    float9[MSKEW_X], float9[MSCALE_Y]);
+            sGlobalTransaction.setPosition(this, float9[MTRANS_X], float9[MTRANS_Y]);
+        }
+    }
+
     public void setWindowCrop(Rect crop) {
         checkNotReleased();
         synchronized (SurfaceControl.class) {
@@ -1348,6 +1371,14 @@
             return this;
         }
 
+        public Transaction setMatrix(SurfaceControl sc, Matrix matrix, float[] float9) {
+            matrix.getValues(float9);
+            setMatrix(sc, float9[MSCALE_X], float9[MSKEW_Y],
+                    float9[MSKEW_X], float9[MSCALE_Y]);
+            setPosition(sc, float9[MTRANS_X], float9[MTRANS_Y]);
+            return this;
+        }
+
         public Transaction setWindowCrop(SurfaceControl sc, Rect crop) {
             sc.checkNotReleased();
             if (crop != null) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 0bae36bf4..6d4998b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -7907,6 +7907,7 @@
             if (!registered) {
                 mAttachInfo.mAccessibilityWindowId =
                         mAccessibilityManager.addAccessibilityInteractionConnection(mWindow,
+                                mContext.getPackageName(),
                                 new AccessibilityInteractionConnection(ViewRootImpl.this));
             }
         }
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 7c2c12f..500701d 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -20,6 +20,7 @@
 
 import android.Manifest.permission;
 import android.annotation.IntDef;
+import android.annotation.LongDef;
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
@@ -1270,7 +1271,7 @@
 
         /** @hide */
         @Retention(RetentionPolicy.SOURCE)
-        @IntDef(
+        @LongDef(
             flag = true,
             value = {
                     LayoutParams.FLAG2_LAYOUT_IN_DISPLAY_CUTOUT_AREA,
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index d890f32..e146555 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -29,6 +29,7 @@
 import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -213,7 +214,7 @@
      *
      * @param connectionId The id of a connection for interacting with the system.
      * @param accessibilityWindowId A unique window id. Use
-     *     {@link android.view.accessibility.AccessibilityNodeInfo#ACTIVE_WINDOW_ID}
+     *     {@link android.view.accessibility.AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
      *     to query the currently active window.
      * @return The {@link AccessibilityWindowInfo}.
      */
@@ -299,7 +300,7 @@
      *
      * @param connectionId The id of a connection for interacting with the system.
      * @param accessibilityWindowId A unique window id. Use
-     *     {@link android.view.accessibility.AccessibilityNodeInfo#ACTIVE_WINDOW_ID}
+     *     {@link android.view.accessibility.AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
      *     to query the currently active window.
      * @param accessibilityNodeId A unique view id or virtual descendant id from
      *     where to start the search. Use
@@ -335,18 +336,19 @@
                 }
                 final int interactionId = mInteractionIdCounter.getAndIncrement();
                 final long identityToken = Binder.clearCallingIdentity();
-                final boolean success;
+                final String[] packageNames;
                 try {
-                    success = connection.findAccessibilityNodeInfoByAccessibilityId(
+                    packageNames = connection.findAccessibilityNodeInfoByAccessibilityId(
                             accessibilityWindowId, accessibilityNodeId, interactionId, this,
                             prefetchFlags, Thread.currentThread().getId(), arguments);
                 } finally {
                     Binder.restoreCallingIdentity(identityToken);
                 }
-                if (success) {
+                if (packageNames != null) {
                     List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
                             interactionId);
-                    finalizeAndCacheAccessibilityNodeInfos(infos, connectionId, bypassCache);
+                    finalizeAndCacheAccessibilityNodeInfos(infos, connectionId,
+                            bypassCache, packageNames);
                     if (infos != null && !infos.isEmpty()) {
                         for (int i = 1; i < infos.size(); i++) {
                             infos.get(i).recycle();
@@ -373,7 +375,7 @@
      *
      * @param connectionId The id of a connection for interacting with the system.
      * @param accessibilityWindowId A unique window id. Use
-     *     {@link android.view.accessibility.AccessibilityNodeInfo#ACTIVE_WINDOW_ID}
+     *     {@link android.view.accessibility.AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
      *     to query the currently active window.
      * @param accessibilityNodeId A unique view id or virtual descendant id from
      *     where to start the search. Use
@@ -389,20 +391,21 @@
             if (connection != null) {
                 final int interactionId = mInteractionIdCounter.getAndIncrement();
                 final long identityToken = Binder.clearCallingIdentity();
-                final boolean success;
+                final String[] packageNames;
                 try {
-                    success = connection.findAccessibilityNodeInfosByViewId(
+                    packageNames = connection.findAccessibilityNodeInfosByViewId(
                             accessibilityWindowId, accessibilityNodeId, viewId, interactionId, this,
                             Thread.currentThread().getId());
                 } finally {
                     Binder.restoreCallingIdentity(identityToken);
                 }
 
-                if (success) {
+                if (packageNames != null) {
                     List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
                             interactionId);
                     if (infos != null) {
-                        finalizeAndCacheAccessibilityNodeInfos(infos, connectionId, false);
+                        finalizeAndCacheAccessibilityNodeInfos(infos, connectionId,
+                                false, packageNames);
                         return infos;
                     }
                 }
@@ -426,7 +429,7 @@
      *
      * @param connectionId The id of a connection for interacting with the system.
      * @param accessibilityWindowId A unique window id. Use
-     *     {@link android.view.accessibility.AccessibilityNodeInfo#ACTIVE_WINDOW_ID}
+     *     {@link android.view.accessibility.AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
      *     to query the currently active window.
      * @param accessibilityNodeId A unique view id or virtual descendant id from
      *     where to start the search. Use
@@ -442,20 +445,21 @@
             if (connection != null) {
                 final int interactionId = mInteractionIdCounter.getAndIncrement();
                 final long identityToken = Binder.clearCallingIdentity();
-                final boolean success;
+                final String[] packageNames;
                 try {
-                    success = connection.findAccessibilityNodeInfosByText(
+                    packageNames = connection.findAccessibilityNodeInfosByText(
                             accessibilityWindowId, accessibilityNodeId, text, interactionId, this,
                             Thread.currentThread().getId());
                 } finally {
                     Binder.restoreCallingIdentity(identityToken);
                 }
 
-                if (success) {
+                if (packageNames != null) {
                     List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
                             interactionId);
                     if (infos != null) {
-                        finalizeAndCacheAccessibilityNodeInfos(infos, connectionId, false);
+                        finalizeAndCacheAccessibilityNodeInfos(infos, connectionId,
+                                false, packageNames);
                         return infos;
                     }
                 }
@@ -478,7 +482,7 @@
      *
      * @param connectionId The id of a connection for interacting with the system.
      * @param accessibilityWindowId A unique window id. Use
-     *     {@link android.view.accessibility.AccessibilityNodeInfo#ACTIVE_WINDOW_ID}
+     *     {@link android.view.accessibility.AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
      *     to query the currently active window.
      * @param accessibilityNodeId A unique view id or virtual descendant id from
      *     where to start the search. Use
@@ -494,19 +498,19 @@
             if (connection != null) {
                 final int interactionId = mInteractionIdCounter.getAndIncrement();
                 final long identityToken = Binder.clearCallingIdentity();
-                final boolean success;
+                final String[] packageNames;
                 try {
-                    success = connection.findFocus(accessibilityWindowId,
+                    packageNames = connection.findFocus(accessibilityWindowId,
                             accessibilityNodeId, focusType, interactionId, this,
                             Thread.currentThread().getId());
                 } finally {
                     Binder.restoreCallingIdentity(identityToken);
                 }
 
-                if (success) {
+                if (packageNames != null) {
                     AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
                             interactionId);
-                    finalizeAndCacheAccessibilityNodeInfo(info, connectionId, false);
+                    finalizeAndCacheAccessibilityNodeInfo(info, connectionId, false, packageNames);
                     return info;
                 }
             } else {
@@ -527,7 +531,7 @@
      *
      * @param connectionId The id of a connection for interacting with the system.
      * @param accessibilityWindowId A unique window id. Use
-     *     {@link android.view.accessibility.AccessibilityNodeInfo#ACTIVE_WINDOW_ID}
+     *     {@link android.view.accessibility.AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
      *     to query the currently active window.
      * @param accessibilityNodeId A unique view id or virtual descendant id from
      *     where to start the search. Use
@@ -543,19 +547,19 @@
             if (connection != null) {
                 final int interactionId = mInteractionIdCounter.getAndIncrement();
                 final long identityToken = Binder.clearCallingIdentity();
-                final boolean success;
+                final String[] packageNames;
                 try {
-                    success = connection.focusSearch(accessibilityWindowId,
+                    packageNames = connection.focusSearch(accessibilityWindowId,
                             accessibilityNodeId, direction, interactionId, this,
                             Thread.currentThread().getId());
                 } finally {
                     Binder.restoreCallingIdentity(identityToken);
                 }
 
-                if (success) {
+                if (packageNames != null) {
                     AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
                             interactionId);
-                    finalizeAndCacheAccessibilityNodeInfo(info, connectionId, false);
+                    finalizeAndCacheAccessibilityNodeInfo(info, connectionId, false, packageNames);
                     return info;
                 }
             } else {
@@ -574,7 +578,7 @@
      *
      * @param connectionId The id of a connection for interacting with the system.
      * @param accessibilityWindowId A unique window id. Use
-     *     {@link android.view.accessibility.AccessibilityNodeInfo#ACTIVE_WINDOW_ID}
+     *     {@link android.view.accessibility.AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
      *     to query the currently active window.
      * @param accessibilityNodeId A unique view id or virtual descendant id from
      *     where to start the search. Use
@@ -661,7 +665,7 @@
                 int interactionId) {
         synchronized (mInstanceLock) {
             final boolean success = waitForResultTimedLocked(interactionId);
-            List<AccessibilityNodeInfo> result = null;
+            final List<AccessibilityNodeInfo> result;
             if (success) {
                 result = mFindAccessibilityNodeInfosResult;
             } else {
@@ -779,11 +783,19 @@
      * @param connectionId The id of the connection to the system.
      * @param bypassCache Whether or not to bypass the cache. The node is added to the cache if
      *                    this value is {@code false}
+     * @param packageNames The valid package names a node can come from.
      */
     private void finalizeAndCacheAccessibilityNodeInfo(AccessibilityNodeInfo info,
-            int connectionId, boolean bypassCache) {
+            int connectionId, boolean bypassCache, String[] packageNames) {
         if (info != null) {
             info.setConnectionId(connectionId);
+            // Empty array means any package name is Okay
+            if (!ArrayUtils.isEmpty(packageNames)
+                    && !ArrayUtils.contains(packageNames, info.getPackageName().toString())) {
+                // If the node package not one of the valid ones, pick the top one - this
+                // is one of the packages running in the introspected UID.
+                info.setPackageName(packageNames[0]);
+            }
             info.setSealed(true);
             if (!bypassCache) {
                 sAccessibilityCache.add(info);
@@ -798,14 +810,16 @@
      * @param connectionId The id of the connection to the system.
      * @param bypassCache Whether or not to bypass the cache. The nodes are added to the cache if
      *                    this value is {@code false}
+     * @param packageNames The valid package names a node can come from.
      */
     private void finalizeAndCacheAccessibilityNodeInfos(List<AccessibilityNodeInfo> infos,
-            int connectionId, boolean bypassCache) {
+            int connectionId, boolean bypassCache, String[] packageNames) {
         if (infos != null) {
             final int infosCount = infos.size();
             for (int i = 0; i < infosCount; i++) {
                 AccessibilityNodeInfo info = infos.get(i);
-                finalizeAndCacheAccessibilityNodeInfo(info, connectionId, bypassCache);
+                finalizeAndCacheAccessibilityNodeInfo(info, connectionId,
+                        bypassCache, packageNames);
             }
         }
     }
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 35f6acb..b4499d1 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -888,7 +888,7 @@
      * @hide
      */
     public int addAccessibilityInteractionConnection(IWindow windowToken,
-            IAccessibilityInteractionConnection connection) {
+            String packageName, IAccessibilityInteractionConnection connection) {
         final IAccessibilityManager service;
         final int userId;
         synchronized (mLock) {
@@ -899,7 +899,8 @@
             userId = mUserId;
         }
         try {
-            return service.addAccessibilityInteractionConnection(windowToken, connection, userId);
+            return service.addAccessibilityInteractionConnection(windowToken, connection,
+                    packageName, userId);
         } catch (RemoteException re) {
             Log.e(LOG_TAG, "Error while adding an accessibility interaction connection. ", re);
         }
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index faea920..9c2f6bb 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -3695,8 +3695,9 @@
 
         if (DEBUG) {
             builder.append("; sourceNodeId: " + mSourceNodeId);
-            builder.append("; accessibilityViewId: " + getAccessibilityViewId(mSourceNodeId));
-            builder.append("; virtualDescendantId: " + getVirtualDescendantId(mSourceNodeId));
+            builder.append("; windowId: " + mWindowId);
+            builder.append("; accessibilityViewId: ").append(getAccessibilityViewId(mSourceNodeId));
+            builder.append("; virtualDescendantId: ").append(getVirtualDescendantId(mSourceNodeId));
             builder.append("; mParentNodeId: " + mParentNodeId);
             builder.append("; traversalBefore: ").append(mTraversalBefore);
             builder.append("; traversalAfter: ").append(mTraversalAfter);
@@ -3726,8 +3727,8 @@
             builder.append("]");
         }
 
-        builder.append("; boundsInParent: " + mBoundsInParent);
-        builder.append("; boundsInScreen: " + mBoundsInScreen);
+        builder.append("; boundsInParent: ").append(mBoundsInParent);
+        builder.append("; boundsInScreen: ").append(mBoundsInScreen);
 
         builder.append("; packageName: ").append(mPackageName);
         builder.append("; className: ").append(mClassName);
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index 3f499ab..c93e2c1 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -45,7 +45,8 @@
     List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType, int userId);
 
     int addAccessibilityInteractionConnection(IWindow windowToken,
-            in IAccessibilityInteractionConnection connection, int userId);
+            in IAccessibilityInteractionConnection connection,
+            String packageName, int userId);
 
     void removeAccessibilityInteractionConnection(IWindow windowToken);
 
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 4d96733..3cd8d4a 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -24,6 +24,7 @@
 import android.annotation.SystemService;
 import android.content.Context;
 import android.graphics.Rect;
+import android.inputmethodservice.InputMethodService;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -735,7 +736,20 @@
         }
     }
 
+    /**
+     * @deprecated Use {@link InputMethodService#showStatusIcon(int)} instead. This method was
+     * intended for IME developers who should be accessing APIs through the service. APIs in this
+     * class are intended for app developers interacting with the IME.
+     */
+    @Deprecated
     public void showStatusIcon(IBinder imeToken, String packageName, int iconId) {
+        showStatusIconInternal(imeToken, packageName, iconId);
+    }
+
+    /**
+     * @hide
+     */
+    public void showStatusIconInternal(IBinder imeToken, String packageName, int iconId) {
         try {
             mService.updateStatusIcon(imeToken, packageName, iconId);
         } catch (RemoteException e) {
@@ -743,7 +757,20 @@
         }
     }
 
+    /**
+     * @deprecated Use {@link InputMethodService#hideStatusIcon()} instead. This method was
+     * intended for IME developers who should be accessing APIs through the service. APIs in
+     * this class are intended for app developers interacting with the IME.
+     */
+    @Deprecated
     public void hideStatusIcon(IBinder imeToken) {
+        hideStatusIconInternal(imeToken);
+    }
+
+    /**
+     * @hide
+     */
+    public void hideStatusIconInternal(IBinder imeToken) {
         try {
             mService.updateStatusIcon(imeToken, null, 0);
         } catch (RemoteException e) {
@@ -1121,7 +1148,6 @@
         }
     }
 
-
     /**
      * This method toggles the input method window display.
      * If the input window is already displayed, it gets hidden.
@@ -1800,8 +1826,19 @@
      * when it was started, which allows it to perform this operation on
      * itself.
      * @param id The unique identifier for the new input method to be switched to.
+     * @deprecated Use {@link InputMethodService#setInputMethod(String)} instead. This method
+     * was intended for IME developers who should be accessing APIs through the service. APIs in
+     * this class are intended for app developers interacting with the IME.
      */
+    @Deprecated
     public void setInputMethod(IBinder token, String id) {
+        setInputMethodInternal(token, id);
+    }
+
+    /**
+     * @hide
+     */
+    public void setInputMethodInternal(IBinder token, String id) {
         try {
             mService.setInputMethod(token, id);
         } catch (RemoteException e) {
@@ -1817,8 +1854,21 @@
      * itself.
      * @param id The unique identifier for the new input method to be switched to.
      * @param subtype The new subtype of the new input method to be switched to.
+     * @deprecated Use
+     * {@link InputMethodService#setInputMethodAndSubtype(String, InputMethodSubtype)}
+     * instead. This method was intended for IME developers who should be accessing APIs through
+     * the service. APIs in this class are intended for app developers interacting with the IME.
      */
+    @Deprecated
     public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) {
+        setInputMethodAndSubtypeInternal(token, id, subtype);
+    }
+
+    /**
+     * @hide
+     */
+    public void setInputMethodAndSubtypeInternal(
+            IBinder token, String id, InputMethodSubtype subtype) {
         try {
             mService.setInputMethodAndSubtype(token, id, subtype);
         } catch (RemoteException e) {
@@ -1837,8 +1887,19 @@
      * @param flags Provides additional operating flags.  Currently may be
      * 0 or have the {@link #HIDE_IMPLICIT_ONLY},
      * {@link #HIDE_NOT_ALWAYS} bit set.
+     * @deprecated Use {@link InputMethodService#hideSoftInputFromInputMethod(int)}
+     * instead. This method was intended for IME developers who should be accessing APIs through
+     * the service. APIs in this class are intended for app developers interacting with the IME.
      */
+    @Deprecated
     public void hideSoftInputFromInputMethod(IBinder token, int flags) {
+        hideSoftInputFromInputMethodInternal(token, flags);
+    }
+
+    /**
+     * @hide
+     */
+    public void hideSoftInputFromInputMethodInternal(IBinder token, int flags) {
         try {
             mService.hideMySoftInput(token, flags);
         } catch (RemoteException e) {
@@ -1858,8 +1919,19 @@
      * @param flags Provides additional operating flags.  Currently may be
      * 0 or have the {@link #SHOW_IMPLICIT} or
      * {@link #SHOW_FORCED} bit set.
+     * @deprecated Use {@link InputMethodService#showSoftInputFromInputMethod(int)}
+     * instead. This method was intended for IME developers who should be accessing APIs through
+     * the service. APIs in this class are intended for app developers interacting with the IME.
      */
+    @Deprecated
     public void showSoftInputFromInputMethod(IBinder token, int flags) {
+        showSoftInputFromInputMethodInternal(token, flags);
+    }
+
+    /**
+     * @hide
+     */
+    public void showSoftInputFromInputMethodInternal(IBinder token, int flags) {
         try {
             mService.showMySoftInput(token, flags);
         } catch (RemoteException e) {
@@ -2239,8 +2311,19 @@
      * which allows it to perform this operation on itself.
      * @return true if the current input method and subtype was successfully switched to the last
      * used input method and subtype.
+     * @deprecated Use {@link InputMethodService#switchToLastInputMethod()} instead. This method
+     * was intended for IME developers who should be accessing APIs through the service. APIs in
+     * this class are intended for app developers interacting with the IME.
      */
+    @Deprecated
     public boolean switchToLastInputMethod(IBinder imeToken) {
+        return switchToLastInputMethodInternal(imeToken);
+    }
+
+    /**
+     * @hide
+     */
+    public boolean switchToLastInputMethodInternal(IBinder imeToken) {
         synchronized (mH) {
             try {
                 return mService.switchToLastInputMethod(imeToken);
@@ -2259,8 +2342,19 @@
      * belongs to the current IME
      * @return true if the current input method and subtype was successfully switched to the next
      * input method and subtype.
+     * @deprecated Use {@link InputMethodService#switchToNextInputMethod(boolean)} instead. This
+     * method was intended for IME developers who should be accessing APIs through the service.
+     * APIs in this class are intended for app developers interacting with the IME.
      */
+    @Deprecated
     public boolean switchToNextInputMethod(IBinder imeToken, boolean onlyCurrentIme) {
+        return switchToNextInputMethodInternal(imeToken, onlyCurrentIme);
+    }
+
+    /**
+     * @hide
+     */
+    public boolean switchToNextInputMethodInternal(IBinder imeToken, boolean onlyCurrentIme) {
         synchronized (mH) {
             try {
                 return mService.switchToNextInputMethod(imeToken, onlyCurrentIme);
@@ -2280,8 +2374,19 @@
      * between IMEs and subtypes.
      * @param imeToken Supplies the identifying token given to an input method when it was started,
      * which allows it to perform this operation on itself.
+     * @deprecated Use {@link InputMethodService#shouldOfferSwitchingToNextInputMethod()}
+     * instead. This method was intended for IME developers who should be accessing APIs through
+     * the service. APIs in this class are intended for app developers interacting with the IME.
      */
+    @Deprecated
     public boolean shouldOfferSwitchingToNextInputMethod(IBinder imeToken) {
+        return shouldOfferSwitchingToNextInputMethodInternal(imeToken);
+    }
+
+    /**
+     * @hide
+     */
+    public boolean shouldOfferSwitchingToNextInputMethodInternal(IBinder imeToken) {
         synchronized (mH) {
             try {
                 return mService.shouldOfferSwitchingToNextInputMethod(imeToken);
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index f4cbc54..fdc9f92 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -48,8 +48,13 @@
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
-    @StringDef({
-            TYPE_UNKNOWN, TYPE_OTHER, TYPE_EMAIL, TYPE_PHONE, TYPE_ADDRESS, TYPE_URL
+    @StringDef(prefix = { "TYPE_" }, value = {
+            TYPE_UNKNOWN,
+            TYPE_OTHER,
+            TYPE_EMAIL,
+            TYPE_PHONE,
+            TYPE_ADDRESS,
+            TYPE_URL,
     })
     @interface EntityType {}
 
diff --git a/core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java b/core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java
index 931eb99..45555bf 100644
--- a/core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java
+++ b/core/java/com/android/internal/graphics/SfVsyncFrameCallbackProvider.java
@@ -26,7 +26,15 @@
  */
 public final class SfVsyncFrameCallbackProvider implements AnimationFrameCallbackProvider {
 
-    private final Choreographer mChoreographer = Choreographer.getSfInstance();
+    private final Choreographer mChoreographer;
+
+    public SfVsyncFrameCallbackProvider() {
+        mChoreographer = Choreographer.getSfInstance();
+    }
+
+    public SfVsyncFrameCallbackProvider(Choreographer choreographer) {
+        mChoreographer = choreographer;
+    }
 
     @Override
     public void postFrameCallback(Choreographer.FrameCallback callback) {
diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java
index 4354486..8848e393 100644
--- a/core/java/com/android/server/BootReceiver.java
+++ b/core/java/com/android/server/BootReceiver.java
@@ -33,6 +33,7 @@
 import android.provider.Downloads;
 import android.text.TextUtils;
 import android.util.AtomicFile;
+import android.util.EventLog;
 import android.util.Slog;
 import android.util.Xml;
 
@@ -40,6 +41,7 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.XmlUtils;
+import com.android.server.DropboxLogTags;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -297,6 +299,7 @@
         Slog.i(TAG, "Copying " + filename + " to DropBox (" + tag + ")");
         db.addText(tag, headers + FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n") +
                 footers);
+        EventLog.writeEvent(DropboxLogTags.DROPBOX_FILE_COPY, filename, maxSize, tag);
     }
 
     private static void addAuditErrorsToDropBox(DropBoxManager db,
diff --git a/core/java/com/android/server/DropboxLogTags.logtags b/core/java/com/android/server/DropboxLogTags.logtags
new file mode 100644
index 0000000..c461cfe
--- /dev/null
+++ b/core/java/com/android/server/DropboxLogTags.logtags
@@ -0,0 +1,12 @@
+# See system/core/logcat/event.logtags for a description of the format of this file.
+
+# The java package name happens to be the same as frameworks/base/services/core
+# /java/com/android/server/EventLogTags.logtags. To avoid conflict, this file's name cannot
+# be EventLogTags.logtags because it generates a class with the same name.
+
+option java_package com.android.server;
+
+# -----------------------------
+# BootReceiver.java
+# -----------------------------
+81002 dropbox_file_copy (FileName|3),(Size|1),(Tag|3)
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 8ed958d..4015a7e 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -45,12 +45,21 @@
 
 package android.os;
 
+// This field contains internal metadata associated with an incident report,
+// such as the section ids and privacy policy specs from caller as well as how long
+// and how many bytes a section takes, etc.
+message IncidentMetadata {
+
+}
+
 // privacy field options must not be set at this level because all
 // the sections are able to be controlled and configured by section ids.
 // Instead privacy field options need to be configured in each section proto message.
 message IncidentProto {
-    // Incident header
+    // Incident header from callers
     repeated IncidentHeaderProto header = 1;
+    // Internal metadata of incidentd
+    optional IncidentMetadata metadata = 2;
 
     // Device information
     optional SystemPropertiesProto system_properties = 1000 [
diff --git a/core/proto/android/os/incidentheader.proto b/core/proto/android/os/incidentheader.proto
index ce924da..f0c736a 100644
--- a/core/proto/android/os/incidentheader.proto
+++ b/core/proto/android/os/incidentheader.proto
@@ -16,18 +16,34 @@
 
 syntax = "proto2";
 option java_multiple_files = true;
-option java_outer_classname = "IncidentHeaderProtoMetadata";
 
 package android.os;
 
+// IncidentHeaderProto contains extra information the caller of incidentd want to
+// attach in an incident report, the data should just be informative.
 message IncidentHeaderProto {
-    enum Cause {
-        CAUSE_UNKNOWN = 0;
-        CAUSE_USER = 1;
-        CAUSE_ANR = 2;
-        CAUSE_CRASH = 3;
+
+    // From statsd config, the name of the anomaly, usually human readable.
+    optional string incident_name = 1;
+
+    // Format a human readable reason why an incident report is requested.
+    // It's optional and may directly come from a user clicking the bug-report button.
+    optional string reason = 2;
+
+    // From statsd, the metric which causes the anomaly triggered.
+    optional string metric_name = 3;
+
+    // From statsd, the metric value exceeds the threshold. This is useful for
+    // ValueMetric and GaugeMetric.
+    oneof metric_value {
+        int64 int64_value = 4;
+        double double_value = 5;
     }
 
-    optional Cause cause = 1;
+    // Defines which stats config used to fire the request.
+    message StatsdConfigKey {
+        optional int32 uid = 1;
+        optional string name = 2;
+    }
+    optional StatsdConfigKey config_key = 6;
 }
-
diff --git a/core/tests/ConnectivityManagerTest/Android.mk b/core/tests/ConnectivityManagerTest/Android.mk
index 39cf4a4..5ed93f3 100644
--- a/core/tests/ConnectivityManagerTest/Android.mk
+++ b/core/tests/ConnectivityManagerTest/Android.mk
@@ -18,8 +18,8 @@
 # We only want this apk build for tests.
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 
 # Include all test java files.
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/core/tests/bandwidthtests/Android.mk b/core/tests/bandwidthtests/Android.mk
index 2af92df..ff9a0fe 100644
--- a/core/tests/bandwidthtests/Android.mk
+++ b/core/tests/bandwidthtests/Android.mk
@@ -22,8 +22,12 @@
 LOCAL_SRC_FILES := \
 	$(call all-java-files-under, src)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner org.apache.http.legacy
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := \
+    android.test.runner \
+    org.apache.http.legacy \
+    android.test.base \
+
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 LOCAL_PACKAGE_NAME := BandwidthTests
 
 include $(BUILD_PACKAGE)
diff --git a/core/tests/bluetoothtests/Android.mk b/core/tests/bluetoothtests/Android.mk
index f53419a..744e5b0 100644
--- a/core/tests/bluetoothtests/Android.mk
+++ b/core/tests/bluetoothtests/Android.mk
@@ -8,8 +8,8 @@
 LOCAL_SRC_FILES := \
 	$(call all-java-files-under, src)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 LOCAL_PACKAGE_NAME := BluetoothTests
 LOCAL_CERTIFICATE := platform
 
diff --git a/core/tests/coretests/src/android/security/recoverablekeystore/RecoverableKeyGeneratorTest.java b/core/tests/coretests/src/android/security/recoverablekeystore/RecoverableKeyGeneratorTest.java
new file mode 100644
index 0000000..d85d3b8
--- /dev/null
+++ b/core/tests/coretests/src/android/security/recoverablekeystore/RecoverableKeyGeneratorTest.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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.recoverablekeystore;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.security.keystore.AndroidKeyStoreSecretKey;
+import android.security.keystore.KeyGenParameterSpec;
+import android.security.keystore.KeyProperties;
+import android.security.keystore.KeyProtection;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.security.KeyStore;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class RecoverableKeyGeneratorTest {
+    private static final String ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore";
+    private static final String KEY_ALGORITHM = "AES";
+    private static final String TEST_ALIAS = "karlin";
+    private static final String WRAPPING_KEY_ALIAS = "RecoverableKeyGeneratorTestWrappingKey";
+
+    @Mock RecoverableKeyStorage mRecoverableKeyStorage;
+
+    @Captor ArgumentCaptor<KeyProtection> mKeyProtectionArgumentCaptor;
+
+    private AndroidKeyStoreSecretKey mPlatformKey;
+    private SecretKey mKeyHandle;
+    private RecoverableKeyGenerator mRecoverableKeyGenerator;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mPlatformKey = generateAndroidKeyStoreKey();
+        mKeyHandle = generateKey();
+        mRecoverableKeyGenerator = RecoverableKeyGenerator.newInstance(
+                mPlatformKey, mRecoverableKeyStorage);
+
+        when(mRecoverableKeyStorage.loadFromAndroidKeyStore(any())).thenReturn(mKeyHandle);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_PROVIDER);
+        keyStore.load(/*param=*/ null);
+        keyStore.deleteEntry(WRAPPING_KEY_ALIAS);
+    }
+
+    @Test
+    public void generateAndStoreKey_setsKeyInKeyStore() throws Exception {
+        mRecoverableKeyGenerator.generateAndStoreKey(TEST_ALIAS);
+
+        verify(mRecoverableKeyStorage, times(1))
+                .importIntoAndroidKeyStore(eq(TEST_ALIAS), any(), any());
+    }
+
+    @Test
+    public void generateAndStoreKey_storesKeyEnabledForEncryptDecrypt() throws Exception {
+        mRecoverableKeyGenerator.generateAndStoreKey(TEST_ALIAS);
+
+        KeyProtection keyProtection = getKeyProtectionUsed();
+        assertEquals(KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT,
+                keyProtection.getPurposes());
+    }
+
+    @Test
+    public void generateAndStoreKey_storesKeyEnabledForGCM() throws Exception {
+        mRecoverableKeyGenerator.generateAndStoreKey(TEST_ALIAS);
+
+        KeyProtection keyProtection = getKeyProtectionUsed();
+        assertArrayEquals(new String[] { KeyProperties.BLOCK_MODE_GCM },
+                keyProtection.getBlockModes());
+    }
+
+    @Test
+    public void generateAndStoreKey_storesKeyEnabledForNoPadding() throws Exception {
+        mRecoverableKeyGenerator.generateAndStoreKey(TEST_ALIAS);
+
+        KeyProtection keyProtection = getKeyProtectionUsed();
+        assertArrayEquals(new String[] { KeyProperties.ENCRYPTION_PADDING_NONE },
+                keyProtection.getEncryptionPaddings());
+    }
+
+    @Test
+    public void generateAndStoreKey_storesWrappedKey() throws Exception {
+        mRecoverableKeyGenerator.generateAndStoreKey(TEST_ALIAS);
+
+        verify(mRecoverableKeyStorage, times(1)).persistToDisk(eq(TEST_ALIAS), any());
+    }
+
+    @Test
+    public void generateAndStoreKey_returnsKeyHandle() throws Exception {
+        SecretKey secretKey = mRecoverableKeyGenerator.generateAndStoreKey(TEST_ALIAS);
+
+        assertEquals(mKeyHandle, secretKey);
+    }
+
+    private KeyProtection getKeyProtectionUsed() throws Exception {
+        verify(mRecoverableKeyStorage, times(1)).importIntoAndroidKeyStore(
+                any(), any(), mKeyProtectionArgumentCaptor.capture());
+        return mKeyProtectionArgumentCaptor.getValue();
+    }
+
+    private SecretKey generateKey() throws Exception {
+        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
+        keyGenerator.init(/*keySize=*/ 256);
+        return keyGenerator.generateKey();
+    }
+
+    private AndroidKeyStoreSecretKey generateAndroidKeyStoreKey() throws Exception {
+        KeyGenerator keyGenerator = KeyGenerator.getInstance(
+                KEY_ALGORITHM,
+                ANDROID_KEY_STORE_PROVIDER);
+        keyGenerator.init(new KeyGenParameterSpec.Builder(
+                WRAPPING_KEY_ALIAS, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
+                    .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+                    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+                    .build());
+        return (AndroidKeyStoreSecretKey) keyGenerator.generateKey();
+    }
+}
diff --git a/core/tests/coretests/src/android/security/recoverablekeystore/WrappedKeyTest.java b/core/tests/coretests/src/android/security/recoverablekeystore/WrappedKeyTest.java
new file mode 100644
index 0000000..233c821
--- /dev/null
+++ b/core/tests/coretests/src/android/security/recoverablekeystore/WrappedKeyTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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.recoverablekeystore;
+
+import static org.junit.Assert.assertEquals;
+
+import android.security.keystore.AndroidKeyStoreSecretKey;
+import android.security.keystore.KeyGenParameterSpec;
+import android.security.keystore.KeyProperties;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.security.KeyStore;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class WrappedKeyTest {
+    private static final String ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore";
+    private static final String KEY_ALGORITHM = "AES";
+    private static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding";
+    private static final String WRAPPING_KEY_ALIAS = "WrappedKeyTestWrappingKeyAlias";
+    private static final int GCM_TAG_LENGTH_BYTES = 16;
+    private static final int BITS_PER_BYTE = 8;
+    private static final int GCM_TAG_LENGTH_BITS = GCM_TAG_LENGTH_BYTES * BITS_PER_BYTE;
+
+    @After
+    public void tearDown() throws Exception {
+        KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_PROVIDER);
+        keyStore.load(/*param=*/ null);
+        keyStore.deleteEntry(WRAPPING_KEY_ALIAS);
+    }
+
+    @Test
+    public void fromSecretKey_createsWrappedKeyThatCanBeUnwrapped() throws Exception {
+        SecretKey wrappingKey = generateAndroidKeyStoreKey();
+        SecretKey rawKey = generateKey();
+
+        WrappedKey wrappedKey = WrappedKey.fromSecretKey(wrappingKey, rawKey);
+
+        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
+        cipher.init(
+                Cipher.UNWRAP_MODE,
+                wrappingKey,
+                new GCMParameterSpec(GCM_TAG_LENGTH_BITS, wrappedKey.getNonce()));
+        SecretKey unwrappedKey = (SecretKey) cipher.unwrap(
+                wrappedKey.getKeyMaterial(), KEY_ALGORITHM, Cipher.SECRET_KEY);
+        assertEquals(rawKey, unwrappedKey);
+    }
+
+    private SecretKey generateKey() throws Exception {
+        KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
+        keyGenerator.init(/*keySize=*/ 256);
+        return keyGenerator.generateKey();
+    }
+
+    private AndroidKeyStoreSecretKey generateAndroidKeyStoreKey() throws Exception {
+        KeyGenerator keyGenerator = KeyGenerator.getInstance(
+                KEY_ALGORITHM,
+                ANDROID_KEY_STORE_PROVIDER);
+        keyGenerator.init(new KeyGenParameterSpec.Builder(
+                WRAPPING_KEY_ALIAS, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
+                .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+                .build());
+        return (AndroidKeyStoreSecretKey) keyGenerator.generateKey();
+    }
+}
diff --git a/core/tests/coretests/src/android/util/ScrollViewScenario.java b/core/tests/coretests/src/android/util/ScrollViewScenario.java
index b5140e3..e9eb978 100644
--- a/core/tests/coretests/src/android/util/ScrollViewScenario.java
+++ b/core/tests/coretests/src/android/util/ScrollViewScenario.java
@@ -269,6 +269,6 @@
         mScrollView.setSmoothScrollingEnabled(false);
 
         setContentView(mScrollView);
-        mScrollView.restoreDefaultFocus();
+        mScrollView.post(() -> mScrollView.restoreDefaultFocus());
     }
 }
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java
index 8a5fc2d..c1b2309 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java
@@ -24,6 +24,7 @@
 import android.os.RemoteException;
 import android.support.test.runner.AndroidJUnit4;
 
+import libcore.util.EmptyArray;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -73,7 +74,7 @@
         List<AccessibilityNodeInfo> mInfosToReturn;
 
         @Override
-        public boolean findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
+        public String[] findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
                 long accessibilityNodeId, int interactionId,
                 IAccessibilityInteractionConnectionCallback callback, int flags, long threadId,
                 Bundle arguments) {
@@ -82,7 +83,7 @@
             } catch (RemoteException e) {
                 throw new RuntimeException(e);
             }
-            return true;
+            return EmptyArray.STRING;
         }
     }
 }
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
index d3bbee7..44b1f08 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
@@ -31,35 +31,35 @@
 public class AccessibilityServiceConnectionImpl extends IAccessibilityServiceConnection.Stub {
     public void setServiceInfo(AccessibilityServiceInfo info) {}
 
-    public boolean findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
+    public String[] findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
             long accessibilityNodeId, int interactionId,
             IAccessibilityInteractionConnectionCallback callback, int flags, long threadId,
             Bundle arguments) {
-        return false;
+        return null;
     }
 
-    public boolean findAccessibilityNodeInfosByText(int accessibilityWindowId,
+    public String[] findAccessibilityNodeInfosByText(int accessibilityWindowId,
             long accessibilityNodeId, String text, int interactionId,
             IAccessibilityInteractionConnectionCallback callback, long threadId) {
-        return false;
+        return null;
     }
 
-    public boolean findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
+    public String[] findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
             long accessibilityNodeId, String viewId, int interactionId,
             IAccessibilityInteractionConnectionCallback callback, long threadId) {
-        return false;
+        return null;
     }
 
-    public boolean findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType,
+    public String[] findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType,
             int interactionId, IAccessibilityInteractionConnectionCallback callback,
             long threadId) {
-        return false;
+        return null;
     }
 
-    public boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction,
+    public String[] focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction,
             int interactionId, IAccessibilityInteractionConnectionCallback callback,
             long threadId) {
-        return false;
+        return null;
     }
 
     public boolean performAccessibilityAction(int accessibilityWindowId, long accessibilityNodeId,
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk b/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk
index 47ee2cf..1d9f624 100644
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk
@@ -20,8 +20,8 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_STATIC_JAVA_LIBRARIES := android-common mockwebserver junit legacy-android-test
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := android-common mockwebserver junit
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
 
 LOCAL_PACKAGE_NAME := DownloadManagerTestApp
 
diff --git a/core/tests/hosttests/test-apps/ExternalSharedPerms/Android.mk b/core/tests/hosttests/test-apps/ExternalSharedPerms/Android.mk
index b35cbae..193e601 100644
--- a/core/tests/hosttests/test-apps/ExternalSharedPerms/Android.mk
+++ b/core/tests/hosttests/test-apps/ExternalSharedPerms/Android.mk
@@ -20,7 +20,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_STATIC_JAVA_LIBRARIES := legacy-android-test junit
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 
 LOCAL_SDK_VERSION := current
 
diff --git a/core/tests/hosttests/test-apps/ExternalSharedPermsBT/Android.mk b/core/tests/hosttests/test-apps/ExternalSharedPermsBT/Android.mk
index 06812b5..9f44767 100644
--- a/core/tests/hosttests/test-apps/ExternalSharedPermsBT/Android.mk
+++ b/core/tests/hosttests/test-apps/ExternalSharedPermsBT/Android.mk
@@ -20,7 +20,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_STATIC_JAVA_LIBRARIES := legacy-android-test junit
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 
 LOCAL_SDK_VERSION := current
 
diff --git a/core/tests/hosttests/test-apps/ExternalSharedPermsDiffKey/Android.mk b/core/tests/hosttests/test-apps/ExternalSharedPermsDiffKey/Android.mk
index 48bceaf..b4d354c 100644
--- a/core/tests/hosttests/test-apps/ExternalSharedPermsDiffKey/Android.mk
+++ b/core/tests/hosttests/test-apps/ExternalSharedPermsDiffKey/Android.mk
@@ -20,7 +20,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_STATIC_JAVA_LIBRARIES := legacy-android-test junit
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 
 LOCAL_SDK_VERSION := current
 
diff --git a/core/tests/hosttests/test-apps/ExternalSharedPermsFL/Android.mk b/core/tests/hosttests/test-apps/ExternalSharedPermsFL/Android.mk
index 569d102..969e588 100644
--- a/core/tests/hosttests/test-apps/ExternalSharedPermsFL/Android.mk
+++ b/core/tests/hosttests/test-apps/ExternalSharedPermsFL/Android.mk
@@ -20,7 +20,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_STATIC_JAVA_LIBRARIES := legacy-android-test junit
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 
 LOCAL_SDK_VERSION := current
 
diff --git a/core/tests/notificationtests/Android.mk b/core/tests/notificationtests/Android.mk
index 0551eb6..30c2dca 100644
--- a/core/tests/notificationtests/Android.mk
+++ b/core/tests/notificationtests/Android.mk
@@ -8,12 +8,11 @@
 LOCAL_SRC_FILES := \
 	$(call all-java-files-under, src)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
 LOCAL_PACKAGE_NAME := NotificationStressTests
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     junit \
-    legacy-android-test \
     ub-uiautomator
 
 include $(BUILD_PACKAGE)
diff --git a/keystore/java/android/security/keystore/KeyProperties.java b/keystore/java/android/security/keystore/KeyProperties.java
index d6b1cf1..a250d1f 100644
--- a/keystore/java/android/security/keystore/KeyProperties.java
+++ b/keystore/java/android/security/keystore/KeyProperties.java
@@ -39,13 +39,12 @@
      * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef(flag = true,
-            value = {
-                PURPOSE_ENCRYPT,
-                PURPOSE_DECRYPT,
-                PURPOSE_SIGN,
-                PURPOSE_VERIFY,
-                })
+    @IntDef(flag = true, prefix = { "PURPOSE_" }, value = {
+            PURPOSE_ENCRYPT,
+            PURPOSE_DECRYPT,
+            PURPOSE_SIGN,
+            PURPOSE_VERIFY,
+    })
     public @interface PurposeEnum {}
 
     /**
@@ -126,7 +125,7 @@
      * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
-    @StringDef({
+    @StringDef(prefix = { "KEY_" }, value = {
         KEY_ALGORITHM_RSA,
         KEY_ALGORITHM_EC,
         KEY_ALGORITHM_AES,
@@ -267,7 +266,7 @@
      * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
-    @StringDef({
+    @StringDef(prefix = { "BLOCK_MODE_" }, value = {
         BLOCK_MODE_ECB,
         BLOCK_MODE_CBC,
         BLOCK_MODE_CTR,
@@ -354,7 +353,7 @@
      * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
-    @StringDef({
+    @StringDef(prefix = { "ENCRYPTION_PADDING_" }, value = {
         ENCRYPTION_PADDING_NONE,
         ENCRYPTION_PADDING_PKCS7,
         ENCRYPTION_PADDING_RSA_PKCS1,
@@ -437,7 +436,7 @@
      * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
-    @StringDef({
+    @StringDef(prefix = { "SIGNATURE_PADDING_" }, value = {
         SIGNATURE_PADDING_RSA_PKCS1,
         SIGNATURE_PADDING_RSA_PSS,
         })
@@ -497,7 +496,7 @@
      * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
-    @StringDef({
+    @StringDef(prefix = { "DIGEST_" }, value = {
         DIGEST_NONE,
         DIGEST_MD5,
         DIGEST_SHA1,
@@ -647,11 +646,12 @@
      * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef({
-        ORIGIN_GENERATED,
-        ORIGIN_IMPORTED,
-        ORIGIN_UNKNOWN,
-        })
+    @IntDef(prefix = { "ORIGIN_" }, value = {
+            ORIGIN_GENERATED,
+            ORIGIN_IMPORTED,
+            ORIGIN_UNKNOWN,
+    })
+
     public @interface OriginEnum {}
 
     /** Key was generated inside AndroidKeyStore. */
diff --git a/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java b/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java
index b15e0a2..7cb8e37 100644
--- a/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java
@@ -81,12 +81,16 @@
         }
         out.writeByteArray(mSpec.getCertificateSubject().getEncoded());
         out.writeByteArray(mSpec.getCertificateSerialNumber().toByteArray());
-        writeOptionalDate(out, mSpec.getCertificateNotBefore());
-        writeOptionalDate(out, mSpec.getCertificateNotAfter());
+        out.writeLong(mSpec.getCertificateNotBefore().getTime());
+        out.writeLong(mSpec.getCertificateNotAfter().getTime());
         writeOptionalDate(out, mSpec.getKeyValidityStart());
         writeOptionalDate(out, mSpec.getKeyValidityForOriginationEnd());
         writeOptionalDate(out, mSpec.getKeyValidityForConsumptionEnd());
-        out.writeStringArray(mSpec.getDigests());
+        if (mSpec.isDigestsSpecified()) {
+            out.writeStringArray(mSpec.getDigests());
+        } else {
+            out.writeStringArray(null);
+        }
         out.writeStringArray(mSpec.getEncryptionPaddings());
         out.writeStringArray(mSpec.getSignaturePaddings());
         out.writeStringArray(mSpec.getBlockModes());
@@ -111,9 +115,15 @@
     private ParcelableKeyGenParameterSpec(Parcel in) {
         String keystoreAlias = in.readString();
         int purposes = in.readInt();
-        KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(keystoreAlias, purposes);
+        KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(
+                keystoreAlias, purposes);
         builder.setUid(in.readInt());
-        builder.setKeySize(in.readInt());
+        // KeySize is -1 by default, if the KeyGenParameterSpec previously parcelled had the default
+        // value, do not set it as this will cause setKeySize to throw.
+        int keySize = in.readInt();
+        if (keySize >= 0) {
+            builder.setKeySize(keySize);
+        }
 
         int keySpecType = in.readInt();
         AlgorithmParameterSpec algorithmSpec = null;
@@ -128,17 +138,22 @@
             algorithmSpec = new ECGenParameterSpec(stdName);
         } else {
             throw new IllegalArgumentException(
-                    String.format("Unknown algorithm parameter spec: %d", algorithmSpec));
+                    String.format("Unknown algorithm parameter spec: %d", keySpecType));
         }
-        builder.setAlgorithmParameterSpec(algorithmSpec);
+        if (algorithmSpec != null) {
+            builder.setAlgorithmParameterSpec(algorithmSpec);
+        }
         builder.setCertificateSubject(new X500Principal(in.createByteArray()));
         builder.setCertificateSerialNumber(new BigInteger(in.createByteArray()));
-        builder.setCertificateNotBefore(readDateOrNull(in));
-        builder.setCertificateNotAfter(readDateOrNull(in));
+        builder.setCertificateNotBefore(new Date(in.readLong()));
+        builder.setCertificateNotAfter(new Date(in.readLong()));
         builder.setKeyValidityStart(readDateOrNull(in));
         builder.setKeyValidityForOriginationEnd(readDateOrNull(in));
         builder.setKeyValidityForConsumptionEnd(readDateOrNull(in));
-        builder.setDigests(in.createStringArray());
+        String[] digests = in.createStringArray();
+        if (digests != null) {
+            builder.setDigests(digests);
+        }
         builder.setEncryptionPaddings(in.createStringArray());
         builder.setSignaturePaddings(in.createStringArray());
         builder.setBlockModes(in.createStringArray());
diff --git a/keystore/tests/Android.mk b/keystore/tests/Android.mk
index 51adde4..1167f76 100644
--- a/keystore/tests/Android.mk
+++ b/keystore/tests/Android.mk
@@ -21,8 +21,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    android-support-test \
-    legacy-android-test
+    android-support-test
 
 LOCAL_PACKAGE_NAME := KeystoreTests
 
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 96e4fcf..7cacaf6 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -122,7 +122,7 @@
         instrumentation: true,
         profile_file: "hwui/hwui.profdata",
         benchmarks: ["hwui"],
-        enable_profile_use: false,
+        enable_profile_use: true,
     },
 }
 
diff --git a/libs/hwui/Outline.h b/libs/hwui/Outline.h
index 77d7bef..4ddacc8 100644
--- a/libs/hwui/Outline.h
+++ b/libs/hwui/Outline.h
@@ -42,8 +42,15 @@
         mBounds.set(left, top, right, bottom);
         mRadius = radius;
 
+
+        // Reuse memory if previous outline was the same shape (rect or round rect).
+        if ( mPath.countVerbs() > 10) {
+            mPath.reset();
+        } else {
+            mPath.rewind();
+        }
+
         // update mPath to reflect new outline
-        mPath.reset();
         if (MathUtils::isPositive(radius)) {
             mPath.addRoundRect(SkRect::MakeLTRB(left, top, right, bottom), radius, radius);
         } else {
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 12e5744..e2f9b47 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -977,7 +977,7 @@
     public static final String PROPERTY_ALGORITHMS = "algorithms";
 
     /** @hide */
-    @StringDef({
+    @StringDef(prefix = { "PROPERTY_" }, value = {
         PROPERTY_VENDOR,
         PROPERTY_VERSION,
         PROPERTY_DESCRIPTION,
@@ -1010,7 +1010,7 @@
     public static final String PROPERTY_DEVICE_UNIQUE_ID = "deviceUniqueId";
 
     /** @hide */
-    @StringDef({
+    @StringDef(prefix = { "PROPERTY_" }, value = {
         PROPERTY_DEVICE_UNIQUE_ID,
     })
     @Retention(RetentionPolicy.SOURCE)
diff --git a/media/java/android/media/MediaMetadata.java b/media/java/android/media/MediaMetadata.java
index 31eb948..94d4d55 100644
--- a/media/java/android/media/MediaMetadata.java
+++ b/media/java/android/media/MediaMetadata.java
@@ -45,34 +45,61 @@
     /**
      * @hide
      */
-    @StringDef({METADATA_KEY_TITLE, METADATA_KEY_ARTIST, METADATA_KEY_ALBUM, METADATA_KEY_AUTHOR,
-            METADATA_KEY_WRITER, METADATA_KEY_COMPOSER, METADATA_KEY_COMPILATION,
-            METADATA_KEY_DATE, METADATA_KEY_GENRE, METADATA_KEY_ALBUM_ARTIST, METADATA_KEY_ART_URI,
-            METADATA_KEY_ALBUM_ART_URI, METADATA_KEY_DISPLAY_TITLE, METADATA_KEY_DISPLAY_SUBTITLE,
-            METADATA_KEY_DISPLAY_DESCRIPTION, METADATA_KEY_DISPLAY_ICON_URI,
-            METADATA_KEY_MEDIA_ID, METADATA_KEY_MEDIA_URI})
+    @StringDef(prefix = { "METADATA_KEY_" }, value = {
+            METADATA_KEY_TITLE,
+            METADATA_KEY_ARTIST,
+            METADATA_KEY_ALBUM,
+            METADATA_KEY_AUTHOR,
+            METADATA_KEY_WRITER,
+            METADATA_KEY_COMPOSER,
+            METADATA_KEY_COMPILATION,
+            METADATA_KEY_DATE,
+            METADATA_KEY_GENRE,
+            METADATA_KEY_ALBUM_ARTIST,
+            METADATA_KEY_ART_URI,
+            METADATA_KEY_ALBUM_ART_URI,
+            METADATA_KEY_DISPLAY_TITLE,
+            METADATA_KEY_DISPLAY_SUBTITLE,
+            METADATA_KEY_DISPLAY_DESCRIPTION,
+            METADATA_KEY_DISPLAY_ICON_URI,
+            METADATA_KEY_MEDIA_ID,
+            METADATA_KEY_MEDIA_URI,
+    })
     @Retention(RetentionPolicy.SOURCE)
     public @interface TextKey {}
 
     /**
      * @hide
      */
-    @StringDef({METADATA_KEY_DURATION, METADATA_KEY_YEAR, METADATA_KEY_TRACK_NUMBER,
-            METADATA_KEY_NUM_TRACKS, METADATA_KEY_DISC_NUMBER, METADATA_KEY_BT_FOLDER_TYPE})
+    @StringDef(prefix = { "METADATA_KEY_" }, value = {
+            METADATA_KEY_DURATION,
+            METADATA_KEY_YEAR,
+            METADATA_KEY_TRACK_NUMBER,
+            METADATA_KEY_NUM_TRACKS,
+            METADATA_KEY_DISC_NUMBER,
+            METADATA_KEY_BT_FOLDER_TYPE,
+    })
     @Retention(RetentionPolicy.SOURCE)
     public @interface LongKey {}
 
     /**
      * @hide
      */
-    @StringDef({METADATA_KEY_ART, METADATA_KEY_ALBUM_ART, METADATA_KEY_DISPLAY_ICON})
+    @StringDef(prefix = { "METADATA_KEY_" }, value = {
+            METADATA_KEY_ART,
+            METADATA_KEY_ALBUM_ART,
+            METADATA_KEY_DISPLAY_ICON,
+    })
     @Retention(RetentionPolicy.SOURCE)
     public @interface BitmapKey {}
 
     /**
      * @hide
      */
-    @StringDef({METADATA_KEY_USER_RATING, METADATA_KEY_RATING})
+    @StringDef(prefix = { "METADATA_KEY_" }, value = {
+            METADATA_KEY_USER_RATING,
+            METADATA_KEY_RATING,
+    })
     @Retention(RetentionPolicy.SOURCE)
     public @interface RatingKey {}
 
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index 8283c8b..17d16b8 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -17,6 +17,7 @@
 
 import android.annotation.DrawableRes;
 import android.annotation.IntDef;
+import android.annotation.LongDef;
 import android.annotation.Nullable;
 import android.media.RemoteControlClient;
 import android.os.Bundle;
@@ -41,7 +42,7 @@
     /**
      * @hide
      */
-    @IntDef(flag=true, value={ACTION_STOP, ACTION_PAUSE, ACTION_PLAY, ACTION_REWIND,
+    @LongDef(flag=true, value={ACTION_STOP, ACTION_PAUSE, ACTION_PLAY, ACTION_REWIND,
             ACTION_SKIP_TO_PREVIOUS, ACTION_SKIP_TO_NEXT, ACTION_FAST_FORWARD, ACTION_SET_RATING,
             ACTION_SEEK_TO, ACTION_PLAY_PAUSE, ACTION_PLAY_FROM_MEDIA_ID, ACTION_PLAY_FROM_SEARCH,
             ACTION_SKIP_TO_QUEUE_ITEM, ACTION_PLAY_FROM_URI, ACTION_PREPARE,
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index 0f46096..3bbc2c4 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -1650,7 +1650,7 @@
         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/channel";
 
         /** @hide */
-        @StringDef({
+        @StringDef(prefix = { "TYPE_" }, value = {
                 TYPE_OTHER,
                 TYPE_NTSC,
                 TYPE_PAL,
@@ -1863,7 +1863,7 @@
         public static final String TYPE_PREVIEW = "TYPE_PREVIEW";
 
         /** @hide */
-        @StringDef({
+        @StringDef(prefix = { "SERVICE_TYPE_" }, value = {
                 SERVICE_TYPE_OTHER,
                 SERVICE_TYPE_AUDIO_VIDEO,
                 SERVICE_TYPE_AUDIO,
@@ -1881,7 +1881,7 @@
         public static final String SERVICE_TYPE_AUDIO = "SERVICE_TYPE_AUDIO";
 
         /** @hide */
-        @StringDef({
+        @StringDef(prefix = { "VIDEO_FORMAT_" }, value = {
                 VIDEO_FORMAT_240P,
                 VIDEO_FORMAT_360P,
                 VIDEO_FORMAT_480I,
@@ -1930,7 +1930,7 @@
         public static final String VIDEO_FORMAT_4320P = "VIDEO_FORMAT_4320P";
 
         /** @hide */
-        @StringDef({
+        @StringDef(prefix = { "VIDEO_RESOLUTION_" }, value = {
                 VIDEO_RESOLUTION_SD,
                 VIDEO_RESOLUTION_ED,
                 VIDEO_RESOLUTION_HD,
diff --git a/media/mca/tests/Android.mk b/media/mca/tests/Android.mk
index eb451f7..394f542 100644
--- a/media/mca/tests/Android.mk
+++ b/media/mca/tests/Android.mk
@@ -4,8 +4,8 @@
 # We only want this apk build for tests.
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 
 # Include all test java files.
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/media/tests/MediaFrameworkTest/Android.mk b/media/tests/MediaFrameworkTest/Android.mk
index 0d9f42b..145cde6 100644
--- a/media/tests/MediaFrameworkTest/Android.mk
+++ b/media/tests/MediaFrameworkTest/Android.mk
@@ -5,13 +5,12 @@
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     mockito-target-minus-junit4 \
     android-support-test \
-    android-ex-camera2 \
-    legacy-android-test
+    android-ex-camera2
 
 LOCAL_PACKAGE_NAME := mediaframeworktest
 
diff --git a/nfc-extras/tests/Android.mk b/nfc-extras/tests/Android.mk
index d8fe5a6..be2bb53 100644
--- a/nfc-extras/tests/Android.mk
+++ b/nfc-extras/tests/Android.mk
@@ -22,7 +22,7 @@
     android.test.runner \
     com.android.nfc_extras
 
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 
 # Include all test java files.
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/packages/CarrierDefaultApp/tests/unit/Android.mk b/packages/CarrierDefaultApp/tests/unit/Android.mk
index 63bd0b1..6e120a6 100644
--- a/packages/CarrierDefaultApp/tests/unit/Android.mk
+++ b/packages/CarrierDefaultApp/tests/unit/Android.mk
@@ -19,9 +19,9 @@
 LOCAL_MODULE_TAGS := tests
 LOCAL_CERTIFICATE := platform
 
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
+LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common android.test.base
 
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test mockito-target-minus-junit4 legacy-android-test
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test mockito-target-minus-junit4
 
 # Include all test java files.
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/packages/ExtServices/tests/Android.mk b/packages/ExtServices/tests/Android.mk
index 92afbeb..1eb5847 100644
--- a/packages/ExtServices/tests/Android.mk
+++ b/packages/ExtServices/tests/Android.mk
@@ -5,14 +5,13 @@
 LOCAL_MODULE_TAGS := tests
 LOCAL_CERTIFICATE := platform
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     android-support-test \
     mockito-target-minus-junit4 \
     espresso-core \
     truth-prebuilt \
-    legacy-android-test \
     testables
 
 # Include all test java files.
diff --git a/packages/InputDevices/res/raw/keyboard_layout_azerbaijani.kcm b/packages/InputDevices/res/raw/keyboard_layout_azerbaijani.kcm
new file mode 100644
index 0000000..69490cc
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_azerbaijani.kcm
@@ -0,0 +1,312 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Azerbaijan (AZ) keyboard layout.
+#
+
+type OVERLAY
+
+### ROW 1
+
+key GRAVE {
+    label:                              '`'
+    base:                               '`'
+    shift:                              '~'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '1'
+    shift:                              '!'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '2'
+    shift:                              '"'
+    ralt:                               '@'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '3'
+    shift:                              '\u2166'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '4'
+    shift:                              ';'
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '5'
+    shift:                              '%'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '6'
+    shift:                              ':'
+    shift+ralt:                         '^'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '7'
+    shift:                              '?'
+    ralt:                               '&'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '8'
+    shift:                              '*'
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '9'
+    shift:                              '('
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '0'
+    shift:                              ')'
+}
+
+key MINUS {
+    label:                              '-'
+    base:                               '-'
+    shift:                              '_'
+}
+
+key EQUALS {
+    label:                              '='
+    base:                               '='
+    shift:                              '+'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base:                               'q'
+    shift, capslock:                    'Q'
+}
+
+key W {
+    label:                              '\u00dc'
+    base:                               '\u00fc'
+    shift, capslock:                    '\u00dc'
+}
+
+key E {
+    label:                              'E'
+    base:                               'e'
+    shift, capslock:                    'E'
+}
+
+key R {
+    label:                              'R'
+    base:                               'r'
+    shift, capslock:                    'R'
+}
+
+key T {
+    label:                              'T'
+    base:                               't'
+    shift, capslock:                    'T'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               'y'
+    shift, capslock:                    'Y'
+}
+
+key U {
+    label:                              'U'
+    base:                               'u'
+    shift, capslock:                    'U'
+}
+
+key I {
+    label:                              '\u0130'
+    base:                               'i'
+    shift, capslock:                    '\u0130'
+}
+
+key O {
+    label:                              'O'
+    base:                               'o'
+    shift, capslock:                    'O'
+}
+
+key P {
+    label:                              'P'
+    base:                               'p'
+    shift, capslock:                    'P'
+}
+
+key LEFT_BRACKET {
+    label:                              '\u00d6'
+    base:                               '\u00f6'
+    shift:                              '\u00d6'
+}
+
+key RIGHT_BRACKET {
+    label:                              '\u011e'
+    base:                               '\u011f'
+    shift:                              '\u011e'
+}
+
+key BACKSLASH {
+    label:                              '\\'
+    base:                               '\\'
+    shift:                              '|'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               'a'
+    shift, capslock:                    'A'
+}
+
+key S {
+    label:                              'S'
+    base:                               's'
+    shift, capslock:                    'S'
+}
+
+key D {
+    label:                              'D'
+    base:                               'd'
+    shift, capslock:                    'D'
+}
+
+key F {
+    label:                              'F'
+    base:                               'f'
+    shift, capslock:                    'F'
+}
+
+key G {
+    label:                              'G'
+    base:                               'g'
+    shift, capslock:                    'G'
+}
+
+key H {
+    label:                              'H'
+    base:                               'h'
+    shift, capslock:                    'H'
+}
+
+key J {
+    label:                              'J'
+    base:                               'j'
+    shift, capslock:                    'J'
+}
+
+key K {
+    label:                              'K'
+    base:                               'k'
+    shift, capslock:                    'K'
+}
+
+key L {
+    label:                              'L'
+    base:                               'l'
+    shift, capslock:                    'L'
+}
+
+key SEMICOLON {
+    label:                              'I'
+    base:                               '\u0131'
+    shift:                              'I'
+}
+
+key APOSTROPHE {
+    label:                              '\u018f'
+    base:                               '\u0259'
+    shift:                              '\u018f'
+}
+
+### ROW 4
+
+key Z {
+    label:                              'Z'
+    base:                               'z'
+    shift, capslock:                    'Z'
+}
+
+key X {
+    label:                              'X'
+    base:                               'x'
+    shift, capslock:                    'X'
+}
+
+key C {
+    label:                              'C'
+    base:                               'c'
+    shift, capslock:                    'C'
+}
+
+key V {
+    label:                              'V'
+    base:                               'v'
+    shift, capslock:                    'V'
+}
+
+key B {
+    label:                              'B'
+    base:                               'b'
+    shift, capslock:                    'B'
+}
+
+key N {
+    label:                              'N'
+    base:                               'n'
+    shift, capslock:                    'N'
+}
+
+key M {
+    label:                              'M'
+    base:                               'm'
+    shift, capslock:                    'M'
+}
+
+key COMMA {
+    label:                              '\u00c7'
+    base:                               '\u00e7'
+    shift:                              '\u00c7'
+}
+
+key PERIOD {
+    label:                              '\u015e'
+    base:                               '\u015f'
+    shift:                              '\u015e'
+}
+
+key SLASH {
+    label:                              '.'
+    base:                               '.'
+    shift:                              ','
+}
diff --git a/packages/InputDevices/res/values/strings.xml b/packages/InputDevices/res/values/strings.xml
index 1e26226..61d3234 100644
--- a/packages/InputDevices/res/values/strings.xml
+++ b/packages/InputDevices/res/values/strings.xml
@@ -122,4 +122,7 @@
 
     <!-- Persian keyboard layout label. [CHAR LIMIT=35] -->
     <string name="keyboard_layout_persian">Persian</string>
+
+    <!-- Azerbaijani keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_azerbaijani">Azerbaijani</string>
 </resources>
diff --git a/packages/InputDevices/res/xml/keyboard_layouts.xml b/packages/InputDevices/res/xml/keyboard_layouts.xml
index c55711a..c6bfc1f 100644
--- a/packages/InputDevices/res/xml/keyboard_layouts.xml
+++ b/packages/InputDevices/res/xml/keyboard_layouts.xml
@@ -155,4 +155,8 @@
     <keyboard-layout android:name="keyboard_layout_persian"
             android:label="@string/keyboard_layout_persian"
             android:keyboardLayout="@raw/keyboard_layout_persian" />
+
+    <keyboard-layout android:name="keyboard_layout_azerbaijani"
+            android:label="@string/keyboard_layout_azerbaijani"
+            android:keyboardLayout="@raw/keyboard_layout_azerbaijani" />
 </keyboard-layouts>
diff --git a/packages/MtpDocumentsProvider/tests/Android.mk b/packages/MtpDocumentsProvider/tests/Android.mk
index 148cd0d..ba346f42 100644
--- a/packages/MtpDocumentsProvider/tests/Android.mk
+++ b/packages/MtpDocumentsProvider/tests/Android.mk
@@ -3,8 +3,8 @@
 
 LOCAL_MODULE_TAGS := tests
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base android.test.mock
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 LOCAL_PACKAGE_NAME := MtpDocumentsProviderTests
 LOCAL_INSTRUMENTATION_FOR := MtpDocumentsProvider
 LOCAL_CERTIFICATE := media
diff --git a/packages/SettingsLib/tests/integ/Android.mk b/packages/SettingsLib/tests/integ/Android.mk
index 3c8c8ac..cfb3519d 100644
--- a/packages/SettingsLib/tests/integ/Android.mk
+++ b/packages/SettingsLib/tests/integ/Android.mk
@@ -20,7 +20,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
+LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common android.test.base
 
 LOCAL_JACK_FLAGS := --multi-dex native
 
@@ -33,7 +33,6 @@
     android-support-test \
     espresso-core \
     mockito-target-minus-junit4 \
-    legacy-android-test \
     truth-prebuilt
 
 # Code coverage puts us over the dex limit, so enable multi-dex for coverage-enabled builds
diff --git a/packages/SettingsProvider/Android.mk b/packages/SettingsProvider/Android.mk
index 069e83a..0f2c5ab 100644
--- a/packages/SettingsProvider/Android.mk
+++ b/packages/SettingsProvider/Android.mk
@@ -7,7 +7,7 @@
     src/com/android/providers/settings/EventLogTags.logtags
 
 LOCAL_JAVA_LIBRARIES := telephony-common ims-common
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 
 LOCAL_PACKAGE_NAME := SettingsProvider
 LOCAL_CERTIFICATE := platform
diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml
index 9374d52..287a888 100644
--- a/packages/SettingsProvider/AndroidManifest.xml
+++ b/packages/SettingsProvider/AndroidManifest.xml
@@ -11,6 +11,8 @@
                  android:icon="@mipmap/ic_launcher_settings"
                  android:defaultToDeviceProtectedStorage="true"
                  android:directBootAware="true">
+        <uses-library android:name="android.test.runner" />
+
 
         <provider android:name="SettingsProvider"
                   android:authorities="settings"
diff --git a/packages/Shell/tests/Android.mk b/packages/Shell/tests/Android.mk
index 48b757c..7f24a38 100644
--- a/packages/Shell/tests/Android.mk
+++ b/packages/Shell/tests/Android.mk
@@ -6,14 +6,13 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base android.test.mock
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     android-support-test \
     mockito-target-minus-junit4 \
     ub-uiautomator \
     junit \
-    legacy-android-test \
 
 LOCAL_PACKAGE_NAME := ShellTests
 LOCAL_COMPATIBILITY_SUITE := device-tests
diff --git a/packages/SystemUI/shared/tests/Android.mk b/packages/SystemUI/shared/tests/Android.mk
index ce3b442..239a4e3 100644
--- a/packages/SystemUI/shared/tests/Android.mk
+++ b/packages/SystemUI/shared/tests/Android.mk
@@ -38,7 +38,6 @@
     mockito-target-minus-junit4 \
     SystemUI-proto \
     SystemUI-tags \
-    legacy-android-test \
     testables \
     truth-prebuilt \
 
@@ -50,4 +49,4 @@
 
 ifeq ($(EXCLUDE_SYSTEMUI_TESTS),)
     include $(BUILD_PACKAGE)
-endif
\ No newline at end of file
+endif
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 3b54e11..5c8c3f35 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -333,7 +333,7 @@
             } else if (GLOBAL_ACTION_KEY_RESTART.equals(actionKey)) {
                 mItems.add(new RestartAction());
             } else if (GLOBAL_ACTION_KEY_LOGOUT.equals(actionKey)) {
-                if (mDevicePolicyManager.isLogoutButtonEnabled()
+                if (mDevicePolicyManager.isLogoutEnabled()
                         && getCurrentUser().id != UserHandle.USER_SYSTEM) {
                     mItems.add(new LogoutAction());
                     mHasLogoutButton = true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 3a36776..05fcbb0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -204,12 +204,15 @@
             throw new IllegalArgumentException("Cannot change to UNINITIALIZED.");
         }
 
+        final ScrimState oldState = mState;
+        mState = state;
+
         if (mCallback != null) {
             mCallback.onCancelled();
         }
         mCallback = callback;
 
-        state.prepare(mState);
+        state.prepare(oldState);
         mScreenBlankingCallbackCalled = false;
         mAnimationDelay = 0;
         mBlankScreen = state.getBlanksScreen();
@@ -228,8 +231,6 @@
             mKeyguardFadeoutAnimation.cancel();
         }
 
-        mState = state;
-
         // Do not let the device sleep until we're done with all animations
         if (!mWakeLockHeld) {
             if (mWakeLock != null) {
@@ -310,7 +311,6 @@
                     mCurrentInFrontAlpha = 0;
                 }
             } else {
-                Log.w(TAG, "Invalid state, cannot set panel expansion when: " + mState);
                 return;
             }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 80bab72..c61b7e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -661,8 +661,7 @@
 
         @Override
         public void onCancelled() {
-            // Transition was cancelled because another one took over.
-            // Nothing to do in here but wait.
+            onFinished();
         }
     };
 
@@ -4140,14 +4139,10 @@
                 .setStartDelay(0)
                 .setDuration(FADE_KEYGUARD_DURATION_PULSING)
                 .setInterpolator(ScrimController.KEYGUARD_FADE_OUT_INTERPOLATOR)
-                .setListener(new AnimatorListenerAdapter() {
-                    @Override
-                    public void onAnimationEnd(Animator animation) {
-                        hideKeyguard();
-                        mStatusBarKeyguardViewManager.onKeyguardFadedAway();
-                    }
-                })
-                .start();
+                .withEndAction(()-> {
+                    hideKeyguard();
+                    mStatusBarKeyguardViewManager.onKeyguardFadedAway();
+                }).start();
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 195607d..7374f11 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -448,7 +448,7 @@
                 childState.height = Math.max(row.getIntrinsicHeight(), childState.height);
                 childState.hidden = false;
                 ExpandableViewState topState = resultState.getViewStateForView(topHeadsUpEntry);
-                if (!isTopEntry && (!mIsExpanded
+                if (topState != null && !isTopEntry && (!mIsExpanded
                         || unmodifiedEndLocation < topState.yTranslation + topState.height)) {
                     // Ensure that a headsUp doesn't vertically extend further than the heads-up at
                     // the top most z-position
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index b695919..9d44895 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -54,11 +54,15 @@
     mockito-target-minus-junit4 \
     SystemUI-proto \
     SystemUI-tags \
-    legacy-android-test \
     testables \
     truth-prebuilt \
 
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common android.car
+LOCAL_JAVA_LIBRARIES := \
+    android.test.runner \
+    telephony-common \
+    android.car \
+    android.test.base \
+
 
 LOCAL_AAPT_FLAGS := --extra-packages com.android.systemui:com.android.keyguard
 
diff --git a/packages/VpnDialogs/res/values-bs/strings.xml b/packages/VpnDialogs/res/values-bs/strings.xml
index 1862bb7..56812d5 100644
--- a/packages/VpnDialogs/res/values-bs/strings.xml
+++ b/packages/VpnDialogs/res/values-bs/strings.xml
@@ -24,7 +24,7 @@
     <string name="data_transmitted" msgid="7988167672982199061">"Poslano:"</string>
     <string name="data_received" msgid="4062776929376067820">"Primljeno:"</string>
     <string name="data_value_format" msgid="2192466557826897580">"Broj bajtova: <xliff:g id="NUMBER_0">%1$s</xliff:g>/Broj paketa: <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
-    <string name="always_on_disconnected_title" msgid="1906740176262776166">"Ne može se povezati na stalno uključen VPN"</string>
+    <string name="always_on_disconnected_title" msgid="1906740176262776166">"Nije se moguće povezati na stalno uključen VPN"</string>
     <string name="always_on_disconnected_message" msgid="555634519845992917">"Aplikacija <xliff:g id="VPN_APP_0">%1$s</xliff:g> je postavljena da ostane povezana sve vrijeme, ali se trenutno ne može povezati. Telefon će koristiti javnu mrežu dok se ponovo ne mogne povezati s aplikacijom <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string>
     <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"Aplikacija <xliff:g id="VPN_APP">%1$s</xliff:g> je postavljena da ostane povezana sve vrijeme, ali se trenutno ne može povezati. Nećete biti imati vezu dok se VPN ne mogne ponovo povezati."</string>
     <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string>
diff --git a/packages/WAPPushManager/tests/Android.mk b/packages/WAPPushManager/tests/Android.mk
index 1dea798..bfc85ab 100644
--- a/packages/WAPPushManager/tests/Android.mk
+++ b/packages/WAPPushManager/tests/Android.mk
@@ -18,8 +18,8 @@
 # We only want this apk build for tests.
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 
 # Include all test java files.
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index ba6bb23..935b787 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3953,6 +3953,10 @@
 
     // An autofill session was started
     // Package: Package of app that is autofilled
+    // NOTE: starting on OS MR1, it also added the following field:
+    // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+    // NOTE: starting on OS P, it also added the following field:
+    // Tag FIELD_FLAGS - Flags used to start the session
     AUTOFILL_SESSION_STARTED = 906;
 
     // An autofill request was processed by a service
@@ -3960,7 +3964,11 @@
     // Type TYPE_FAILURE: The request failed
     // Package: Package of app that is autofilled
     // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
-    // Tag FIELD_AUTOFILL_NUM_DATASET: The number of datasets returned (only in success case)
+    // Tag FIELD_AUTOFILL_NUM_DATASETS: The number of datasets returned (only in success case)
+    // NOTE: starting on OS P, it also added:
+    // Type TYPE_CLOSE: Service returned a null response.
+    // Tag FIELD_AUTOFILL_NUM_FIELD_CLASSIFICATION_IDS: if service requested field classification,
+    // number of entries field ids in the request.
     AUTOFILL_REQUEST = 907;
 
     // Tag of a field for a package of an autofill service
@@ -4863,7 +4871,6 @@
     // Counter: duration (in ms) that autofill will be disabled
     // OS: P
     // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
-    // Tag FIELD_CLASS_NAME: Name of the Package of service that processed the request
     AUTOFILL_SERVICE_DISABLED_APP = 1231;
 
     // An autofill service asked to disable autofill for a given activity.
@@ -5067,6 +5074,26 @@
     // OS: P
     NOTIFICATION_ZEN_MODE_RULE_SELECTION_DIALOG = 1270;
 
+    // Tag of a field for the number of ids in an autofill field classification request.
+    FIELD_AUTOFILL_NUM_FIELD_CLASSIFICATION_IDS = 1271;
+
+    // An autofill service updated its user data
+    // Package: Package of the autofill service that updated the user data
+    // Counter: number of fields added (or 0 if reset)
+    // OS: P
+    AUTOFILL_USERDATA_UPDATED = 1272;
+
+    // Some data entered by the user matched the field classification requested by the service.
+    // Package: Package of app that is autofilled
+    // Counter: number of matches found
+    // OS: P
+    // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+    // Tag FIELD_AUTOFILL_MATCH_SCORE: Average score of the matches, in the range of 0 to 100
+    AUTOFILL_FIELD_CLASSIFICATION_MATCHES = 1273;
+
+    // Tag used to report autofill field classification scores
+    FIELD_AUTOFILL_MATCH_SCORE = 1274;
+
     // ---- End P Constants, all P constants go above this line ----
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index 75d080d..d817da5 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -187,6 +187,12 @@
     // to a Wi-Fi network
     NOTE_WIFI_WRONG_PASSWORD = 42;
 
+    // Inform the user that Wifi Wake will re-enable wifi when possible
+    NOTE_WIFI_WAKE_ONBOARD = 43;
+
+    // Inform the user that Wifi Wake has automatically re-enabled Wifi
+    NOTE_WIFI_WAKE_TURNED_BACK_ON = 44;
+
     // ADD_NEW_IDS_ABOVE_THIS_LINE
     // Legacy IDs with arbitrary values appear below
     // Legacy IDs existed as stable non-conflicting constants prior to the O release
diff --git a/sax/tests/saxtests/Android.mk b/sax/tests/saxtests/Android.mk
index d3fbd05..e0e490c 100644
--- a/sax/tests/saxtests/Android.mk
+++ b/sax/tests/saxtests/Android.mk
@@ -7,8 +7,8 @@
 # Include all test java files.
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 LOCAL_PACKAGE_NAME := FrameworksSaxTests
 
 include $(BUILD_PACKAGE)
diff --git a/services/Android.bp b/services/Android.bp
index 84c45fe..5e75c37 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -1,3 +1,46 @@
+// merge all required services into one jar
+// ============================================================
+java_library {
+    name: "services",
+
+    dex_preopt: {
+        app_image: true,
+        profile: "art-profile",
+    },
+
+    srcs: [
+        "java/**/*.java",
+    ],
+
+    // The convention is to name each service module 'services.$(module_name)'
+    static_libs: [
+        "services.core.priorityboosted",
+        "services.accessibility",
+        "services.appwidget",
+        "services.autofill",
+        "services.backup",
+        "services.companion",
+        "services.coverage",
+        "services.devicepolicy",
+        "services.midi",
+        "services.net",
+        "services.print",
+        "services.restrictions",
+        "services.usage",
+        "services.usb",
+        "services.voiceinteraction",
+        "android.hidl.base-V1.0-java",
+    ],
+
+    libs: [
+        "android.hidl.manager-V1.0-java",
+    ],
+
+    // Uncomment to enable output of certain warnings (deprecated, unchecked)
+    //javacflags: ["-Xlint"],
+
+}
+
 // native library
 // =============================================================
 
diff --git a/services/Android.mk b/services/Android.mk
deleted file mode 100644
index 81d8181..0000000
--- a/services/Android.mk
+++ /dev/null
@@ -1,67 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-# merge all required services into one jar
-# ============================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services
-LOCAL_DEX_PREOPT_APP_IMAGE := true
-LOCAL_DEX_PREOPT_GENERATE_PROFILE := true
-LOCAL_DEX_PREOPT_PROFILE_CLASS_LISTING := $(LOCAL_PATH)/art-profile
-
-LOCAL_SRC_FILES := $(call all-java-files-under,java)
-
-# EventLogTags files.
-LOCAL_SRC_FILES += \
-        core/java/com/android/server/EventLogTags.logtags
-
-# Uncomment to enable output of certain warnings (deprecated, unchecked)
-# LOCAL_JAVACFLAGS := -Xlint
-
-# Services that will be built as part of services.jar
-# These should map to directory names relative to this
-# Android.mk.
-services := \
-    core \
-    accessibility \
-    appwidget \
-    autofill \
-    backup \
-    companion \
-    coverage\
-    devicepolicy \
-    midi \
-    net \
-    print \
-    restrictions \
-    usage \
-    usb \
-    voiceinteraction
-
-# The convention is to name each service module 'services.$(module_name)'
-LOCAL_STATIC_JAVA_LIBRARIES := $(addprefix services.,$(services)) \
-    android.hidl.base-V1.0-java \
-    android.hardware.biometrics.fingerprint-V2.1-java
-
-LOCAL_JAVA_LIBRARIES := \
-    android.hidl.manager-V1.0-java
-
-ifeq ($(EMMA_INSTRUMENT_FRAMEWORK),true)
-LOCAL_EMMA_INSTRUMENT := true
-endif
-
-include $(BUILD_JAVA_LIBRARY)
-
-# =============================================================
-
-ifeq (,$(ONE_SHOT_MAKEFILE))
-# A full make is happening, so make everything.
-include $(call all-makefiles-under,$(LOCAL_PATH))
-else
-# If we ran an mm[m] command, we still want to build the individual
-# services that we depend on. This differs from the above condition
-# by only including service makefiles and not any tests or other
-# modules.
-include $(patsubst %,$(LOCAL_PATH)/%/Android.mk,$(services))
-endif
-
diff --git a/services/accessibility/Android.bp b/services/accessibility/Android.bp
new file mode 100644
index 0000000..f991d7b
--- /dev/null
+++ b/services/accessibility/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+    name: "services.accessibility",
+    srcs: ["java/**/*.java"],
+    libs: ["services.core"],
+}
diff --git a/services/accessibility/Android.mk b/services/accessibility/Android.mk
deleted file mode 100644
index ce89aa7..0000000
--- a/services/accessibility/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.accessibility
-
-LOCAL_SRC_FILES += \
-      $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityClientConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityClientConnection.java
index 7e94d7b..01679dd 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityClientConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityClientConnection.java
@@ -20,9 +20,7 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
 
-import android.accessibilityservice.AccessibilityService;
 import android.accessibilityservice.AccessibilityServiceInfo;
-import android.accessibilityservice.GestureDescription;
 import android.accessibilityservice.IAccessibilityServiceClient;
 import android.accessibilityservice.IAccessibilityServiceConnection;
 import android.annotation.NonNull;
@@ -49,7 +47,6 @@
 import android.view.View;
 import android.view.accessibility.AccessibilityCache;
 import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityInteractionClient;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityWindowInfo;
 import android.view.accessibility.IAccessibilityInteractionConnection;
@@ -58,6 +55,7 @@
 
 import com.android.internal.os.SomeArgs;
 import com.android.internal.util.DumpUtils;
+import com.android.server.accessibility.AccessibilityManagerService.RemoteAccessibilityConnection;
 import com.android.server.accessibility.AccessibilityManagerService.SecurityPolicy;
 import com.android.server.wm.WindowManagerInternal;
 
@@ -171,13 +169,13 @@
         @NonNull MagnificationController getMagnificationController();
 
         /**
-         * Resolve a connection for a window id
+         * Resolve a connection wrapper for a window id
          *
          * @param windowId The id of the window of interest
          *
          * @return a connection to the window
          */
-        IAccessibilityInteractionConnection getConnectionLocked(int windowId);
+        RemoteAccessibilityConnection getConnectionLocked(int windowId);
 
         /**
          * Perform the specified accessibility action
@@ -416,28 +414,28 @@
     }
 
     @Override
-    public boolean findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
+    public String[] findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
             long accessibilityNodeId, String viewIdResName, int interactionId,
             IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
             throws RemoteException {
         final int resolvedWindowId;
-        IAccessibilityInteractionConnection connection = null;
+        RemoteAccessibilityConnection connection;
         Region partialInteractiveRegion = Region.obtain();
         MagnificationSpec spec;
         synchronized (mLock) {
             mUsesAccessibilityCache = true;
             if (!isCalledForCurrentUserLocked()) {
-                return false;
+                return null;
             }
             resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
             final boolean permissionGranted =
                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
             if (!permissionGranted) {
-                return false;
+                return null;
             } else {
                 connection = mSystemSupport.getConnectionLocked(resolvedWindowId);
                 if (connection == null) {
-                    return false;
+                    return null;
                 }
             }
             if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
@@ -450,12 +448,14 @@
         final int interrogatingPid = Binder.getCallingPid();
         callback = mSystemSupport.replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
                 interrogatingPid, interrogatingTid);
+        final int callingUid = Binder.getCallingUid();
         final long identityToken = Binder.clearCallingIdentity();
         try {
-            connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId, viewIdResName,
-                    partialInteractiveRegion, interactionId, callback, mFetchFlags,
+            connection.getRemote().findAccessibilityNodeInfosByViewId(accessibilityNodeId,
+                    viewIdResName, partialInteractiveRegion, interactionId, callback, mFetchFlags,
                     interrogatingPid, interrogatingTid, spec);
-            return true;
+            return mSecurityPolicy.computeValidReportedPackages(callingUid,
+                    connection.getPackageName(), connection.getUid());
         } catch (RemoteException re) {
             if (DEBUG) {
                 Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId().");
@@ -463,36 +463,36 @@
         } finally {
             Binder.restoreCallingIdentity(identityToken);
             // Recycle if passed to another process.
-            if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
+            if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
                 partialInteractiveRegion.recycle();
             }
         }
-        return false;
+        return null;
     }
 
     @Override
-    public boolean findAccessibilityNodeInfosByText(int accessibilityWindowId,
+    public String[] findAccessibilityNodeInfosByText(int accessibilityWindowId,
             long accessibilityNodeId, String text, int interactionId,
             IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
             throws RemoteException {
         final int resolvedWindowId;
-        IAccessibilityInteractionConnection connection = null;
+        RemoteAccessibilityConnection connection;
         Region partialInteractiveRegion = Region.obtain();
         MagnificationSpec spec;
         synchronized (mLock) {
             mUsesAccessibilityCache = true;
             if (!isCalledForCurrentUserLocked()) {
-                return false;
+                return null;
             }
             resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
             final boolean permissionGranted =
                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
             if (!permissionGranted) {
-                return false;
+                return null;
             } else {
                 connection = mSystemSupport.getConnectionLocked(resolvedWindowId);
                 if (connection == null) {
-                    return false;
+                    return null;
                 }
             }
             if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
@@ -505,12 +505,14 @@
         final int interrogatingPid = Binder.getCallingPid();
         callback = mSystemSupport.replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
                 interrogatingPid, interrogatingTid);
+        final int callingUid = Binder.getCallingUid();
         final long identityToken = Binder.clearCallingIdentity();
         try {
-            connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text,
-                    partialInteractiveRegion, interactionId, callback, mFetchFlags,
+            connection.getRemote().findAccessibilityNodeInfosByText(accessibilityNodeId,
+                    text, partialInteractiveRegion, interactionId, callback, mFetchFlags,
                     interrogatingPid, interrogatingTid, spec);
-            return true;
+            return mSecurityPolicy.computeValidReportedPackages(callingUid,
+                    connection.getPackageName(), connection.getUid());
         } catch (RemoteException re) {
             if (DEBUG) {
                 Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()");
@@ -518,36 +520,36 @@
         } finally {
             Binder.restoreCallingIdentity(identityToken);
             // Recycle if passed to another process.
-            if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
+            if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
                 partialInteractiveRegion.recycle();
             }
         }
-        return false;
+        return null;
     }
 
     @Override
-    public boolean findAccessibilityNodeInfoByAccessibilityId(
+    public String[] findAccessibilityNodeInfoByAccessibilityId(
             int accessibilityWindowId, long accessibilityNodeId, int interactionId,
             IAccessibilityInteractionConnectionCallback callback, int flags,
             long interrogatingTid, Bundle arguments) throws RemoteException {
         final int resolvedWindowId;
-        IAccessibilityInteractionConnection connection = null;
+        RemoteAccessibilityConnection connection;
         Region partialInteractiveRegion = Region.obtain();
         MagnificationSpec spec;
         synchronized (mLock) {
             mUsesAccessibilityCache = true;
             if (!isCalledForCurrentUserLocked()) {
-                return false;
+                return null;
             }
             resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
             final boolean permissionGranted =
                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
             if (!permissionGranted) {
-                return false;
+                return null;
             } else {
                 connection = mSystemSupport.getConnectionLocked(resolvedWindowId);
                 if (connection == null) {
-                    return false;
+                    return null;
                 }
             }
             if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
@@ -560,12 +562,14 @@
         final int interrogatingPid = Binder.getCallingPid();
         callback = mSystemSupport.replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
                 interrogatingPid, interrogatingTid);
+        final int callingUid = Binder.getCallingUid();
         final long identityToken = Binder.clearCallingIdentity();
         try {
-            connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId,
-                    partialInteractiveRegion, interactionId, callback, mFetchFlags | flags,
-                    interrogatingPid, interrogatingTid, spec, arguments);
-            return true;
+            connection.getRemote().findAccessibilityNodeInfoByAccessibilityId(
+                    accessibilityNodeId, partialInteractiveRegion, interactionId, callback,
+                    mFetchFlags | flags, interrogatingPid, interrogatingTid, spec, arguments);
+            return mSecurityPolicy.computeValidReportedPackages(callingUid,
+                    connection.getPackageName(), connection.getUid());
         } catch (RemoteException re) {
             if (DEBUG) {
                 Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()");
@@ -573,36 +577,36 @@
         } finally {
             Binder.restoreCallingIdentity(identityToken);
             // Recycle if passed to another process.
-            if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
+            if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
                 partialInteractiveRegion.recycle();
             }
         }
-        return false;
+        return null;
     }
 
     @Override
-    public boolean findFocus(int accessibilityWindowId, long accessibilityNodeId,
+    public String[] findFocus(int accessibilityWindowId, long accessibilityNodeId,
             int focusType, int interactionId,
             IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
             throws RemoteException {
         final int resolvedWindowId;
-        IAccessibilityInteractionConnection connection = null;
+        RemoteAccessibilityConnection connection;
         Region partialInteractiveRegion = Region.obtain();
         MagnificationSpec spec;
         synchronized (mLock) {
             if (!isCalledForCurrentUserLocked()) {
-                return false;
+                return null;
             }
             resolvedWindowId = resolveAccessibilityWindowIdForFindFocusLocked(
                     accessibilityWindowId, focusType);
             final boolean permissionGranted =
                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
             if (!permissionGranted) {
-                return false;
+                return null;
             } else {
                 connection = mSystemSupport.getConnectionLocked(resolvedWindowId);
                 if (connection == null) {
-                    return false;
+                    return null;
                 }
             }
             if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
@@ -615,12 +619,14 @@
         final int interrogatingPid = Binder.getCallingPid();
         callback = mSystemSupport.replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
                 interrogatingPid, interrogatingTid);
+        final int callingUid = Binder.getCallingUid();
         final long identityToken = Binder.clearCallingIdentity();
         try {
-            connection.findFocus(accessibilityNodeId, focusType, partialInteractiveRegion,
-                    interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
-                    spec);
-            return true;
+            connection.getRemote().findFocus(accessibilityNodeId, focusType,
+                    partialInteractiveRegion, interactionId, callback, mFetchFlags,
+                    interrogatingPid, interrogatingTid, spec);
+            return mSecurityPolicy.computeValidReportedPackages(callingUid,
+                    connection.getPackageName(), connection.getUid());
         } catch (RemoteException re) {
             if (DEBUG) {
                 Slog.e(LOG_TAG, "Error calling findFocus()");
@@ -628,35 +634,35 @@
         } finally {
             Binder.restoreCallingIdentity(identityToken);
             // Recycle if passed to another process.
-            if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
+            if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
                 partialInteractiveRegion.recycle();
             }
         }
-        return false;
+        return null;
     }
 
     @Override
-    public boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId,
+    public String[] focusSearch(int accessibilityWindowId, long accessibilityNodeId,
             int direction, int interactionId,
             IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
             throws RemoteException {
         final int resolvedWindowId;
-        IAccessibilityInteractionConnection connection = null;
+        RemoteAccessibilityConnection connection;
         Region partialInteractiveRegion = Region.obtain();
         MagnificationSpec spec;
         synchronized (mLock) {
             if (!isCalledForCurrentUserLocked()) {
-                return false;
+                return null;
             }
             resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
             final boolean permissionGranted =
                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
             if (!permissionGranted) {
-                return false;
+                return null;
             } else {
                 connection = mSystemSupport.getConnectionLocked(resolvedWindowId);
                 if (connection == null) {
-                    return false;
+                    return null;
                 }
             }
             if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
@@ -669,12 +675,14 @@
         final int interrogatingPid = Binder.getCallingPid();
         callback = mSystemSupport.replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
                 interrogatingPid, interrogatingTid);
+        final int callingUid = Binder.getCallingUid();
         final long identityToken = Binder.clearCallingIdentity();
         try {
-            connection.focusSearch(accessibilityNodeId, direction, partialInteractiveRegion,
-                    interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
-                    spec);
-            return true;
+            connection.getRemote().focusSearch(accessibilityNodeId, direction,
+                    partialInteractiveRegion, interactionId, callback, mFetchFlags,
+                    interrogatingPid, interrogatingTid, spec);
+            return mSecurityPolicy.computeValidReportedPackages(callingUid,
+                    connection.getPackageName(), connection.getUid());
         } catch (RemoteException re) {
             if (DEBUG) {
                 Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()");
@@ -682,11 +690,11 @@
         } finally {
             Binder.restoreCallingIdentity(identityToken);
             // Recycle if passed to another process.
-            if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
+            if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
                 partialInteractiveRegion.recycle();
             }
         }
-        return false;
+        return null;
     }
 
     @Override
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 0a21b9e..ac0cdd7 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -24,12 +24,12 @@
 import android.accessibilityservice.AccessibilityService;
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.accessibilityservice.IAccessibilityServiceClient;
-import android.accessibilityservice.IAccessibilityServiceConnection;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManagerInternal;
 import android.app.AlertDialog;
 import android.app.PendingIntent;
+import android.appwidget.AppWidgetManagerInternal;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -72,6 +72,7 @@
 import android.provider.SettingsStringUtil.SettingStringHelper;
 import android.text.TextUtils;
 import android.text.TextUtils.SimpleStringSplitter;
+import android.util.ArraySet;
 import android.util.IntArray;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -97,6 +98,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.content.PackageMonitor;
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IntPair;
 import com.android.server.LocalServices;
@@ -104,6 +106,7 @@
 import com.android.internal.accessibility.AccessibilityShortcutController.ToggleableFrameworkFeatureInfo;
 import com.android.server.wm.WindowManagerInternal;
 
+import libcore.util.EmptyArray;
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.FileDescriptor;
@@ -186,6 +189,8 @@
 
     private final WindowManagerInternal mWindowManagerService;
 
+    private AppWidgetManagerInternal mAppWidgetService;
+
     private final SecurityPolicy mSecurityPolicy;
 
     private final MainHandler mMainHandler;
@@ -218,10 +223,10 @@
     private final RemoteCallbackList<IAccessibilityManagerClient> mGlobalClients =
             new RemoteCallbackList<>();
 
-    private final SparseArray<AccessibilityConnectionWrapper> mGlobalInteractionConnections =
+    private final SparseArray<RemoteAccessibilityConnection> mGlobalInteractionConnections =
             new SparseArray<>();
 
-    private AccessibilityConnectionWrapper mPictureInPictureActionReplacingConnection;
+    private RemoteAccessibilityConnection mPictureInPictureActionReplacingConnection;
 
     private final SparseArray<IBinder> mGlobalWindowTokens = new SparseArray<>();
 
@@ -453,6 +458,7 @@
             // performs the current profile parent resolution.
             final int resolvedUserId = mSecurityPolicy
                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
+
             // If the client is from a process that runs across users such as
             // the system UI or the system we add it to the global state that
             // is shared across users.
@@ -497,9 +503,14 @@
 
             // We treat calls from a profile as if made by its parent as profiles
             // share the accessibility state of the parent. The call below
-            // performs the current profile parent resolution..
+            // performs the current profile parent resolution.
             final int resolvedUserId = mSecurityPolicy
                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
+
+            // Make sure the reported package is one the caller has access to.
+            event.setPackageName(mSecurityPolicy.resolveValidReportedPackageLocked(
+                    event.getPackageName(), UserHandle.getCallingAppId(), resolvedUserId));
+
             // This method does nothing for a background user.
             if (resolvedUserId == mCurrentUserId) {
                 if (mSecurityPolicy.canDispatchAccessibilityEventLocked(event)) {
@@ -617,30 +628,38 @@
 
     @Override
     public int addAccessibilityInteractionConnection(IWindow windowToken,
-            IAccessibilityInteractionConnection connection, int userId) throws RemoteException {
+            IAccessibilityInteractionConnection connection, String packageName,
+            int userId) throws RemoteException {
         synchronized (mLock) {
             // We treat calls from a profile as if made by its parent as profiles
             // share the accessibility state of the parent. The call below
             // performs the current profile parent resolution.
             final int resolvedUserId = mSecurityPolicy
                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
+            final int resolvedUid = UserHandle.getUid(resolvedUserId, UserHandle.getCallingAppId());
+
+            // Make sure the reported package is one the caller has access to.
+            packageName = mSecurityPolicy.resolveValidReportedPackageLocked(
+                    packageName, UserHandle.getCallingAppId(), resolvedUserId);
+
             final int windowId = sNextWindowId++;
             // If the window is from a process that runs across users such as
             // the system UI or the system we add it to the global state that
             // is shared across users.
             if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) {
-                AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
-                        windowId, connection, UserHandle.USER_ALL);
+                RemoteAccessibilityConnection wrapper = new RemoteAccessibilityConnection(
+                        windowId, connection, packageName, resolvedUid, UserHandle.USER_ALL);
                 wrapper.linkToDeath();
                 mGlobalInteractionConnections.put(windowId, wrapper);
                 mGlobalWindowTokens.put(windowId, windowToken.asBinder());
                 if (DEBUG) {
                     Slog.i(LOG_TAG, "Added global connection for pid:" + Binder.getCallingPid()
-                            + " with windowId: " + windowId + " and  token: " + windowToken.asBinder());
+                            + " with windowId: " + windowId + " and  token: "
+                            + windowToken.asBinder());
                 }
             } else {
-                AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
-                        windowId, connection, resolvedUserId);
+                RemoteAccessibilityConnection wrapper = new RemoteAccessibilityConnection(
+                        windowId, connection, packageName, resolvedUid, resolvedUserId);
                 wrapper.linkToDeath();
                 UserState userState = getUserStateLocked(resolvedUserId);
                 userState.mInteractionConnections.put(windowId, wrapper);
@@ -693,13 +712,13 @@
 
     private int removeAccessibilityInteractionConnectionInternalLocked(IBinder windowToken,
             SparseArray<IBinder> windowTokens,
-            SparseArray<AccessibilityConnectionWrapper> interactionConnections) {
+            SparseArray<RemoteAccessibilityConnection> interactionConnections) {
         final int count = windowTokens.size();
         for (int i = 0; i < count; i++) {
             if (windowTokens.valueAt(i) == windowToken) {
                 final int windowId = windowTokens.keyAt(i);
                 windowTokens.removeAt(i);
-                AccessibilityConnectionWrapper wrapper = interactionConnections.get(windowId);
+                RemoteAccessibilityConnection wrapper = interactionConnections.get(windowId);
                 wrapper.unlinkToDeath();
                 interactionConnections.remove(windowId);
                 return windowId;
@@ -719,9 +738,9 @@
                 mPictureInPictureActionReplacingConnection = null;
             }
             if (connection != null) {
-                AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
+                RemoteAccessibilityConnection wrapper = new RemoteAccessibilityConnection(
                         AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID,
-                        connection, UserHandle.USER_ALL);
+                        connection, "foo.bar.baz", Process.SYSTEM_UID, UserHandle.USER_ALL);
                 mPictureInPictureActionReplacingConnection = wrapper;
                 wrapper.linkToDeath();
             }
@@ -2264,18 +2283,35 @@
         }
     }
 
-    private class AccessibilityConnectionWrapper implements DeathRecipient {
+    class RemoteAccessibilityConnection implements DeathRecipient {
+        private final int mUid;
+        private final String mPackageName;
         private final int mWindowId;
         private final int mUserId;
         private final IAccessibilityInteractionConnection mConnection;
 
-        public AccessibilityConnectionWrapper(int windowId,
-                IAccessibilityInteractionConnection connection, int userId) {
+        RemoteAccessibilityConnection(int windowId,
+                IAccessibilityInteractionConnection connection,
+                String packageName, int uid, int userId) {
             mWindowId = windowId;
+            mPackageName = packageName;
+            mUid = uid;
             mUserId = userId;
             mConnection = connection;
         }
 
+        public int getUid() {
+            return  mUid;
+        }
+
+        public String getPackageName() {
+            return mPackageName;
+        }
+
+        public IAccessibilityInteractionConnection getRemote() {
+            return mConnection;
+        }
+
         public void linkToDeath() throws RemoteException {
             mConnection.asBinder().linkToDeath(this, 0);
         }
@@ -2532,11 +2568,13 @@
             long accessibilityNodeId, int action, Bundle arguments, int interactionId,
             IAccessibilityInteractionConnectionCallback callback, int fetchFlags,
             long interrogatingTid) {
-        IAccessibilityInteractionConnection connection = null;
+        RemoteAccessibilityConnection connection;
         IBinder activityToken = null;
         synchronized (mLock) {
             connection = getConnectionLocked(resolvedWindowId);
-            if (connection == null)  return false;
+            if (connection == null)  {
+                return false;
+            }
             final boolean isA11yFocusAction = (action == ACTION_ACCESSIBILITY_FOCUS)
                     || (action == ACTION_CLEAR_ACCESSIBILITY_FOCUS);
             final AccessibilityWindowInfo a11yWindowInfo =
@@ -2548,7 +2586,7 @@
             }
             if ((a11yWindowInfo != null) && a11yWindowInfo.isInPictureInPictureMode()
                     && (mPictureInPictureActionReplacingConnection != null) && !isA11yFocusAction) {
-                connection = mPictureInPictureActionReplacingConnection.mConnection;
+                connection = mPictureInPictureActionReplacingConnection;
             }
         }
         final int interrogatingPid = Binder.getCallingPid();
@@ -2563,8 +2601,9 @@
                 LocalServices.getService(ActivityManagerInternal.class)
                         .setFocusedActivity(activityToken);
             }
-            connection.performAccessibilityAction(accessibilityNodeId, action, arguments,
-                    interactionId, callback, fetchFlags, interrogatingPid, interrogatingTid);
+            connection.mConnection.performAccessibilityAction(accessibilityNodeId, action,
+                    arguments, interactionId, callback, fetchFlags, interrogatingPid,
+                    interrogatingTid);
         } catch (RemoteException re) {
             if (DEBUG) {
                 Slog.e(LOG_TAG, "Error calling performAccessibilityAction: " + re);
@@ -2577,17 +2616,17 @@
     }
 
     @Override
-    public IAccessibilityInteractionConnection getConnectionLocked(int windowId) {
+    public RemoteAccessibilityConnection getConnectionLocked(int windowId) {
         if (DEBUG) {
             Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId);
         }
-        AccessibilityManagerService.AccessibilityConnectionWrapper wrapper =
+        RemoteAccessibilityConnection connection =
                 mGlobalInteractionConnections.get(windowId);
-        if (wrapper == null) {
-            wrapper = getCurrentUserStateLocked().mInteractionConnections.get(windowId);
+        if (connection == null) {
+            connection = getCurrentUserStateLocked().mInteractionConnections.get(windowId);
         }
-        if (wrapper != null && wrapper.mConnection != null) {
-            return wrapper.mConnection;
+        if (connection != null && connection.mConnection != null) {
+            return connection;
         }
         if (DEBUG) {
             Slog.e(LOG_TAG, "No interaction connection to window: " + windowId);
@@ -2620,6 +2659,16 @@
         }
     }
 
+    private AppWidgetManagerInternal getAppWidgetManager() {
+        synchronized (mLock) {
+            if (mAppWidgetService == null
+                    && mPackageManager.hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS)) {
+                mAppWidgetService = LocalServices.getService(AppWidgetManagerInternal.class);
+            }
+            return mAppWidgetService;
+        }
+    }
+
     final class WindowsForAccessibilityCallback implements
             WindowManagerInternal.WindowsForAccessibilityCallback {
 
@@ -2912,6 +2961,78 @@
             }
         }
 
+        private boolean isValidPackageForUid(String packageName, int uid) {
+            try {
+                return uid == mPackageManager.getPackageUidAsUser(
+                        packageName, UserHandle.getUserId(uid));
+            } catch (PackageManager.NameNotFoundException e) {
+                return false;
+            }
+        }
+
+        String resolveValidReportedPackageLocked(CharSequence packageName, int appId, int userId) {
+            // Okay to pass no package
+            if (packageName == null) {
+                return null;
+            }
+            // The system gets to pass any package
+            if (appId == Process.SYSTEM_UID) {
+                return packageName.toString();
+            }
+            // Passing a package in your UID is fine
+            final String packageNameStr = packageName.toString();
+            final int resolvedUid = UserHandle.getUid(userId, appId);
+            if (isValidPackageForUid(packageNameStr, resolvedUid)) {
+                return packageName.toString();
+            }
+            // Appwidget hosts get to pass packages for widgets they host
+            final AppWidgetManagerInternal appWidgetManager = getAppWidgetManager();
+            if (appWidgetManager != null && ArrayUtils.contains(appWidgetManager
+                            .getHostedWidgetPackages(resolvedUid), packageNameStr)) {
+                return packageName.toString();
+            }
+            // Otherwise, set the package to the first one in the UID
+            final String[] packageNames = mPackageManager.getPackagesForUid(resolvedUid);
+            if (ArrayUtils.isEmpty(packageNames)) {
+                return null;
+            }
+            // Okay, the caller reported a package it does not have access to.
+            // Instead of crashing the caller for better backwards compatibility
+            // we report the first package in the UID. Since most of the time apps
+            // don't use shared user id, this will yield correct results and for
+            // the edge case of using a shared user id we may report the wrong
+            // package but this is fine since first, this is a cheating app and
+            // second there is no way to get the correct package anyway.
+            return packageNames[0];
+        }
+
+        String[] computeValidReportedPackages(int callingUid,
+                String targetPackage, int targetUid) {
+            if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
+                // Empty array means any package is Okay
+                return EmptyArray.STRING;
+            }
+            // IMPORTANT: The target package is already vetted to be in the target UID
+            String[] uidPackages = new String[]{targetPackage};
+            // Appwidget hosts get to pass packages for widgets they host
+            final AppWidgetManagerInternal appWidgetManager = getAppWidgetManager();
+            if (appWidgetManager != null) {
+                final ArraySet<String> widgetPackages = appWidgetManager
+                        .getHostedWidgetPackages(targetUid);
+                if (widgetPackages != null && !widgetPackages.isEmpty()) {
+                    final String[] validPackages = new String[uidPackages.length
+                            + widgetPackages.size()];
+                    System.arraycopy(uidPackages, 0, validPackages, 0, uidPackages.length);
+                    final int widgetPackageCount = widgetPackages.size();
+                    for (int i = 0; i < widgetPackageCount; i++) {
+                        validPackages[uidPackages.length + i] = widgetPackages.valueAt(i);
+                    }
+                    return validPackages;
+                }
+            }
+            return uidPackages;
+        }
+
         public void clearWindowsLocked() {
             List<WindowInfo> windows = Collections.emptyList();
             final int activeWindowId = mActiveWindowId;
@@ -3338,7 +3459,7 @@
         public final RemoteCallbackList<IAccessibilityManagerClient> mUserClients =
             new RemoteCallbackList<>();
 
-        public final SparseArray<AccessibilityConnectionWrapper> mInteractionConnections =
+        public final SparseArray<RemoteAccessibilityConnection> mInteractionConnections =
                 new SparseArray<>();
 
         public final SparseArray<IBinder> mWindowTokens = new SparseArray<>();
diff --git a/services/appwidget/Android.bp b/services/appwidget/Android.bp
new file mode 100644
index 0000000..aad2ad19
--- /dev/null
+++ b/services/appwidget/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+    name: "services.appwidget",
+    srcs: ["java/**/*.java"],
+    libs: ["services.core"],
+}
diff --git a/services/appwidget/Android.mk b/services/appwidget/Android.mk
deleted file mode 100644
index e9bab4a..0000000
--- a/services/appwidget/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.appwidget
-
-LOCAL_SRC_FILES += \
-      $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index b446209..54cf726 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -32,6 +32,7 @@
 import android.app.admin.DevicePolicyManagerInternal;
 import android.app.admin.DevicePolicyManagerInternal.OnCrossProfileWidgetProvidersChangeListener;
 import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetManagerInternal;
 import android.appwidget.AppWidgetProviderInfo;
 import android.appwidget.PendingHostUpdate;
 import android.content.BroadcastReceiver;
@@ -100,6 +101,8 @@
 import com.android.internal.appwidget.IAppWidgetService;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.os.SomeArgs;
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.widget.IRemoteViewsFactory;
@@ -107,6 +110,7 @@
 import com.android.server.WidgetBackupProvider;
 import com.android.server.policy.IconUtilities;
 
+import libcore.util.EmptyArray;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
@@ -259,6 +263,8 @@
         computeMaximumWidgetBitmapMemory();
         registerBroadcastReceiver();
         registerOnCrossProfileProvidersChangedListener();
+
+        LocalServices.addService(AppWidgetManagerInternal.class, new AppWidgetManagerLocal());
     }
 
     private void computeMaximumWidgetBitmapMemory() {
@@ -4630,4 +4636,24 @@
             }
         }
     }
+
+    private class AppWidgetManagerLocal extends AppWidgetManagerInternal {
+        @Override
+        public ArraySet<String> getHostedWidgetPackages(int uid) {
+            synchronized (mLock) {
+                ArraySet<String> widgetPackages = null;
+                final int widgetCount = mWidgets.size();
+                for (int i = 0; i < widgetCount; i++) {
+                    final Widget widget = mWidgets.get(i);
+                    if  (widget.host.id.uid == uid) {
+                        if (widgetPackages == null) {
+                            widgetPackages = new ArraySet<>();
+                        }
+                        widgetPackages.add(widget.provider.id.componentName.getPackageName());
+                    }
+                }
+                return widgetPackages;
+            }
+        }
+    }
 }
diff --git a/services/autofill/Android.bp b/services/autofill/Android.bp
new file mode 100644
index 0000000..2768c18
--- /dev/null
+++ b/services/autofill/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+    name: "services.autofill",
+    srcs: ["java/**/*.java"],
+    libs: ["services.core"],
+}
diff --git a/services/autofill/Android.mk b/services/autofill/Android.mk
deleted file mode 100644
index a1f19fd..0000000
--- a/services/autofill/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.autofill
-
-LOCAL_SRC_FILES += \
-      $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index b2a0ce5..7bc63f0 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -36,6 +36,7 @@
 import android.content.pm.ServiceInfo;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.metrics.LogMaker;
 import android.os.AsyncTask;
 import android.os.Binder;
 import android.os.Bundle;
@@ -352,7 +353,7 @@
         pruneAbandonedSessionsLocked();
 
         final Session newSession = createSessionByTokenLocked(activityToken, uid, appCallbackToken,
-                hasCallback, componentName);
+                hasCallback, componentName, flags);
         if (newSession == null) {
             return NO_SESSION;
         }
@@ -453,7 +454,7 @@
 
     private Session createSessionByTokenLocked(@NonNull IBinder activityToken, int uid,
             @NonNull IBinder appCallbackToken, boolean hasCallback,
-            @NonNull ComponentName componentName) {
+            @NonNull ComponentName componentName, int flags) {
         // use random ids so that one app cannot know that another app creates sessions
         int sessionId;
         int tries = 0;
@@ -471,7 +472,7 @@
 
         final Session newSession = new Session(this, mUi, mContext, mHandlerCaller, mUserId, mLock,
                 sessionId, uid, activityToken, appCallbackToken, hasCallback,
-                mUiLatencyHistory, mInfo.getServiceInfo().getComponentName(), componentName);
+                mUiLatencyHistory, mInfo.getServiceInfo().getComponentName(), componentName, flags);
         mSessions.put(newSession.id, newSession);
 
         return newSession;
@@ -716,7 +717,8 @@
             @Nullable ArrayList<AutofillId> manuallyFilledFieldIds,
             @Nullable ArrayList<ArrayList<String>> manuallyFilledDatasetIds,
             @Nullable ArrayList<AutofillId> detectedFieldIdsList,
-            @Nullable ArrayList<Match> detectedMatchesList) {
+            @Nullable ArrayList<Match> detectedMatchesList,
+            @NonNull String appPackageName) {
 
         synchronized (mLock) {
             if (isValidEventLocked("logDatasetNotSelected()", sessionId)) {
@@ -727,6 +729,19 @@
                     detectedFieldIdsList.toArray(detectedFieldsIds);
                     detectedMatches = new Match[detectedMatchesList.size()];
                     detectedMatchesList.toArray(detectedMatches);
+
+                    final int size = detectedMatchesList.size();
+                    float totalScore = 0;
+                    for (int i = 0; i < size; i++) {
+                        totalScore += detectedMatches[i].getScore();
+                    }
+                    final int averageScore = (int) ((totalScore * 100) / size);
+                    mMetricsLogger.write(
+                            Helper.newLogMaker(MetricsEvent.AUTOFILL_FIELD_CLASSIFICATION_MATCHES,
+                                    appPackageName, getServicePackageName())
+                            .setCounterValue(size)
+                            .addTaggedData(MetricsEvent.FIELD_AUTOFILL_MATCH_SCORE, averageScore));
+
                 }
                 mEventHistory.addEvent(new Event(Event.TYPE_CONTEXT_COMMITTED, null,
                         clientState, selectedDatasets, ignoredDatasets,
@@ -776,6 +791,11 @@
         synchronized (mLock) {
             if (isCalledByServiceLocked("setUserData", callingUid)) {
                 mUserData = userData;
+                // Log it
+                int numberFields = mUserData == null ? 0: mUserData.getRemoteIds().length;
+                mMetricsLogger.write(Helper.newLogMaker(MetricsEvent.AUTOFILL_USERDATA_UPDATED,
+                        getServicePackageName(), null)
+                        .setCounterValue(numberFields));
             }
         }
     }
@@ -1013,10 +1033,12 @@
                 expiration = Long.MAX_VALUE;
             }
             mDisabledActivities.put(componentName, expiration);
-            int intDuration = duration > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) duration;
-            mMetricsLogger.write(Helper.newLogMaker(MetricsEvent.AUTOFILL_SERVICE_DISABLED_ACTIVITY,
-                    componentName.getPackageName(), getServicePackageName())
-                    .addTaggedData(MetricsEvent.FIELD_CLASS_NAME, componentName.getClassName())
+            final int intDuration = duration > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) duration;
+            // NOTE: not using Helper.newLogMaker() because we're setting the componentName instead
+            // of package name
+            mMetricsLogger.write(new LogMaker(MetricsEvent.AUTOFILL_SERVICE_DISABLED_ACTIVITY)
+                    .setComponentName(componentName)
+                    .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, getServicePackageName())
                     .setCounterValue(intDuration));
         }
     }
@@ -1034,7 +1056,8 @@
                 if (expiration >= elapsedTime) return true;
                 // Restriction expired - clean it up.
                 if (sVerbose) {
-                    Slog.v(TAG, "Removing " + componentName.toShortString() + " from disabled list");
+                    Slog.v(TAG, "Removing " + componentName.toShortString()
+                        + " from disabled list");
                 }
                 mDisabledActivities.remove(componentName);
             }
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 4e64afb..56f5f64 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -128,6 +128,9 @@
     /** uid the session is for */
     public final int uid;
 
+    /** Flags used to start the session */
+    public final int mFlags;
+
     @GuardedBy("mLock")
     @NonNull private IBinder mActivityToken;
 
@@ -441,8 +444,10 @@
             @NonNull Context context, @NonNull HandlerCaller handlerCaller, int userId,
             @NonNull Object lock, int sessionId, int uid, @NonNull IBinder activityToken,
             @NonNull IBinder client, boolean hasCallback, @NonNull LocalLog uiLatencyHistory,
-            @NonNull ComponentName serviceComponentName, @NonNull ComponentName componentName) {
+            @NonNull ComponentName serviceComponentName, @NonNull ComponentName componentName,
+            int flags) {
         id = sessionId;
+        mFlags = flags;
         this.uid = uid;
         mStartTime = SystemClock.elapsedRealtime();
         mService = service;
@@ -456,7 +461,8 @@
         mComponentName = componentName;
         mClient = IAutoFillManagerClient.Stub.asInterface(client);
 
-        writeLog(MetricsEvent.AUTOFILL_SESSION_STARTED);
+        mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_SESSION_STARTED)
+                .addTaggedData(MetricsEvent.FIELD_FLAGS, flags));
     }
 
     /**
@@ -505,8 +511,9 @@
             }
         }
 
-        // TODO(b/67867469): remove once feature is finished
-        if (response.getFieldClassificationIds() != null && !mService.isFieldClassificationEnabled()) {
+        final AutofillId[] fieldClassificationIds = response.getFieldClassificationIds();
+        // TODO(b/67867469): remove once feature is finished (or use method from AFM to check)
+        if (fieldClassificationIds != null && !mService.isFieldClassificationEnabled()) {
             Slog.w(TAG, "Ignoring " + response + " because field detection is disabled");
             processNullResponseLocked(requestFlags);
             return;
@@ -548,6 +555,10 @@
                 .setType(MetricsEvent.TYPE_SUCCESS)
                 .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS,
                         response.getDatasets() == null ? 0 : response.getDatasets().size());
+        if (fieldClassificationIds != null) {
+            log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_FIELD_CLASSIFICATION_IDS,
+                    fieldClassificationIds.length);
+        }
         mMetricsLogger.write(log);
     }
 
@@ -1106,7 +1117,7 @@
         mService.logContextCommitted(id, mClientState, mSelectedDatasetIds, ignoredDatasets,
                 changedFieldIds, changedDatasetIds,
                 manuallyFilledFieldIds, manuallyFilledDatasetIds,
-                detectedFieldIds, detectedMatches);
+                detectedFieldIds, detectedMatches, mComponentName.getPackageName());
     }
 
     /**
@@ -2115,6 +2126,7 @@
         final String prefix2 = prefix + "  ";
         pw.print(prefix); pw.print("id: "); pw.println(id);
         pw.print(prefix); pw.print("uid: "); pw.println(uid);
+        pw.print(prefix); pw.print("flags: "); pw.println(mFlags);
         pw.print(prefix); pw.print("mComponentName: "); pw.println(mComponentName);
         pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken);
         pw.print(prefix); pw.print("mStartTime: "); pw.println(mStartTime);
diff --git a/services/backup/Android.bp b/services/backup/Android.bp
new file mode 100644
index 0000000..ef03d83
--- /dev/null
+++ b/services/backup/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+    name: "services.backup",
+    srcs: ["java/**/*.java"],
+    libs: ["services.core"],
+}
diff --git a/services/backup/Android.mk b/services/backup/Android.mk
deleted file mode 100644
index 3e686d1..0000000
--- a/services/backup/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.backup
-
-LOCAL_SRC_FILES += \
-      $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/companion/Android.bp b/services/companion/Android.bp
new file mode 100644
index 0000000..d2dac35
--- /dev/null
+++ b/services/companion/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+    name: "services.companion",
+    srcs: ["java/**/*.java"],
+    libs: ["services.core"],
+}
diff --git a/services/companion/Android.mk b/services/companion/Android.mk
deleted file mode 100644
index be48761..0000000
--- a/services/companion/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.companion
-
-LOCAL_SRC_FILES += \
-      $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/core/Android.bp b/services/core/Android.bp
new file mode 100644
index 0000000..446c2a5
--- /dev/null
+++ b/services/core/Android.bp
@@ -0,0 +1,57 @@
+java_library_static {
+    name: "services.core",
+
+    aidl: {
+        include_dirs: [
+            "frameworks/native/aidl/binder",
+            "system/core/storaged/binder",
+            "system/netd/server/binder",
+            "system/vold/binder",
+        ],
+    },
+    srcs: [
+        "java/**/*.java",
+        ":netd_aidl",
+        ":netd_metrics_aidl",
+        ":installd_aidl",
+        ":storaged_aidl",
+        ":vold_aidl",
+        "java/com/android/server/EventLogTags.logtags",
+        "java/com/android/server/am/EventLogTags.logtags",
+    ],
+
+    libs: [
+        "services.net",
+        "android.hardware.light-V2.0-java",
+        "android.hardware.power-V1.0-java",
+        "android.hardware.tv.cec-V1.0-java",
+        "android.hidl.manager-V1.0-java",
+    ],
+
+    static_libs: [
+        "time_zone_distro",
+        "time_zone_distro_installer",
+        "android.hardware.health-V1.0-java",
+        "android.hardware.health-V2.0-java",
+        "android.hardware.weaver-V1.0-java",
+        "android.hardware.biometrics.fingerprint-V2.1-java",
+        "android.hardware.oemlock-V1.0-java",
+        "android.hardware.tetheroffload.control-V1.0-java",
+        "android.hardware.vibrator-V1.0-java",
+        "android.hardware.configstore-V1.0-java",
+        "android.hardware.contexthub-V1.0-java",
+    ],
+}
+
+java_genrule {
+    name: "services.core.priorityboosted",
+    srcs: [":services.core"],
+    tools: ["lockedregioncodeinjection"],
+    cmd: "$(location lockedregioncodeinjection) " +
+        "  --targets \"Lcom/android/server/am/ActivityManagerService;,Lcom/android/server/wm/WindowHashMap;\" " +
+        "  --pre \"com/android/server/am/ActivityManagerService.boostPriorityForLockedSection,com/android/server/wm/WindowManagerService.boostPriorityForLockedSection\" " +
+        "  --post \"com/android/server/am/ActivityManagerService.resetPriorityAfterLockedSection,com/android/server/wm/WindowManagerService.resetPriorityAfterLockedSection\" " +
+        "  -o $(out) " +
+        "  -i $(in)",
+    out: ["services.core.priorityboosted.jar"],
+}
diff --git a/services/core/Android.mk b/services/core/Android.mk
deleted file mode 100644
index 3d81baf..0000000
--- a/services/core/Android.mk
+++ /dev/null
@@ -1,72 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.core
-
-LOCAL_AIDL_INCLUDES := \
-    frameworks/native/aidl/binder \
-    system/core/storaged/binder \
-    system/netd/server/binder \
-    system/vold/binder
-
-LOCAL_SRC_FILES += \
-    $(call all-java-files-under,java) \
-    java/com/android/server/EventLogTags.logtags \
-    java/com/android/server/am/EventLogTags.logtags \
-    ../../../../system/core/storaged/binder/android/os/IStoraged.aidl \
-    ../../../../system/netd/server/binder/android/net/INetd.aidl \
-    ../../../../system/netd/server/binder/android/net/metrics/INetdEventListener.aidl \
-    ../../../../system/vold/binder/android/os/IVold.aidl \
-    ../../../../system/vold/binder/android/os/IVoldListener.aidl \
-    ../../../../system/vold/binder/android/os/IVoldTaskListener.aidl \
-    ../../../native/cmds/installd/binder/android/os/IInstalld.aidl \
-
-LOCAL_AIDL_INCLUDES += \
-    system/netd/server/binder
-
-LOCAL_JAVA_LIBRARIES := \
-    services.net \
-    android.hardware.light-V2.0-java \
-    android.hardware.power-V1.0-java \
-    android.hardware.tv.cec-V1.0-java \
-    android.hidl.manager-V1.0-java
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    time_zone_distro \
-    time_zone_distro_installer \
-    android.hidl.base-V1.0-java \
-    android.hardware.health-V1.0-java \
-    android.hardware.health-V2.0-java \
-    android.hardware.weaver-V1.0-java \
-    android.hardware.biometrics.fingerprint-V2.1-java \
-    android.hardware.oemlock-V1.0-java \
-    android.hardware.tetheroffload.control-V1.0-java \
-    android.hardware.vibrator-V1.0-java \
-    android.hardware.configstore-V1.0-java \
-    android.hardware.contexthub-V1.0-java
-
-ifneq ($(INCREMENTAL_BUILDS),)
-    LOCAL_PROGUARD_ENABLED := disabled
-    LOCAL_JACK_ENABLED := incremental
-endif
-
-LOCAL_JACK_FLAGS := \
- -D jack.transformations.boost-locked-region-priority=true \
- -D jack.transformations.boost-locked-region-priority.classname=com.android.server.am.ActivityManagerService,com.android.server.wm.WindowHashMap \
- -D jack.transformations.boost-locked-region-priority.request=com.android.server.am.ActivityManagerService\#boostPriorityForLockedSection,com.android.server.wm.WindowManagerService\#boostPriorityForLockedSection \
- -D jack.transformations.boost-locked-region-priority.reset=com.android.server.am.ActivityManagerService\#resetPriorityAfterLockedSection,com.android.server.wm.WindowManagerService\#resetPriorityAfterLockedSection
-
-LOCAL_JAR_PROCESSOR := lockedregioncodeinjection
-# Use = instead of := to delay evaluation of ${in} and ${out}
-LOCAL_JAR_PROCESSOR_ARGS = \
- --targets \
-  "Lcom/android/server/am/ActivityManagerService;,Lcom/android/server/wm/WindowHashMap;" \
- --pre \
-  "com/android/server/am/ActivityManagerService.boostPriorityForLockedSection,com/android/server/wm/WindowManagerService.boostPriorityForLockedSection" \
- --post \
-  "com/android/server/am/ActivityManagerService.resetPriorityAfterLockedSection,com/android/server/wm/WindowManagerService.resetPriorityAfterLockedSection" \
- -o ${out} \
- -i ${in}
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/core/java/com/android/server/AnimationThread.java b/services/core/java/com/android/server/AnimationThread.java
index 08392b0..c86042b 100644
--- a/services/core/java/com/android/server/AnimationThread.java
+++ b/services/core/java/com/android/server/AnimationThread.java
@@ -22,8 +22,8 @@
 import android.os.Trace;
 
 /**
- * Thread for handling all window animations, or anything that's directly impacting animations like
- * starting windows or traversals.
+ * Thread for handling all legacy window animations, or anything that's directly impacting
+ * animations like starting windows or traversals.
  */
 public final class AnimationThread extends ServiceThread {
     private static AnimationThread sInstance;
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 763a4e4..d9713a5 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -1628,7 +1628,7 @@
 
                         //Do enable request
                         try {
-                            if (mQuietEnable) {
+                            if (!mQuietEnable) {
                                 if (!mBluetooth.enable()) {
                                     Slog.e(TAG, "IBluetooth.enable() returned false");
                                 }
diff --git a/services/core/java/com/android/server/am/ActivityStartController.java b/services/core/java/com/android/server/am/ActivityStartController.java
index a97b93c..aed49e0 100644
--- a/services/core/java/com/android/server/am/ActivityStartController.java
+++ b/services/core/java/com/android/server/am/ActivityStartController.java
@@ -105,7 +105,8 @@
     /**
      * TODO(b/64750076): Capture information necessary for dump and
      * {@link #postStartActivityProcessingForLastStarter} rather than keeping the entire object
-     * around */
+     * around
+     */
     private ActivityStarter mLastStarter;
 
     ActivityStartController(ActivityManagerService service) {
@@ -130,10 +131,16 @@
      *         considered invalid and no longer modified or used.
      */
     ActivityStarter obtainStarter(Intent intent, String reason) {
-        final ActivityStarter starter = mFactory.obtainStarter();
-        mLastStarter = starter;
+        return mFactory.obtain().setIntent(intent).setReason(reason);
+    }
 
-        return starter.setIntent(intent).setReason(reason);
+    void onExecutionComplete(ActivityStarter starter) {
+        if (mLastStarter == null) {
+            mLastStarter = mFactory.obtain();
+        }
+
+        mLastStarter.set(starter);
+        mFactory.recycle(starter);
     }
 
     /**
@@ -142,6 +149,10 @@
      */
     void postStartActivityProcessingForLastStarter(ActivityRecord r, int result,
             ActivityStack targetStack) {
+        if (mLastStarter == null) {
+            return;
+        }
+
         mLastStarter.postStartActivityProcessing(r, result, targetStack);
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 10fb6e2a..69cc3c7 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -102,6 +102,7 @@
 import android.service.voice.IVoiceInteractionSession;
 import android.text.TextUtils;
 import android.util.EventLog;
+import android.util.Pools.SynchronizedPool;
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -131,7 +132,6 @@
     private final ActivityManagerService mService;
     private final ActivityStackSupervisor mSupervisor;
     private final ActivityStartInterceptor mInterceptor;
-
     private final ActivityStartController mController;
 
     // Share state variable among methods when starting an activity.
@@ -209,18 +209,34 @@
          *                   this instance.
          * @return an {@link ActivityStarter}
          */
-        ActivityStarter obtainStarter();
+        ActivityStarter obtain();
+
+        /**
+         * Recycles a starter for reuse.
+         */
+        void recycle(ActivityStarter starter);
     }
 
     /**
      * Default implementation of {@link StarterFactory}.
      */
     static class DefaultFactory implements Factory {
+        /**
+         * The maximum count of starters that should be active at one time:
+         * 1. last ran starter (for logging and post activity processing)
+         * 2. current running starter
+         * 3. starter from re-entry in (2)
+         */
+        private final int MAX_STARTER_COUNT = 3;
+
         private ActivityStartController mController;
         private ActivityManagerService mService;
         private ActivityStackSupervisor mSupervisor;
         private ActivityStartInterceptor mInterceptor;
 
+        private SynchronizedPool<ActivityStarter> mStarterPool =
+                new SynchronizedPool<>(MAX_STARTER_COUNT);
+
         DefaultFactory(ActivityManagerService service,
                 ActivityStackSupervisor supervisor, ActivityStartInterceptor interceptor) {
             mService = service;
@@ -234,9 +250,20 @@
         }
 
         @Override
-        public ActivityStarter obtainStarter() {
-            // TODO(b/64750076): Investigate recycling instances to reduce object creation overhead.
-            return new ActivityStarter(mController, mService, mSupervisor, mInterceptor);
+        public ActivityStarter obtain() {
+            ActivityStarter starter = mStarterPool.acquire();
+
+            if (starter == null) {
+                starter = new ActivityStarter(mController, mService, mSupervisor, mInterceptor);
+            }
+
+            return starter;
+        }
+
+        @Override
+        public void recycle(ActivityStarter starter) {
+            starter.reset(true /* clearRequest*/);
+            mStarterPool.release(starter);
         }
     }
 
@@ -289,6 +316,76 @@
          * {@see ActivityStarter#startActivityMayWait}.
          */
         boolean mayWait;
+
+        /**
+         * Sets values back to the initial state, clearing any held references.
+         */
+        void reset() {
+            caller = null;
+            intent = null;
+            ephemeralIntent = null;
+            resolvedType = null;
+            activityInfo = null;
+            resolveInfo = null;
+            voiceSession = null;
+            voiceInteractor = null;
+            resultTo = null;
+            resultWho = null;
+            requestCode = 0;
+            callingPid = 0;
+            callingUid = 0;
+            callingPackage = null;
+            realCallingPid = 0;
+            realCallingUid = 0;
+            startFlags = 0;
+            activityOptions = null;
+            ignoreTargetSecurity = false;
+            componentSpecified = false;
+            outActivity = null;
+            inTask = null;
+            reason = null;
+            profilerInfo = null;
+            globalConfig = null;
+            waitOptions = null;
+            userId = 0;
+            waitResult = null;
+            mayWait = false;
+        }
+
+        /**
+         * Adopts all values from passed in request.
+         */
+        void set(Request request) {
+            caller = request.caller;
+            intent = request.intent;
+            ephemeralIntent = request.ephemeralIntent;
+            resolvedType = request.resolvedType;
+            activityInfo = request.activityInfo;
+            resolveInfo = request.resolveInfo;
+            voiceSession = request.voiceSession;
+            voiceInteractor = request.voiceInteractor;
+            resultTo = request.resultTo;
+            resultWho = request.resultWho;
+            requestCode = request.requestCode;
+            callingPid = request.callingPid;
+            callingUid = request.callingUid;
+            callingPackage = request.callingPackage;
+            realCallingPid = request.realCallingPid;
+            realCallingUid = request.realCallingUid;
+            startFlags = request.startFlags;
+            activityOptions = request.activityOptions;
+            ignoreTargetSecurity = request.ignoreTargetSecurity;
+            componentSpecified = request.componentSpecified;
+            outActivity = request.outActivity;
+            inTask = request.inTask;
+            reason = request.reason;
+            profilerInfo = request.profilerInfo;
+            globalConfig = request.globalConfig;
+            waitOptions = request.waitOptions;
+            userId = request.userId;
+            waitResult = request.waitResult;
+            mayWait = request.mayWait;
+        }
     }
 
     ActivityStarter(ActivityStartController controller, ActivityManagerService service,
@@ -297,6 +394,52 @@
         mService = service;
         mSupervisor = supervisor;
         mInterceptor = interceptor;
+        reset(true);
+    }
+
+    /**
+     * Effectively duplicates the starter passed in. All state and request values will be
+     * mirrored.
+     * @param starter
+     */
+    void set(ActivityStarter starter) {
+        mStartActivity = starter.mStartActivity;
+        mIntent = starter.mIntent;
+        mCallingUid = starter.mCallingUid;
+        mOptions = starter.mOptions;
+
+        mLaunchTaskBehind = starter.mLaunchTaskBehind;
+        mLaunchFlags = starter.mLaunchFlags;
+        mLaunchMode = starter.mLaunchMode;
+
+        mLaunchBounds.set(starter.mLaunchBounds);
+
+        mNotTop = starter.mNotTop;
+        mDoResume = starter.mDoResume;
+        mStartFlags = starter.mStartFlags;
+        mSourceRecord = starter.mSourceRecord;
+        mPreferredDisplayId = starter.mPreferredDisplayId;
+
+        mInTask = starter.mInTask;
+        mAddingToTask = starter.mAddingToTask;
+        mReuseTask = starter.mReuseTask;
+
+        mNewTaskInfo = starter.mNewTaskInfo;
+        mNewTaskIntent = starter.mNewTaskIntent;
+        mSourceStack = starter.mSourceStack;
+
+        mTargetStack = starter.mTargetStack;
+        mMovedToFront = starter.mMovedToFront;
+        mNoAnimation = starter.mNoAnimation;
+        mKeepCurTransition = starter.mKeepCurTransition;
+        mAvoidMoveToFront = starter.mAvoidMoveToFront;
+
+        mVoiceSession = starter.mVoiceSession;
+        mVoiceInteractor = starter.mVoiceInteractor;
+
+        mIntentDelivered = starter.mIntentDelivered;
+
+        mRequest.set(starter.mRequest);
     }
 
     ActivityRecord getStartActivity() {
@@ -314,25 +457,47 @@
      * @return The starter result.
      */
     int execute() {
-        // TODO(b/64750076): Look into passing request directly to these methods to allow
-        // for transactional diffs and preprocessing.
-        if (mRequest.mayWait) {
-            return startActivityMayWait(mRequest.caller, mRequest.callingUid,
-                    mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
-                    mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
-                    mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
-                    mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
-                    mRequest.waitOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
-                    mRequest.inTask, mRequest.reason);
-        } else {
-            return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
-                    mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
-                    mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
-                    mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
-                    mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
-                    mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
-                    mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
-                    mRequest.outActivity, mRequest.inTask, mRequest.reason);
+        try {
+            // TODO(b/64750076): Look into passing request directly to these methods to allow
+            // for transactional diffs and preprocessing.
+            if (mRequest.mayWait) {
+                return startActivityMayWait(mRequest.caller, mRequest.callingUid,
+                        mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
+                        mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
+                        mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
+                        mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
+                        mRequest.waitOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
+                        mRequest.inTask, mRequest.reason);
+            } else {
+                return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
+                        mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
+                        mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
+                        mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
+                        mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
+                        mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
+                        mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
+                        mRequest.outActivity, mRequest.inTask, mRequest.reason);
+            }
+        } finally {
+            onExecutionComplete();
+        }
+    }
+
+    /**
+     * Starts an activity based on the provided {@link ActivityRecord} and environment parameters.
+     * Note that this method is called internally as well as part of {@link #startActivity}.
+     *
+     * @return The start result.
+     */
+    int startResolvedActivity(final ActivityRecord r, ActivityRecord sourceRecord,
+            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
+            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
+            ActivityRecord[] outActivity) {
+        try {
+            return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
+                    doResume, options, inTask, outActivity);
+        } finally {
+            onExecutionComplete();
         }
     }
 
@@ -370,6 +535,14 @@
         return result != START_ABORTED ? result : START_SUCCESS;
     }
 
+    /**
+     * Called when execution is complete. Sets state indicating completion and proceeds with
+     * recycling if appropriate.
+     */
+    private void onExecutionComplete() {
+        mController.onExecutionComplete(this);
+    }
+
     private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
             String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
             IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
@@ -652,7 +825,7 @@
 
         mController.doPendingActivityLaunches(false);
 
-        return startResolvedActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
+        return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                 true /* doResume */, options, inTask, outActivity);
     }
 
@@ -925,16 +1098,10 @@
         }
     }
 
-    /**
-     * Starts an activity based on the provided {@link ActivityRecord} and environment parameters.
-     * Note that this method is called internally as well as part of {@link #startActivity}.
-     *
-     * @return The start result.
-     */
-    int startResolvedActivity(final ActivityRecord r, ActivityRecord sourceRecord,
-        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
-        int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
-        ActivityRecord[] outActivity) {
+    private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
+                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
+                int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
+                ActivityRecord[] outActivity) {
         int result = START_CANCELED;
         try {
             mService.mWindowManager.deferSurfaceLayout();
@@ -1190,9 +1357,57 @@
         return START_SUCCESS;
     }
 
+    /**
+     * Resets the {@link ActivityStarter} state.
+     * @param clearRequest whether the request should be reset to default values.
+     */
+    void reset(boolean clearRequest) {
+        mStartActivity = null;
+        mIntent = null;
+        mCallingUid = -1;
+        mOptions = null;
+
+        mLaunchTaskBehind = false;
+        mLaunchFlags = 0;
+        mLaunchMode = INVALID_LAUNCH_MODE;
+
+        mLaunchBounds.setEmpty();
+
+        mNotTop = null;
+        mDoResume = false;
+        mStartFlags = 0;
+        mSourceRecord = null;
+        mPreferredDisplayId = INVALID_DISPLAY;
+
+        mInTask = null;
+        mAddingToTask = false;
+        mReuseTask = null;
+
+        mNewTaskInfo = null;
+        mNewTaskIntent = null;
+        mSourceStack = null;
+
+        mTargetStack = null;
+        mMovedToFront = false;
+        mNoAnimation = false;
+        mKeepCurTransition = false;
+        mAvoidMoveToFront = false;
+
+        mVoiceSession = null;
+        mVoiceInteractor = null;
+
+        mIntentDelivered = false;
+
+        if (clearRequest) {
+            mRequest.reset();
+        }
+    }
+
     private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
             boolean doResume, int startFlags, ActivityRecord sourceRecord,
             IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
+        reset(false /* clearRequest */);
+
         mStartActivity = r;
         mIntent = r.intent;
         mOptions = options;
diff --git a/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java
index 28c3585..bd2e96e 100644
--- a/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java
+++ b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java
@@ -51,6 +51,7 @@
     // Information about the current status of the default network.
     @GuardedBy("this")
     private DefaultNetworkEvent mCurrentDefaultNetwork;
+    // True if the current default network has been validated.
     @GuardedBy("this")
     private boolean mIsCurrentlyValid;
     @GuardedBy("this")
@@ -71,6 +72,8 @@
             printEvent(localTimeMs, pw, ev);
         }
         mCurrentDefaultNetwork.updateDuration(timeMs);
+        // When printing default network events for bug reports, update validation time
+        // and refresh the last validation timestmap for future validation time updates.
         if (mIsCurrentlyValid) {
             updateValidationTime(timeMs);
             mLastValidationTimeMs = timeMs;
@@ -92,11 +95,13 @@
     }
 
     public synchronized void logDefaultNetworkValidity(long timeMs, boolean isValid) {
+        // Transition from valid to invalid: update validity duration since last update
         if (!isValid && mIsCurrentlyValid) {
             mIsCurrentlyValid = false;
             updateValidationTime(timeMs);
         }
 
+        // Transition from invalid to valid: simply mark the validation timestamp.
         if (isValid && !mIsCurrentlyValid) {
             mIsCurrentlyValid = true;
             mLastValidationTimeMs = timeMs;
@@ -114,6 +119,9 @@
     }
 
     private void logCurrentDefaultNetwork(long timeMs, NetworkAgentInfo oldNai) {
+        if (mIsCurrentlyValid) {
+            updateValidationTime(timeMs);
+        }
         DefaultNetworkEvent ev = mCurrentDefaultNetwork;
         ev.updateDuration(timeMs);
         ev.previousTransports = mLastTransports;
@@ -122,7 +130,6 @@
             // The system acquired a new default network.
             fillLinkInfo(ev, oldNai);
             ev.finalScore = oldNai.getCurrentScore();
-            ev.validatedMs = ev.durationMs;
         }
         // Only change transport of the previous default network if the event currently logged
         // corresponds to an existing default network, and not to the absence of a default network.
@@ -143,9 +150,10 @@
             fillLinkInfo(ev, newNai);
             ev.initialScore = newNai.getCurrentScore();
             if (newNai.lastValidated) {
-                mIsCurrentlyValid = true;
-                mLastValidationTimeMs = timeMs;
+                logDefaultNetworkValidity(timeMs, true);
             }
+        } else {
+            mIsCurrentlyValid = false;
         }
         mCurrentDefaultNetwork = ev;
     }
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 19a74d7..c1bfa47 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -76,6 +76,7 @@
 import com.android.server.SystemService;
 import com.android.server.UiThread;
 import com.android.server.wm.WindowManagerInternal;
+import com.android.server.wm.SurfaceAnimationThread;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -292,6 +293,8 @@
                 Process.THREAD_GROUP_TOP_APP);
         Process.setThreadGroupAndCpuset(AnimationThread.get().getThreadId(),
                 Process.THREAD_GROUP_TOP_APP);
+        Process.setThreadGroupAndCpuset(SurfaceAnimationThread.get().getThreadId(),
+                Process.THREAD_GROUP_TOP_APP);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 3f014b5..f2a1c47 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -1721,16 +1721,29 @@
 
         // If the app is in a non-active standby bucket, make sure we've waited
         // an appropriate amount of time since the last invocation
-        if (mHeartbeat < mNextBucketHeartbeat[job.getStandbyBucket()]) {
-            // TODO: log/trace that we're deferring the job due to bucketing if we hit this
-            if (job.getWhenStandbyDeferred() == 0) {
-                if (DEBUG_STANDBY) {
-                    Slog.v(TAG, "Bucket deferral: " + mHeartbeat + " < "
-                            + mNextBucketHeartbeat[job.getStandbyBucket()] + " for " + job);
+        final int bucket = job.getStandbyBucket();
+        if (mHeartbeat < mNextBucketHeartbeat[bucket]) {
+            // Only skip this job if it's still waiting for the end of its (initial) nominal
+            // bucket interval.  Once it's waited that long, we let it go ahead and clear.
+            // The final (NEVER) bucket is special; we never age those apps' jobs into
+            // runnability.
+            if (bucket >= mConstants.STANDBY_BEATS.length
+                    || (mHeartbeat < job.getBaseHeartbeat() + mConstants.STANDBY_BEATS[bucket])) {
+                // TODO: log/trace that we're deferring the job due to bucketing if we hit this
+                if (job.getWhenStandbyDeferred() == 0) {
+                    if (DEBUG_STANDBY) {
+                        Slog.v(TAG, "Bucket deferral: " + mHeartbeat + " < "
+                                + mNextBucketHeartbeat[job.getStandbyBucket()] + " for " + job);
+                    }
+                    job.setWhenStandbyDeferred(sElapsedRealtimeClock.millis());
                 }
-                job.setWhenStandbyDeferred(sElapsedRealtimeClock.millis());
+                return false;
+            } else {
+                if (DEBUG_STANDBY) {
+                    Slog.v(TAG, "Bucket deferred job aged into runnability at "
+                            + mHeartbeat + " : " + job);
+                }
             }
-            return false;
         }
 
         // The expensive check last: validate that the defined package+service is
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index e0f3ec7..5dfb48a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -12884,14 +12884,13 @@
         if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
             return null;
         }
-        // writer
-        synchronized (mPackages) {
-            if (!isExternalMediaAvailable()) {
+        if (!isExternalMediaAvailable()) {
                 // If the external storage is no longer mounted at this point,
                 // the caller may not have been able to delete all of this
                 // packages files and can not delete any more.  Bail.
-                return null;
-            }
+            return null;
+        }
+        synchronized (mPackages) {
             final ArrayList<PackageCleanItem> pkgs = mSettings.mPackagesToBeCleaned;
             if (lastPackage != null) {
                 pkgs.remove(lastPackage);
diff --git a/services/core/java/com/android/server/timezone/ClockHelper.java b/services/core/java/com/android/server/timezone/ClockHelper.java
deleted file mode 100644
index 353728a..0000000
--- a/services/core/java/com/android/server/timezone/ClockHelper.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS 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.timezone;
-
-/**
- * An easy-to-mock interface for obtaining a monotonically increasing time value in milliseconds.
- */
-interface ClockHelper {
-
-    long currentTimestamp();
-}
diff --git a/services/core/java/com/android/server/timezone/PackageTracker.java b/services/core/java/com/android/server/timezone/PackageTracker.java
index 1c54320..c362c80 100644
--- a/services/core/java/com/android/server/timezone/PackageTracker.java
+++ b/services/core/java/com/android/server/timezone/PackageTracker.java
@@ -22,11 +22,14 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.Environment;
+import android.os.FileUtils;
+import android.os.SystemClock;
 import android.provider.TimeZoneRulesDataContract;
 import android.util.Slog;
 
 import java.io.File;
 import java.io.PrintWriter;
+import java.time.Clock;
 
 /**
  * Monitors the installed applications associated with time zone updates. If the app packages are
@@ -58,7 +61,7 @@
     private final IntentHelper mIntentHelper;
     private final ConfigHelper mConfigHelper;
     private final PackageStatusStorage mPackageStatusStorage;
-    private final ClockHelper mClockHelper;
+    private final Clock mElapsedRealtimeClock;
 
     // False if tracking is disabled.
     private boolean mTrackingEnabled;
@@ -91,15 +94,15 @@
 
     /** Creates the {@link PackageTracker} for normal use. */
     static PackageTracker create(Context context) {
+        Clock elapsedRealtimeClock = SystemClock.elapsedRealtimeClock();
         PackageTrackerHelperImpl helperImpl = new PackageTrackerHelperImpl(context);
-        // TODO(nfuller): Switch to FileUtils.createDir() when available. http://b/31008728
-        File storageDir = new File(Environment.getDataSystemDirectory(), "timezone");
+        File storageDir = FileUtils.createDir(Environment.getDataSystemDirectory(), "timezone");
         if (!storageDir.exists()) {
             storageDir.mkdir();
         }
 
         return new PackageTracker(
-                helperImpl /* clock */,
+                elapsedRealtimeClock /* elapsedRealtimeClock */,
                 helperImpl /* configHelper */,
                 helperImpl /* packageManagerHelper */,
                 new PackageStatusStorage(storageDir),
@@ -107,10 +110,10 @@
     }
 
     // A constructor that can be used by tests to supply mocked / faked dependencies.
-    PackageTracker(ClockHelper clockHelper, ConfigHelper configHelper,
+    PackageTracker(Clock elapsedRealtimeClock, ConfigHelper configHelper,
             PackageManagerHelper packageManagerHelper, PackageStatusStorage packageStatusStorage,
             IntentHelper intentHelper) {
-        mClockHelper = clockHelper;
+        mElapsedRealtimeClock = elapsedRealtimeClock;
         mConfigHelper = configHelper;
         mPackageManagerHelper = packageManagerHelper;
         mPackageStatusStorage = packageStatusStorage;
@@ -425,7 +428,7 @@
     }
 
     private void setCheckInProgress() {
-        mLastTriggerTimestamp = mClockHelper.currentTimestamp();
+        mLastTriggerTimestamp = mElapsedRealtimeClock.millis();
     }
 
     private void setCheckComplete() {
@@ -441,7 +444,7 @@
             return false;
         }
         // Risk of overflow, but highly unlikely given the implementation and not problematic.
-        return mClockHelper.currentTimestamp() > mLastTriggerTimestamp + mCheckTimeAllowedMillis;
+        return mElapsedRealtimeClock.millis() > mLastTriggerTimestamp + mCheckTimeAllowedMillis;
     }
 
     private PackageVersions lookupInstalledPackageVersions() {
diff --git a/services/core/java/com/android/server/timezone/PackageTrackerHelperImpl.java b/services/core/java/com/android/server/timezone/PackageTrackerHelperImpl.java
index 6a330e6..5f90be1 100644
--- a/services/core/java/com/android/server/timezone/PackageTrackerHelperImpl.java
+++ b/services/core/java/com/android/server/timezone/PackageTrackerHelperImpl.java
@@ -25,7 +25,6 @@
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
-import android.os.SystemClock;
 import android.os.UserHandle;
 import android.util.Slog;
 
@@ -34,7 +33,7 @@
 /**
  * A single class that implements multiple helper interfaces for use by {@link PackageTracker}.
  */
-final class PackageTrackerHelperImpl implements ClockHelper, ConfigHelper, PackageManagerHelper {
+final class PackageTrackerHelperImpl implements ConfigHelper, PackageManagerHelper {
 
     private static final String TAG = "PackageTrackerHelperImpl";
 
@@ -74,13 +73,6 @@
     }
 
     @Override
-    public long currentTimestamp() {
-        // Use of elapsedRealtime() because this is in-memory state and elapsedRealtime() shouldn't
-        // change if the system clock changes.
-        return SystemClock.elapsedRealtime();
-    }
-
-    @Override
     public long getInstalledPackageVersion(String packageName)
             throws PackageManager.NameNotFoundException {
         int flags = PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
diff --git a/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java b/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java
index 0cf61c0..e8a401e 100644
--- a/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java
+++ b/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java
@@ -16,6 +16,8 @@
 
 package com.android.server.timezone;
 
+import com.android.internal.util.DumpUtils;
+
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.AsyncTask;
@@ -46,15 +48,7 @@
 
     @Override
     public boolean checkDumpPermission(String tag, PrintWriter pw) {
-        // TODO(nfuller): Switch to DumpUtils.checkDumpPermission() when it is available in AOSP.
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump LocationManagerService from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid());
-            return false;
-        }
-        return true;
+        return DumpUtils.checkDumpPermission(mContext, tag, pw);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/AnimationAdapter.java b/services/core/java/com/android/server/wm/AnimationAdapter.java
new file mode 100644
index 0000000..84d47b4
--- /dev/null
+++ b/services/core/java/com/android/server/wm/AnimationAdapter.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.annotation.ColorInt;
+import android.graphics.Point;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
+import android.view.animation.Animation;
+
+import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
+
+/**
+ * Interface that describes an animation and bridges the animation start to the component
+ * responsible for running the animation.
+ */
+interface AnimationAdapter {
+
+    /**
+     * @return Whether we should detach the wallpaper during the animation.
+     * @see Animation#setDetachWallpaper
+     */
+    boolean getDetachWallpaper();
+
+    /**
+     * @return The background color behind the animation.
+     */
+    @ColorInt int getBackgroundColor();
+
+    /**
+     * Requests to start the animation.
+     *
+     * @param animationLeash The surface to run the animation on. See {@link SurfaceAnimator} for an
+     *                       overview of the mechanism. This surface needs to be released by the
+     *                       component running the animation after {@code finishCallback} has been
+     *                       invoked, or after the animation was cancelled.
+     * @param t The Transaction to apply the initial frame of the animation.
+     * @param finishCallback The callback to be invoked when the animation has finished.
+     */
+    void startAnimation(SurfaceControl animationLeash, Transaction t,
+            OnAnimationFinishedCallback finishCallback);
+
+    /**
+     * Called when the animation that was started with {@link #startAnimation} was cancelled by the
+     * window manager.
+     *
+     * @param animationLeash The leash passed to {@link #startAnimation}.
+     */
+    void onAnimationCancelled(SurfaceControl animationLeash);
+
+    /**
+     * @return The approximate duration of the animation, in milliseconds.
+     */
+    long getDurationHint();
+}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 91cad46..eda8fec 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1766,8 +1766,8 @@
         updateBounds();
     }
 
-    void getContentRect(Rect out) {
-        out.set(mDisplayFrames.mContent);
+    void getStableRect(Rect out) {
+        out.set(mDisplayFrames.mStable);
     }
 
     TaskStack createStack(int stackId, boolean onTop, StackWindowController controller) {
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 7e29a3a..88b7a11 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -390,12 +390,13 @@
             }
         }
 
-        final boolean inPositioning = (mService.mTaskPositioner != null);
+        final boolean inPositioning = mService.mTaskPositioningController.isPositioningLocked();
         if (inPositioning) {
             if (DEBUG_TASK_POSITIONING) {
                 Log.d(TAG_WM, "Inserting window handle for repositioning");
             }
-            final InputWindowHandle dragWindowHandle = mService.mTaskPositioner.mDragWindowHandle;
+            final InputWindowHandle dragWindowHandle =
+                    mService.mTaskPositioningController.getDragWindowHandleLocked();
             if (dragWindowHandle != null) {
                 addInputWindowHandle(dragWindowHandle);
             } else {
diff --git a/services/core/java/com/android/server/wm/LocalAnimationAdapter.java b/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
new file mode 100644
index 0000000..5fe4565
--- /dev/null
+++ b/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.graphics.Point;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
+import android.view.animation.Animation;
+
+import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
+
+/**
+ * Animation that can be executed without holding the window manager lock. See
+ * {@link SurfaceAnimationRunner}.
+ */
+class LocalAnimationAdapter implements AnimationAdapter {
+
+    private final AnimationSpec mSpec;
+    private final SurfaceAnimationRunner mAnimator;
+
+    LocalAnimationAdapter(AnimationSpec spec, SurfaceAnimationRunner animator) {
+        mSpec = spec;
+        mAnimator = animator;
+    }
+
+    @Override
+    public boolean getDetachWallpaper() {
+        return mSpec.getDetachWallpaper();
+    }
+
+    @Override
+    public int getBackgroundColor() {
+        return mSpec.getBackgroundColor();
+    }
+
+    @Override
+    public void startAnimation(SurfaceControl animationLeash, Transaction t,
+            OnAnimationFinishedCallback finishCallback) {
+        mAnimator.startAnimation(mSpec, animationLeash, t,
+                () -> finishCallback.onAnimationFinished(this));
+    }
+
+    @Override
+    public void onAnimationCancelled(SurfaceControl animationLeash) {
+        mAnimator.onAnimationCancelled(animationLeash);
+    }
+
+    @Override
+    public long getDurationHint() {
+        return mSpec.getDuration();
+    }
+
+    /**
+     * Describes how to apply an animation.
+     */
+    interface AnimationSpec {
+
+        /**
+         * @see AnimationAdapter#getDetachWallpaper
+         */
+        default boolean getDetachWallpaper() {
+            return false;
+        }
+
+        /**
+         * @see AnimationAdapter#getBackgroundColor
+         */
+        default int getBackgroundColor() {
+            return 0;
+        }
+
+        /**
+         * @return The duration of the animation.
+         */
+        long getDuration();
+
+        /**
+         * Called when the spec needs to apply the current animation state to the leash.
+         *
+         * @param t The transaction to use to apply a transform.
+         * @param leash The leash to apply the state to.
+         * @param currentPlayTime The current time of the animation.
+         */
+        void apply(Transaction t, SurfaceControl leash, long currentPlayTime);
+    }
+}
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 63eea10..192d6c8 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -368,7 +368,7 @@
 
         long ident = Binder.clearCallingIdentity();
         try {
-            return mService.startMovingTask(window, startX, startY);
+            return mService.mTaskPositioningController.startMovingTask(window, startX, startY);
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
new file mode 100644
index 0000000..5bc2722
--- /dev/null
+++ b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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 static android.view.Choreographer.CALLBACK_TRAVERSAL;
+import static android.view.Choreographer.getSfInstance;
+
+import android.animation.AnimationHandler;
+import android.animation.AnimationHandler.AnimationFrameCallbackProvider;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.annotation.Nullable;
+import android.util.ArrayMap;
+import android.view.Choreographer;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
+import android.view.animation.Transformation;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
+import com.android.server.AnimationThread;
+import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
+
+/**
+ * Class to run animations without holding the window manager lock.
+ */
+class SurfaceAnimationRunner {
+
+    private final Object mLock = new Object();
+
+    @VisibleForTesting
+    Choreographer mChoreographer;
+
+    private final Runnable mApplyTransactionRunnable = this::applyTransaction;
+    private final AnimationHandler mAnimationHandler;
+    private final Transaction mFrameTransaction;
+    private boolean mApplyScheduled;
+
+    @GuardedBy("mLock")
+    @VisibleForTesting
+    final ArrayMap<SurfaceControl, RunningAnimation> mPendingAnimations = new ArrayMap<>();
+
+    @GuardedBy("mLock")
+    @VisibleForTesting
+    final ArrayMap<SurfaceControl, ValueAnimator> mRunningAnimations = new ArrayMap<>();
+
+    SurfaceAnimationRunner() {
+        this(null /* callbackProvider */, new Transaction());
+    }
+
+    @VisibleForTesting
+    SurfaceAnimationRunner(@Nullable AnimationFrameCallbackProvider callbackProvider,
+            Transaction frameTransaction) {
+        SurfaceAnimationThread.getHandler().runWithScissors(() -> mChoreographer = getSfInstance(),
+                0 /* timeout */);
+        mFrameTransaction = frameTransaction;
+        mAnimationHandler = new AnimationHandler();
+        mAnimationHandler.setProvider(callbackProvider != null
+                ? callbackProvider
+                : new SfVsyncFrameCallbackProvider(mChoreographer));
+    }
+
+    void startAnimation(AnimationSpec a, SurfaceControl animationLeash, Transaction t,
+            Runnable finishCallback) {
+        synchronized (mLock) {
+            final RunningAnimation runningAnim = new RunningAnimation(a, animationLeash,
+                    finishCallback);
+            mPendingAnimations.put(animationLeash, runningAnim);
+            mChoreographer.postFrameCallback(this::stepAnimation);
+
+            // Some animations (e.g. move animations) require the initial transform to be applied
+            // immediately.
+            applyTransformation(runningAnim, t, 0 /* currentPlayTime */);
+        }
+    }
+
+    void onAnimationCancelled(SurfaceControl leash) {
+        synchronized (mLock) {
+            if (mPendingAnimations.containsKey(leash)) {
+                mPendingAnimations.remove(leash);
+                // TODO: Releasing the leash is problematic if reparenting hasn't happened yet.
+                // Fix with transaction
+                //leash.release();
+                return;
+            }
+            final ValueAnimator anim = mRunningAnimations.get(leash);
+            if (anim != null) {
+                mRunningAnimations.remove(leash);
+                SurfaceAnimationThread.getHandler().post(() -> {
+                    anim.cancel();
+                    applyTransaction();
+                    //leash.release();
+                });
+            }
+        }
+    }
+
+    private void startPendingAnimationsLocked() {
+        for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
+            startAnimationLocked(mPendingAnimations.valueAt(i));
+        }
+        mPendingAnimations.clear();
+    }
+
+    private void startAnimationLocked(RunningAnimation a) {
+        final ValueAnimator result = new SfValueAnimator();
+
+        // Animation length is already expected to be scaled.
+        result.overrideDurationScale(1.0f);
+        result.setDuration(a.animSpec.getDuration());
+        result.addUpdateListener(animation -> {
+            applyTransformation(a, mFrameTransaction, result.getCurrentPlayTime());
+
+            // Transaction will be applied in the commit phase.
+            scheduleApplyTransaction();
+        });
+        result.addListener(new AnimatorListenerAdapter() {
+
+            private boolean mCancelled;
+
+            @Override
+            public void onAnimationStart(Animator animation) {
+                mFrameTransaction.show(a.leash);
+            }
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                mCancelled = true;
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                synchronized (mLock) {
+                    mRunningAnimations.remove(a.leash);
+                }
+                if (!mCancelled) {
+                    // Post on other thread that we can push final state without jank.
+                    AnimationThread.getHandler().post(() -> {
+                        a.finishCallback.run();
+
+                        // Make sure to release the leash after finishCallback has been invoked such
+                        // that reparenting is done already when releasing the leash.
+                        a.leash.release();
+                    });
+                }
+            }
+        });
+        result.start();
+        mRunningAnimations.put(a.leash, result);
+    }
+
+    private void applyTransformation(RunningAnimation a, Transaction t, long currentPlayTime) {
+        a.animSpec.apply(t, a.leash, currentPlayTime);
+    }
+
+    private void stepAnimation(long frameTimeNanos) {
+        synchronized (mLock) {
+            startPendingAnimationsLocked();
+        }
+    }
+
+    private void scheduleApplyTransaction() {
+        if (!mApplyScheduled) {
+            mChoreographer.postCallback(CALLBACK_TRAVERSAL, mApplyTransactionRunnable,
+                    null /* token */);
+            mApplyScheduled = true;
+        }
+    }
+
+    private void applyTransaction() {
+        mFrameTransaction.apply();
+        mApplyScheduled = false;
+    }
+
+    private static final class RunningAnimation {
+        final AnimationSpec animSpec;
+        final SurfaceControl leash;
+        final Runnable finishCallback;
+
+        RunningAnimation(AnimationSpec animSpec, SurfaceControl leash, Runnable finishCallback) {
+            this.animSpec = animSpec;
+            this.leash = leash;
+            this.finishCallback = finishCallback;
+        }
+    }
+
+    /**
+     * Value animator that uses sf-vsync signal to tick.
+     */
+    private class SfValueAnimator extends ValueAnimator {
+
+        SfValueAnimator() {
+            setFloatValues(0f, 1f);
+        }
+
+        @Override
+        public AnimationHandler getAnimationHandler() {
+            return mAnimationHandler;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimationThread.java b/services/core/java/com/android/server/wm/SurfaceAnimationThread.java
new file mode 100644
index 0000000..0d3afc0
--- /dev/null
+++ b/services/core/java/com/android/server/wm/SurfaceAnimationThread.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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 static android.os.Process.THREAD_PRIORITY_DISPLAY;
+
+import android.os.Handler;
+import android.os.Trace;
+
+import com.android.server.ServiceThread;
+
+/**
+ * Thread for running {@link SurfaceAnimationRunner} that does not hold the window manager lock.
+ */
+public final class SurfaceAnimationThread extends ServiceThread {
+    private static SurfaceAnimationThread sInstance;
+    private static Handler sHandler;
+
+    private SurfaceAnimationThread() {
+        super("android.anim.lf", THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
+    }
+
+    private static void ensureThreadLocked() {
+        if (sInstance == null) {
+            sInstance = new SurfaceAnimationThread();
+            sInstance.start();
+            sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_WINDOW_MANAGER);
+            sHandler = new Handler(sInstance.getLooper());
+        }
+    }
+
+    public static SurfaceAnimationThread get() {
+        synchronized (SurfaceAnimationThread.class) {
+            ensureThreadLocked();
+            return sInstance;
+        }
+    }
+
+    public static Handler getHandler() {
+        synchronized (SurfaceAnimationThread.class) {
+            ensureThreadLocked();
+            return sHandler;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
new file mode 100644
index 0000000..713d58b
--- /dev/null
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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 static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.Slog;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
+
+import java.io.PrintWriter;
+
+/**
+ * A class that can run animations on objects that have a set of child surfaces. We do this by
+ * reparenting all child surfaces of an object onto a new surface, called the "Leash". The Leash
+ * gets attached in the surface hierarchy where the the children were attached to. We then hand off
+ * the Leash to the component handling the animation, which is specified by the
+ * {@link AnimationAdapter}. When the animation is done animating, our callback to finish the
+ * animation will be invoked, at which we reparent the children back to the original parent.
+ */
+class SurfaceAnimator {
+
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "SurfaceAnimator" : TAG_WM;
+    private final WindowManagerService mService;
+    private AnimationAdapter mAnimation;
+    private SurfaceControl mLeash;
+    private final Animatable mAnimatable;
+    private final OnAnimationFinishedCallback mInnerAnimationFinishedCallback;
+    private final Runnable mAnimationFinishedCallback;
+    private boolean mAnimationStartDelayed;
+
+    /**
+     * @param animatable The object to animate.
+     * @param animationFinishedCallback Callback to invoke when an animation has finished running.
+     */
+    SurfaceAnimator(Animatable animatable, Runnable animationFinishedCallback,
+            WindowManagerService service) {
+        mAnimatable = animatable;
+        mService = service;
+        mAnimationFinishedCallback = animationFinishedCallback;
+        mInnerAnimationFinishedCallback = getFinishedCallback(animationFinishedCallback);
+    }
+
+    private OnAnimationFinishedCallback getFinishedCallback(Runnable animationFinishedCallback) {
+        return anim -> {
+            synchronized (mService.mWindowMap) {
+                if (anim != mAnimation) {
+                    // Callback was from another animation - ignore.
+                    return;
+                }
+
+                final Transaction t = new Transaction();
+                SurfaceControl.openTransaction();
+                try {
+                    reset(t);
+                    animationFinishedCallback.run();
+                } finally {
+                    // TODO: This should use pendingTransaction eventually, but right now things
+                    // happening on the animation finished callback are happening on the global
+                    // transaction.
+                    SurfaceControl.mergeToGlobalTransaction(t);
+                    SurfaceControl.closeTransaction();
+                }
+            }
+        };
+    }
+
+    /**
+     * Starts an animation.
+     *
+     * @param anim The object that bridges the controller, {@link SurfaceAnimator}, with the
+     *             component responsible for running the animation. It runs the animation with
+     *             {@link AnimationAdapter#startAnimation} once the hierarchy with
+     *             the Leash has been set up.
+     * @param hidden Whether the container holding the child surfaces is currently visible or not.
+     *               This is important as it will start with the leash hidden or visible before
+     *               handing it to the component that is responsible to run the animation.
+     */
+    void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden) {
+        cancelAnimation(t, true /* restarting */);
+        mAnimation = anim;
+        final SurfaceControl surface = mAnimatable.getSurface();
+        if (surface == null) {
+            Slog.w(TAG, "Unable to start animation, surface is null or no children.");
+            cancelAnimation();
+            return;
+        }
+        mLeash = createAnimationLeash(surface, t,
+                mAnimatable.getSurfaceWidth(), mAnimatable.getSurfaceHeight(), hidden);
+        mAnimatable.onLeashCreated(t, mLeash);
+        if (mAnimationStartDelayed) {
+            if (DEBUG_ANIM) Slog.i(TAG, "Animation start delayed");
+            return;
+        }
+        mAnimation.startAnimation(mLeash, t, mInnerAnimationFinishedCallback);
+    }
+
+    /**
+     * Begins with delaying all animations to start. Any subsequent call to {@link #startAnimation}
+     * will not start the animation until {@link #endDelayingAnimationStart} is called. When an
+     * animation start is being delayed, the animator is considered animating already.
+     */
+    void startDelayingAnimationStart() {
+
+        // We only allow delaying animation start we are not currently animating
+        if (!isAnimating()) {
+            mAnimationStartDelayed = true;
+        }
+    }
+
+    /**
+     * See {@link #startDelayingAnimationStart}.
+     */
+    void endDelayingAnimationStart() {
+        final boolean delayed = mAnimationStartDelayed;
+        mAnimationStartDelayed = false;
+        if (delayed && mAnimation != null) {
+            mAnimation.startAnimation(mLeash, mAnimatable.getPendingTransaction(),
+                    mInnerAnimationFinishedCallback);
+            mAnimatable.commitPendingTransaction();
+        }
+    }
+
+    /**
+     * @return Whether we are currently running an animation, or we have a pending animation that
+     *         is waiting to be started with {@link #endDelayingAnimationStart}
+     */
+    boolean isAnimating() {
+        return mAnimation != null;
+    }
+
+    /**
+     * @return The current animation spec if we are running an animation, or {@code null} otherwise.
+     */
+    AnimationAdapter getAnimation() {
+        return mAnimation;
+    }
+
+    /**
+     * Cancels any currently running animation.
+     */
+    void cancelAnimation() {
+        cancelAnimation(mAnimatable.getPendingTransaction(), false /* restarting */);
+        mAnimatable.commitPendingTransaction();
+    }
+
+    /**
+     * Sets the layer of the surface.
+     * <p>
+     * When the layer of the surface needs to be adjusted, we need to set it on the leash if the
+     * surface is reparented to the leash. This method takes care of that.
+     */
+    void setLayer(Transaction t, int layer) {
+        t.setLayer(mLeash != null ? mLeash : mAnimatable.getSurface(), layer);
+    }
+
+    /**
+     * Reparents the surface.
+     *
+     * @see #setLayer
+     */
+    void reparent(Transaction t, SurfaceControl newParent) {
+        t.reparent(mLeash != null ? mLeash : mAnimatable.getSurface(), newParent.getHandle());
+    }
+
+    /**
+     * @return True if the surface is attached to the leash; false otherwise.
+     */
+    boolean hasLeash() {
+        return mLeash != null;
+    }
+
+    private void cancelAnimation(Transaction t, boolean restarting) {
+        if (DEBUG_ANIM) Slog.i(TAG, "Cancelling animation restarting=" + restarting);
+        final SurfaceControl leash = mLeash;
+        final AnimationAdapter animation = mAnimation;
+        reset(t);
+        if (animation != null) {
+            if (!mAnimationStartDelayed) {
+                animation.onAnimationCancelled(leash);
+            }
+            if (!restarting) {
+                mAnimationFinishedCallback.run();
+            }
+        }
+        if (!restarting) {
+            mAnimationStartDelayed = false;
+        }
+    }
+
+    private void reset(Transaction t) {
+        final SurfaceControl surface = mAnimatable.getSurface();
+        final SurfaceControl parent = mAnimatable.getParentSurface();
+
+        // If the surface was destroyed, we don't care to reparent it back.
+        final boolean destroy = mLeash != null && surface != null && parent != null;
+        if (destroy) {
+            if (DEBUG_ANIM) Slog.i(TAG, "Reparenting to original parent");
+            t.reparent(surface, parent.getHandle());
+        }
+        mLeash = null;
+        mAnimation = null;
+
+        // Make sure to inform the animatable after the leash was destroyed.
+        if (destroy) {
+            mAnimatable.onLeashDestroyed(t);
+        }
+    }
+
+    private SurfaceControl createAnimationLeash(SurfaceControl surface, Transaction t, int width,
+            int height, boolean hidden) {
+        if (DEBUG_ANIM) Slog.i(TAG, "Reparenting to leash");
+        final SurfaceControl.Builder builder = mAnimatable.makeLeash()
+                .setName(surface + " - animation-leash")
+                .setSize(width, height);
+        final SurfaceControl leash = builder.build();
+        if (!hidden) {
+            t.show(leash);
+        }
+        t.reparent(surface, leash.getHandle());
+        return leash;
+    }
+
+    void dump(PrintWriter pw, String prefix) {
+        pw.print(prefix); pw.print("mAnimation="); pw.print(mAnimation);
+        pw.print(" mLeash="); pw.println(mLeash);
+    }
+
+    /**
+     * Callback to be passed into {@link AnimationAdapter#startAnimation} to be invoked by the
+     * component that is running the animation when the animation is finished.
+     */
+    interface OnAnimationFinishedCallback {
+        void onAnimationFinished(AnimationAdapter anim);
+    }
+
+    /**
+     * Interface to be animated by {@link SurfaceAnimator}.
+     */
+    interface Animatable {
+
+        /**
+         * @return The pending transaction that will be committed in the next frame.
+         */
+        @NonNull Transaction getPendingTransaction();
+
+        /**
+         * Schedules a commit of the pending transaction.
+         */
+        void commitPendingTransaction();
+
+        /**
+         * Called when the was created.
+         *
+         * @param t The transaction to use to apply any necessary changes.
+         * @param leash The leash that was created.
+         */
+        void onLeashCreated(Transaction t, SurfaceControl leash);
+
+        /**
+         * Called when the leash is being destroyed, and the surface was reparented back to the
+         * original parent.
+         *
+         * @param t The transaction to use to apply any necessary changes.
+         */
+        void onLeashDestroyed(Transaction t);
+
+        /**
+         * @return A new child surface.
+         */
+        SurfaceControl.Builder makeLeash();
+
+        /**
+         * @return The surface of the object to be animated.
+         */
+        @Nullable SurfaceControl getSurface();
+
+        /**
+         * @return The parent of the surface object to be animated.
+         */
+        @Nullable SurfaceControl getParentSurface();
+
+        /**
+         * @return The width of the surface to be animated.
+         */
+        int getSurfaceWidth();
+
+        /**
+         * @return The height of the surface to be animated.
+         */
+        int getSurfaceHeight();
+    }
+}
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 87d0a40..ca9f3a9 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -16,15 +16,11 @@
 
 package com.android.server.wm;
 
-import static android.app.ActivityManager.SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT;
-import static android.app.ActivityManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
 import static android.app.ActivityManager.RESIZE_MODE_USER;
 import static android.app.ActivityManager.RESIZE_MODE_USER_FORCED;
-import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
-import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.dipToPixel;
@@ -44,7 +40,6 @@
 import android.view.BatchedInputEventReceiver;
 import android.view.Choreographer;
 import android.view.Display;
-import android.view.DisplayInfo;
 import android.view.InputChannel;
 import android.view.InputDevice;
 import android.view.InputEvent;
diff --git a/services/core/java/com/android/server/wm/TaskPositioningController.java b/services/core/java/com/android/server/wm/TaskPositioningController.java
new file mode 100644
index 0000000..bb5706c
--- /dev/null
+++ b/services/core/java/com/android/server/wm/TaskPositioningController.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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 static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.annotation.Nullable;
+import android.app.IActivityManager;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.view.Display;
+import android.view.IWindow;
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.input.InputManagerService;
+import com.android.server.input.InputWindowHandle;
+
+/**
+ * Controller for task positioning by drag.
+ */
+class TaskPositioningController {
+    private final WindowManagerService mService;
+    private final InputManagerService mInputManager;
+    private final InputMonitor mInputMonitor;
+    private final IActivityManager mActivityManager;
+
+    @GuardedBy("WindowManagerSerivce.mWindowMap")
+    private @Nullable TaskPositioner mTaskPositioner;
+
+    boolean isPositioningLocked() {
+        return mTaskPositioner != null;
+    }
+
+    InputWindowHandle getDragWindowHandleLocked() {
+        return mTaskPositioner != null ? mTaskPositioner.mDragWindowHandle : null;
+    }
+
+    TaskPositioningController(WindowManagerService service, InputManagerService inputManager,
+            InputMonitor inputMonitor, IActivityManager activityManager) {
+        mService = service;
+        mInputMonitor = inputMonitor;
+        mInputManager = inputManager;
+        mActivityManager = activityManager;
+    }
+
+    boolean startMovingTask(IWindow window, float startX, float startY) {
+        WindowState win = null;
+        synchronized (mService.mWindowMap) {
+            win = mService.windowForClientLocked(null, window, false);
+            // win shouldn't be null here, pass it down to startPositioningLocked
+            // to get warning if it's null.
+            if (!startPositioningLocked(
+                    win, false /*resize*/, false /*preserveOrientation*/, startX, startY)) {
+                return false;
+            }
+        }
+        try {
+            mActivityManager.setFocusedTask(win.getTask().mTaskId);
+        } catch(RemoteException e) {}
+        return true;
+    }
+
+    void handleTapOutsideTask(DisplayContent displayContent, int x, int y) {
+        int taskId = -1;
+        synchronized (mService.mWindowMap) {
+            final Task task = displayContent.findTaskForResizePoint(x, y);
+            if (task != null) {
+                if (!startPositioningLocked(task.getTopVisibleAppMainWindow(), true /*resize*/,
+                        task.preserveOrientationOnResize(), x, y)) {
+                    return;
+                }
+                taskId = task.mTaskId;
+            } else {
+                taskId = displayContent.taskIdFromPoint(x, y);
+            }
+        }
+        if (taskId >= 0) {
+            try {
+                mActivityManager.setFocusedTask(taskId);
+            } catch(RemoteException e) {}
+        }
+    }
+
+    private boolean startPositioningLocked(WindowState win, boolean resize,
+            boolean preserveOrientation, float startX, float startY) {
+        if (DEBUG_TASK_POSITIONING)
+            Slog.d(TAG_WM, "startPositioningLocked: "
+                    + "win=" + win + ", resize=" + resize + ", preserveOrientation="
+                    + preserveOrientation + ", {" + startX + ", " + startY + "}");
+
+        if (win == null || win.getAppToken() == null) {
+            Slog.w(TAG_WM, "startPositioningLocked: Bad window " + win);
+            return false;
+        }
+        if (win.mInputChannel == null) {
+            Slog.wtf(TAG_WM, "startPositioningLocked: " + win + " has no input channel, "
+                    + " probably being removed");
+            return false;
+        }
+
+        final DisplayContent displayContent = win.getDisplayContent();
+        if (displayContent == null) {
+            Slog.w(TAG_WM, "startPositioningLocked: Invalid display content " + win);
+            return false;
+        }
+
+        Display display = displayContent.getDisplay();
+        mTaskPositioner = new TaskPositioner(mService);
+        mTaskPositioner.register(displayContent);
+        mInputMonitor.updateInputWindowsLw(true /*force*/);
+
+        // We need to grab the touch focus so that the touch events during the
+        // resizing/scrolling are not sent to the app. 'win' is the main window
+        // of the app, it may not have focus since there might be other windows
+        // on top (eg. a dialog window).
+        WindowState transferFocusFromWin = win;
+        if (mService.mCurrentFocus != null && mService.mCurrentFocus != win
+                && mService.mCurrentFocus.mAppToken == win.mAppToken) {
+            transferFocusFromWin = mService.mCurrentFocus;
+        }
+        if (!mInputManager.transferTouchFocus(
+                transferFocusFromWin.mInputChannel, mTaskPositioner.mServerChannel)) {
+            Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus");
+            mTaskPositioner.unregister();
+            mTaskPositioner = null;
+            mInputMonitor.updateInputWindowsLw(true /*force*/);
+            return false;
+        }
+
+        mTaskPositioner.startDrag(win, resize, preserveOrientation, startX, startY);
+        return true;
+    }
+
+    void finishPositioning() {
+        if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM, "finishPositioning");
+
+        synchronized (mService.mWindowMap) {
+            if (mTaskPositioner != null) {
+                mTaskPositioner.unregister();
+                mTaskPositioner = null;
+                mInputMonitor.updateInputWindowsLw(true /*force*/);
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 832d395..28b1390 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1114,12 +1114,12 @@
             return false;
         }
 
-        final Rect displayContentRect = mTmpRect;
+        final Rect displayStableRect = mTmpRect;
         final Rect contentBounds = mTmpRect2;
 
         // Calculate the content bounds excluding the area occupied by IME
-        getDisplayContent().getContentRect(displayContentRect);
-        contentBounds.set(displayContentRect);
+        getDisplayContent().getStableRect(displayStableRect);
+        contentBounds.set(displayStableRect);
         int imeTop = Math.max(imeWin.getFrameLw().top, contentBounds.top);
 
         imeTop += imeWin.getGivenContentInsetsLw().top;
@@ -1127,7 +1127,7 @@
             contentBounds.bottom = imeTop;
         }
 
-        final int yOffset = displayContentRect.bottom - contentBounds.bottom;
+        final int yOffset = displayStableRect.bottom - contentBounds.bottom;
 
         final int dividerWidth =
                 getDisplayContent().mDividerControllerLocked.getContentWidth();
@@ -1139,7 +1139,7 @@
             // occluded by IME. We shift its bottom up by the height of the IME, but
             // leaves at least 30% of the top stack visible.
             final int minTopStackBottom =
-                    getMinTopStackBottom(displayContentRect, getRawBounds().bottom);
+                    getMinTopStackBottom(displayStableRect, getRawBounds().bottom);
             final int bottom = Math.max(
                     getRawBounds().bottom - yOffset + dividerWidth - dividerWidthInactive,
                     minTopStackBottom);
@@ -1159,7 +1159,7 @@
             final int topBeforeImeAdjust =
                     getRawBounds().top - dividerWidth + dividerWidthInactive;
             final int minTopStackBottom =
-                    getMinTopStackBottom(displayContentRect,
+                    getMinTopStackBottom(displayStableRect,
                             getRawBounds().top - dividerWidth);
             final int top = Math.max(
                     getRawBounds().top - yOffset, minTopStackBottom + dividerWidthInactive);
diff --git a/services/core/java/com/android/server/wm/WindowAnimationSpec.java b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
new file mode 100644
index 0000000..56175c7
--- /dev/null
+++ b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.graphics.Point;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
+import android.view.animation.Animation;
+import android.view.animation.Transformation;
+
+import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
+
+/**
+ * Animation spec for regular window animations.
+ */
+public class WindowAnimationSpec implements AnimationSpec {
+
+    private Animation mAnimation;
+    private final Point mPosition = new Point();
+    private final ThreadLocal<Tmp> mThreadLocalTmps = ThreadLocal.withInitial(Tmp::new);
+
+    public WindowAnimationSpec(Animation animation, Point position)  {
+        mAnimation = animation;
+        mPosition.set(position.x, position.y);
+    }
+
+    @Override
+    public boolean getDetachWallpaper() {
+        return mAnimation.getDetachWallpaper();
+    }
+
+    @Override
+    public int getBackgroundColor() {
+        return mAnimation.getBackgroundColor();
+    }
+
+    @Override
+    public long getDuration() {
+        return mAnimation.computeDurationHint();
+    }
+
+    @Override
+    public void apply(Transaction t, SurfaceControl leash, long currentPlayTime) {
+        final Tmp tmp = mThreadLocalTmps.get();
+        tmp.transformation.clear();
+        mAnimation.getTransformation(currentPlayTime, tmp.transformation);
+        tmp.transformation.getMatrix().postTranslate(mPosition.x, mPosition.y);
+        t.setMatrix(leash, tmp.transformation.getMatrix(), tmp.floats);
+        t.setAlpha(leash, tmp.transformation.getAlpha());
+    }
+
+    private static class Tmp {
+        final Transformation transformation = new Transformation();
+        final float[] floats = new float[9];
+    }
+}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e598224..8c9948e 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -755,7 +755,7 @@
     // Whether or not a layout can cause a wake up when theater mode is enabled.
     boolean mAllowTheaterModeWakeFromLayout;
 
-    TaskPositioner mTaskPositioner;
+    final TaskPositioningController mTaskPositioningController;
     final DragDropController mDragDropController;
 
     // For frozen screen animations.
@@ -769,6 +769,7 @@
     int mTransactionSequence;
 
     final WindowAnimator mAnimator;
+    final SurfaceAnimationRunner mSurfaceAnimationRunner;
 
     final BoundsAnimationController mBoundsAnimationController;
 
@@ -1082,10 +1083,13 @@
         mHoldingScreenWakeLock.setReferenceCounted(false);
 
         mAnimator = new WindowAnimator(this);
+        mSurfaceAnimationRunner = new SurfaceAnimationRunner();
 
         mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
 
+        mTaskPositioningController =
+                new TaskPositioningController(this, mInputManager, mInputMonitor, mActivityManager);
         mDragDropController = new DragDropController(this, mH.getLooper());
 
         LocalServices.addService(WindowManagerInternal.class, new LocalService());
@@ -4440,107 +4444,6 @@
         }
     }
 
-    boolean startMovingTask(IWindow window, float startX, float startY) {
-        WindowState win = null;
-        synchronized (mWindowMap) {
-            win = windowForClientLocked(null, window, false);
-            // win shouldn't be null here, pass it down to startPositioningLocked
-            // to get warning if it's null.
-            if (!startPositioningLocked(
-                        win, false /*resize*/, false /*preserveOrientation*/, startX, startY)) {
-                return false;
-            }
-        }
-        try {
-            mActivityManager.setFocusedTask(win.getTask().mTaskId);
-        } catch(RemoteException e) {}
-        return true;
-    }
-
-    private void handleTapOutsideTask(DisplayContent displayContent, int x, int y) {
-        int taskId = -1;
-        synchronized (mWindowMap) {
-            final Task task = displayContent.findTaskForResizePoint(x, y);
-            if (task != null) {
-                if (!startPositioningLocked(task.getTopVisibleAppMainWindow(), true /*resize*/,
-                            task.preserveOrientationOnResize(), x, y)) {
-                    return;
-                }
-                taskId = task.mTaskId;
-            } else {
-                taskId = displayContent.taskIdFromPoint(x, y);
-            }
-        }
-        if (taskId >= 0) {
-            try {
-                mActivityManager.setFocusedTask(taskId);
-            } catch(RemoteException e) {}
-        }
-    }
-
-    private boolean startPositioningLocked(WindowState win, boolean resize,
-            boolean preserveOrientation, float startX, float startY) {
-        if (DEBUG_TASK_POSITIONING)
-            Slog.d(TAG_WM, "startPositioningLocked: "
-                            + "win=" + win + ", resize=" + resize + ", preserveOrientation="
-                            + preserveOrientation + ", {" + startX + ", " + startY + "}");
-
-        if (win == null || win.getAppToken() == null) {
-            Slog.w(TAG_WM, "startPositioningLocked: Bad window " + win);
-            return false;
-        }
-        if (win.mInputChannel == null) {
-            Slog.wtf(TAG_WM, "startPositioningLocked: " + win + " has no input channel, "
-                    + " probably being removed");
-            return false;
-        }
-
-        final DisplayContent displayContent = win.getDisplayContent();
-        if (displayContent == null) {
-            Slog.w(TAG_WM, "startPositioningLocked: Invalid display content " + win);
-            return false;
-        }
-
-        Display display = displayContent.getDisplay();
-        mTaskPositioner = new TaskPositioner(this);
-        mTaskPositioner.register(displayContent);
-        mInputMonitor.updateInputWindowsLw(true /*force*/);
-
-        // We need to grab the touch focus so that the touch events during the
-        // resizing/scrolling are not sent to the app. 'win' is the main window
-        // of the app, it may not have focus since there might be other windows
-        // on top (eg. a dialog window).
-        WindowState transferFocusFromWin = win;
-        if (mCurrentFocus != null && mCurrentFocus != win
-                && mCurrentFocus.mAppToken == win.mAppToken) {
-            transferFocusFromWin = mCurrentFocus;
-        }
-        if (!mInputManager.transferTouchFocus(
-                transferFocusFromWin.mInputChannel, mTaskPositioner.mServerChannel)) {
-            Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus");
-            mTaskPositioner.unregister();
-            mTaskPositioner = null;
-            mInputMonitor.updateInputWindowsLw(true /*force*/);
-            return false;
-        }
-
-        mTaskPositioner.startDrag(win, resize, preserveOrientation, startX, startY);
-        return true;
-    }
-
-    private void finishPositioning() {
-        if (DEBUG_TASK_POSITIONING) {
-            Slog.d(TAG_WM, "finishPositioning");
-        }
-        synchronized (mWindowMap) {
-            if (mTaskPositioner != null) {
-                mTaskPositioner.unregister();
-                mTaskPositioner = null;
-                mInputMonitor.updateInputWindowsLw(true /*force*/);
-            }
-        }
-    }
-
     // -------------------------------------------------------------
     // Input Events and Focus Management
     // -------------------------------------------------------------
@@ -5003,12 +4906,13 @@
                 }
 
                 case TAP_OUTSIDE_TASK: {
-                    handleTapOutsideTask((DisplayContent)msg.obj, msg.arg1, msg.arg2);
+                    mTaskPositioningController.handleTapOutsideTask(
+                            (DisplayContent)msg.obj, msg.arg1, msg.arg2);
                 }
                 break;
 
                 case FINISH_TASK_POSITIONING: {
-                    finishPositioning();
+                    mTaskPositioningController.finishPositioning();
                 }
                 break;
 
diff --git a/services/coverage/Android.bp b/services/coverage/Android.bp
new file mode 100644
index 0000000..16c9c1b
--- /dev/null
+++ b/services/coverage/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+    name: "services.coverage",
+    srcs: ["java/**/*.java"],
+    libs: ["jacocoagent"],
+}
diff --git a/services/coverage/Android.mk b/services/coverage/Android.mk
deleted file mode 100644
index da99994..0000000
--- a/services/coverage/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.coverage
-
-LOCAL_SRC_FILES += \
-      $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := jacocoagent
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/devicepolicy/Android.bp b/services/devicepolicy/Android.bp
new file mode 100644
index 0000000..0505204
--- /dev/null
+++ b/services/devicepolicy/Android.bp
@@ -0,0 +1,9 @@
+java_library_static {
+    name: "services.devicepolicy",
+    srcs: ["java/**/*.java"],
+
+    libs: [
+        "conscrypt",
+        "services.core",
+    ],
+}
diff --git a/services/devicepolicy/Android.mk b/services/devicepolicy/Android.mk
deleted file mode 100644
index 7020f17..0000000
--- a/services/devicepolicy/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.devicepolicy
-
-LOCAL_SRC_FILES += \
-      $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := conscrypt services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b979ff4..91ba87e 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -79,7 +79,6 @@
 import android.app.admin.DeviceAdminReceiver;
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
-import android.app.admin.IDevicePolicyManager;
 import android.app.admin.NetworkEvent;
 import android.app.admin.PasswordMetrics;
 import android.app.admin.SecurityLog;
@@ -740,7 +739,7 @@
         private static final String TAG_ORGANIZATION_NAME = "organization-name";
         private static final String ATTR_LAST_NETWORK_LOGGING_NOTIFICATION = "last-notification";
         private static final String ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS = "num-notifications";
-        private static final String TAG_IS_LOGOUT_BUTTON_ENABLED = "is_logout_button_enabled";
+        private static final String TAG_IS_LOGOUT_ENABLED = "is_logout_enabled";
 
         final DeviceAdminInfo info;
 
@@ -790,7 +789,7 @@
         boolean requireAutoTime = false; // Can only be set by a device owner.
         boolean forceEphemeralUsers = false; // Can only be set by a device owner.
         boolean isNetworkLoggingEnabled = false; // Can only be set by a device owner.
-        boolean isLogoutButtonEnabled = false; // Can only be set by a device owner.
+        boolean isLogoutEnabled = false; // Can only be set by a device owner.
 
         // one notification after enabling + one more after reboots
         static final int DEF_MAXIMUM_NETWORK_LOGGING_NOTIFICATIONS_SHOWN = 2;
@@ -1108,10 +1107,10 @@
                 out.text(organizationName);
                 out.endTag(null, TAG_ORGANIZATION_NAME);
             }
-            if (isLogoutButtonEnabled) {
-                out.startTag(null, TAG_IS_LOGOUT_BUTTON_ENABLED);
-                out.attribute(null, ATTR_VALUE, Boolean.toString(isLogoutButtonEnabled));
-                out.endTag(null, TAG_IS_LOGOUT_BUTTON_ENABLED);
+            if (isLogoutEnabled) {
+                out.startTag(null, TAG_IS_LOGOUT_ENABLED);
+                out.attribute(null, ATTR_VALUE, Boolean.toString(isLogoutEnabled));
+                out.endTag(null, TAG_IS_LOGOUT_ENABLED);
             }
         }
 
@@ -1286,8 +1285,8 @@
                     } else {
                         Log.w(LOG_TAG, "Missing text when loading organization name");
                     }
-                } else if (TAG_IS_LOGOUT_BUTTON_ENABLED.equals(tag)) {
-                    isLogoutButtonEnabled = Boolean.parseBoolean(
+                } else if (TAG_IS_LOGOUT_ENABLED.equals(tag)) {
+                    isLogoutEnabled = Boolean.parseBoolean(
                             parser.getAttributeValue(null, ATTR_VALUE));
                 } else {
                     Slog.w(LOG_TAG, "Unknown admin tag: " + tag);
@@ -11581,35 +11580,35 @@
     }
 
     @Override
-    public synchronized void setLogoutButtonEnabled(ComponentName admin, boolean enabled) {
+    public synchronized void setLogoutEnabled(ComponentName admin, boolean enabled) {
         if (!mHasFeature) {
             return;
         }
         Preconditions.checkNotNull(admin);
         getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
 
-        if (enabled == isLogoutButtonEnabledInternalLocked()) {
+        if (enabled == isLogoutEnabledInternalLocked()) {
             // already in the requested state
             return;
         }
         ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
-        deviceOwner.isLogoutButtonEnabled = enabled;
+        deviceOwner.isLogoutEnabled = enabled;
         saveSettingsLocked(mInjector.userHandleGetCallingUserId());
     }
 
     @Override
-    public boolean isLogoutButtonEnabled() {
+    public boolean isLogoutEnabled() {
         if (!mHasFeature) {
             return false;
         }
         synchronized (this) {
-            return isLogoutButtonEnabledInternalLocked();
+            return isLogoutEnabledInternalLocked();
         }
     }
 
-    private boolean isLogoutButtonEnabledInternalLocked() {
+    private boolean isLogoutEnabledInternalLocked() {
         ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
-        return (deviceOwner != null) && deviceOwner.isLogoutButtonEnabled;
+        return (deviceOwner != null) && deviceOwner.isLogoutEnabled;
     }
 
 }
diff --git a/services/midi/Android.bp b/services/midi/Android.bp
new file mode 100644
index 0000000..3745e89
--- /dev/null
+++ b/services/midi/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+    name: "services.midi",
+    srcs: ["java/**/*.java"],
+    libs: ["services.core"],
+}
diff --git a/services/midi/Android.mk b/services/midi/Android.mk
deleted file mode 100644
index faac01c..0000000
--- a/services/midi/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.midi
-
-LOCAL_SRC_FILES += \
-      $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/net/Android.bp b/services/net/Android.bp
new file mode 100644
index 0000000..e0ae68f
--- /dev/null
+++ b/services/net/Android.bp
@@ -0,0 +1,4 @@
+java_library_static {
+    name: "services.net",
+    srcs: ["java/**/*.java"],
+}
diff --git a/services/net/Android.mk b/services/net/Android.mk
deleted file mode 100644
index 408794e..0000000
--- a/services/net/Android.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.net
-
-LOCAL_SRC_FILES += \
-    $(call all-java-files-under,java)
-
-LOCAL_AIDL_INCLUDES += \
-    system/netd/server/binder
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java
index b305b33..fdb366c 100644
--- a/services/net/java/android/net/ip/IpClient.java
+++ b/services/net/java/android/net/ip/IpClient.java
@@ -163,10 +163,10 @@
     // TODO: Find an lighter weight approach.
     private class LoggingCallbackWrapper extends Callback {
         private static final String PREFIX = "INVOKE ";
-        private final Callback mCallback;
+        private Callback mCallback;
 
         public LoggingCallbackWrapper(Callback callback) {
-            mCallback = (callback != null) ? callback : new Callback();
+            mCallback = callback;
         }
 
         private void log(String msg) {
@@ -1283,7 +1283,6 @@
             stopAllIP();
 
             resetLinkProperties();
-            mCallback.onLinkPropertiesChange(new LinkProperties(mLinkProperties));
             if (mStartTimeMillis > 0) {
                 recordMetric(IpManagerEvent.COMPLETE_LIFECYCLE);
                 mStartTimeMillis = 0;
diff --git a/services/print/Android.bp b/services/print/Android.bp
new file mode 100644
index 0000000..80a8c75
--- /dev/null
+++ b/services/print/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+    name: "services.print",
+    srcs: ["java/**/*.java"],
+    libs: ["services.core"],
+}
diff --git a/services/print/Android.mk b/services/print/Android.mk
deleted file mode 100644
index 00eb2e4..0000000
--- a/services/print/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.print
-
-LOCAL_SRC_FILES += \
-      $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/restrictions/Android.bp b/services/restrictions/Android.bp
new file mode 100644
index 0000000..979e891
--- /dev/null
+++ b/services/restrictions/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+    name: "services.restrictions",
+    srcs: ["java/**/*.java"],
+    libs: ["services.core"],
+}
diff --git a/services/restrictions/Android.mk b/services/restrictions/Android.mk
deleted file mode 100644
index 57d1c46..0000000
--- a/services/restrictions/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.restrictions
-
-LOCAL_SRC_FILES += \
-      $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/tests/Android.mk b/services/tests/Android.mk
deleted file mode 100644
index 40369ee..0000000
--- a/services/tests/Android.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java
index 7160d7f..a44f5c4 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java
@@ -19,6 +19,7 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 
+import android.content.Intent;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -61,14 +62,13 @@
         mController = new ActivityStartController(mService, mService.mStackSupervisor, mFactory);
         mStarter = spy(new ActivityStarter(mController, mService, mService.mStackSupervisor,
                 mock(ActivityStartInterceptor.class)));
-        doReturn(mStarter).when(mFactory).obtainStarter();
+        doReturn(mStarter).when(mFactory).obtain();
     }
 
     /**
      * Ensures that pending launches are processed.
      */
     @Test
-    @Presubmit
     public void testPendingActivityLaunches() {
         final Random random = new Random();
 
@@ -88,4 +88,20 @@
         verify(mStarter, times(1)).startResolvedActivity(eq(activity), eq(source), eq(null),
                 eq(null), eq(startFlags), eq(resume), eq(null), eq(null), eq(null));
     }
+
+
+    /**
+     * Ensures instances are recycled after execution.
+     */
+    @Test
+    public void testRecycling() throws Exception {
+        final Intent intent = new Intent();
+        final ActivityStarter optionStarter = new ActivityStarter(mController, mService,
+                mService.mStackSupervisor, mock(ActivityStartInterceptor.class));
+        optionStarter
+                .setIntent(intent)
+                .setReason("Test")
+                .execute();
+        verify(mFactory, times(1)).recycle(eq(optionStarter));
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
index e8194dd..589a89b 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
@@ -63,6 +63,7 @@
 import static android.app.ActivityManager.START_INTENT_NOT_RESOLVED;
 
 import com.android.internal.os.BatteryStatsImpl;
+import com.android.server.am.ActivityStarter.Factory;
 
 /**
  * Tests for the {@link ActivityStarter} class.
diff --git a/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java b/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java
index 0ea8d4f..5d739a3 100644
--- a/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java
@@ -32,6 +32,9 @@
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.time.Clock;
+import java.time.Instant;
+import java.time.ZoneId;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -57,7 +60,7 @@
     private ConfigHelper mMockConfigHelper;
     private PackageManagerHelper mMockPackageManagerHelper;
 
-    private FakeClockHelper mFakeClock;
+    private FakeClock mFakeClock;
     private FakeIntentHelper mFakeIntentHelper;
     private PackageStatusStorage mPackageStatusStorage;
     private PackageTracker mPackageTracker;
@@ -66,7 +69,7 @@
     public void setUp() throws Exception {
         Context context = InstrumentationRegistry.getContext();
 
-        mFakeClock = new FakeClockHelper();
+        mFakeClock = new FakeClock();
 
         // Read-only interfaces so are easy to mock.
         mMockConfigHelper = mock(ConfigHelper.class);
@@ -1444,18 +1447,33 @@
         }
     }
 
-    private static class FakeClockHelper implements ClockHelper {
+    private static class FakeClock extends Clock {
 
         private long currentTime = 1000;
 
         @Override
-        public long currentTimestamp() {
+        public long millis() {
             return currentTime;
         }
 
         public void incrementClock(long millis) {
             currentTime += millis;
         }
+
+        @Override
+        public ZoneId getZone() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Clock withZone(ZoneId zone) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Instant instant() {
+            throw new UnsupportedOperationException();
+        }
     }
 
     /**
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 87b34ab..86ce90c 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -18,6 +18,7 @@
 
 import static android.app.usage.UsageEvents.Event.NOTIFICATION_SEEN;
 import static android.app.usage.UsageEvents.Event.USER_INTERACTION;
+import static android.app.usage.UsageStatsManager.REASON_PREDICTED;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
@@ -364,4 +365,29 @@
         reportEvent(controller, NOTIFICATION_SEEN, mInjector.mElapsedRealtime);
         assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(controller));
     }
+
+    @Test
+    public void testPredictionTimedout() throws Exception {
+        AppStandbyController controller = setupController();
+        setChargingState(controller, false);
+        controller.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
+                REASON_PREDICTED + "CTS", 1 * HOUR_MS);
+
+        // Fast forward 12 hours
+        mInjector.mElapsedRealtime += WORKING_SET_THRESHOLD;
+        controller.checkIdleStates(USER_ID);
+        // Should still be in predicted bucket, since prediction timeout is 1 day since prediction
+        assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(controller));
+        // Fast forward two more hours
+        mInjector.mElapsedRealtime += 2 * HOUR_MS;
+        controller.checkIdleStates(USER_ID);
+        // Should have now applied prediction timeout
+        assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(controller));
+
+        // Fast forward RARE bucket
+        mInjector.mElapsedRealtime += RARE_THRESHOLD;
+        controller.checkIdleStates(USER_ID);
+        // Should continue to apply prediction timeout
+        assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(controller));
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
new file mode 100644
index 0000000..9ecf51e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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 static java.util.concurrent.TimeUnit.SECONDS;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.verify;
+
+import android.animation.AnimationHandler.AnimationFrameCallbackProvider;
+import android.graphics.Matrix;
+import android.graphics.Point;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.Choreographer;
+import android.view.Choreographer.FrameCallback;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
+import android.view.animation.Animation;
+import android.view.animation.TranslateAnimation;
+
+import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * Test class for {@link SurfaceAnimationRunner}.
+ *
+ * runtest frameworks-services -c com.android.server.wm.SurfaceAnimationRunnerTest
+ */
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class SurfaceAnimationRunnerTest extends WindowTestsBase {
+
+    @Mock SurfaceControl mMockSurface;
+    @Mock Transaction mMockTransaction;
+    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    private SurfaceAnimationRunner mSurfaceAnimationRunner;
+    private CountDownLatch mFinishCallbackLatch;
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        mFinishCallbackLatch = new CountDownLatch(1);
+        mSurfaceAnimationRunner = new SurfaceAnimationRunner(null /* callbackProvider */,
+                mMockTransaction);
+    }
+
+    private void finishedCallback() {
+        mFinishCallbackLatch.countDown();
+    }
+
+    @Test
+    public void testAnimation() throws Exception {
+        mSurfaceAnimationRunner
+                .startAnimation(createTranslateAnimation(), mMockSurface, mMockTransaction,
+                this::finishedCallback);
+
+        // Ensure that the initial transformation has been applied.
+        final Matrix m = new Matrix();
+        m.setTranslate(-10, 0);
+        verify(mMockTransaction, atLeastOnce()).setMatrix(eq(mMockSurface), eq(m), any());
+        verify(mMockTransaction, atLeastOnce()).setAlpha(eq(mMockSurface), eq(1.0f));
+
+        mFinishCallbackLatch.await(1, SECONDS);
+        assertFinishCallbackCalled();
+
+        m.setTranslate(10, 0);
+        verify(mMockTransaction, atLeastOnce()).setMatrix(eq(mMockSurface), eq(m), any());
+
+        // At least 3 times: After initialization, first frame, last frame.
+        verify(mMockTransaction, atLeast(3)).setAlpha(eq(mMockSurface), eq(1.0f));
+    }
+
+    @Test
+    public void testCancel_notStarted() throws Exception {
+        mSurfaceAnimationRunner = new SurfaceAnimationRunner(new NoOpFrameCallbackProvider(), mMockTransaction);
+        mSurfaceAnimationRunner
+                .startAnimation(createTranslateAnimation(), mMockSurface, mMockTransaction,
+                this::finishedCallback);
+        mSurfaceAnimationRunner.onAnimationCancelled(mMockSurface);
+        waitUntilHandlersIdle();
+        assertTrue(mSurfaceAnimationRunner.mPendingAnimations.isEmpty());
+        assertFinishCallbackNotCalled();
+        //verify(mMockSurface).release();
+    }
+
+    @Test
+    public void testCancel_running() throws Exception {
+        mSurfaceAnimationRunner = new SurfaceAnimationRunner(new NoOpFrameCallbackProvider(), mMockTransaction);
+        mSurfaceAnimationRunner
+                .startAnimation(createTranslateAnimation(), mMockSurface, mMockTransaction,
+                this::finishedCallback);
+        waitUntilNextFrame();
+        assertFalse(mSurfaceAnimationRunner.mRunningAnimations.isEmpty());
+        mSurfaceAnimationRunner.onAnimationCancelled(mMockSurface);
+        assertTrue(mSurfaceAnimationRunner.mRunningAnimations.isEmpty());
+        waitUntilHandlersIdle();
+        assertFinishCallbackNotCalled();
+        //verify(mMockSurface).release();
+    }
+
+    private void waitUntilNextFrame() throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
+        mSurfaceAnimationRunner.mChoreographer.postCallback(Choreographer.CALLBACK_COMMIT,
+                latch::countDown, null /* token */);
+        latch.await();
+    }
+
+    private void assertFinishCallbackCalled() {
+        assertEquals(0, mFinishCallbackLatch.getCount());
+    }
+
+    private void assertFinishCallbackNotCalled() {
+        assertEquals(1, mFinishCallbackLatch.getCount());
+    }
+
+    private AnimationSpec createTranslateAnimation() {
+        final Animation a = new TranslateAnimation(-10, 10, 0, 0);
+        a.initialize(0, 0, 0, 0);
+        a.setDuration(50);
+        return new WindowAnimationSpec(a, new Point(0, 0));
+    }
+
+    /**
+     * Callback provider that doesn't animate at all.
+     */
+    private static final class NoOpFrameCallbackProvider implements AnimationFrameCallbackProvider {
+
+        @Override
+        public void postFrameCallback(FrameCallback callback) {
+        }
+
+        @Override
+        public void postCommitCallback(Runnable runnable) {
+        }
+
+        @Override
+        public long getFrameTime() {
+            return 0;
+        }
+
+        @Override
+        public long getFrameDelay() {
+            return 0;
+        }
+
+        @Override
+        public void setFrameDelay(long delay) {
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java
new file mode 100644
index 0000000..9a52042
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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 static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Builder;
+import android.view.SurfaceControl.Transaction;
+import android.view.SurfaceSession;
+
+import com.google.android.collect.Lists;
+
+import com.android.server.wm.SurfaceAnimator.Animatable;
+import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+
+/**
+ * Test class for {@link SurfaceAnimatorTest}.
+ *
+ * runtest frameworks-services -c com.android.server.wm.SurfaceAnimatorTest
+ */
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class SurfaceAnimatorTest extends WindowTestsBase {
+
+    @Mock
+    AnimationAdapter mSpec;
+    @Mock
+    AnimationAdapter mSpec2;
+    @Mock Transaction mTransaction;
+
+    private SurfaceAnimator mSurfaceAnimator;
+    private SurfaceControl mParent;
+    private SurfaceControl mSurface;
+    private boolean mFinishedCallbackCalled;
+    private SurfaceControl mLeash;
+    private SurfaceSession mSession = new SurfaceSession();
+
+    private final Animatable mAnimatable = new Animatable() {
+        @Override
+        public Transaction getPendingTransaction() {
+            return mTransaction;
+        }
+
+        @Override
+        public void commitPendingTransaction() {
+        }
+
+        @Override
+        public void onLeashCreated(Transaction t, SurfaceControl leash) {
+        }
+
+        @Override
+        public void onLeashDestroyed(Transaction t) {
+        }
+
+        @Override
+        public Builder makeLeash() {
+            return new SurfaceControl.Builder(mSession) {
+
+                @Override
+                public SurfaceControl build() {
+                    mLeash = super.build();
+                    return mLeash;
+                }
+            }.setParent(mParent);
+        }
+
+        @Override
+        public SurfaceControl getSurface() {
+            return mSurface;
+        }
+
+        @Override
+        public SurfaceControl getParentSurface() {
+            return mParent;
+        }
+
+        @Override
+        public int getSurfaceWidth() {
+            return 1;
+        }
+
+        @Override
+        public int getSurfaceHeight() {
+            return 1;
+        }
+    };
+
+    private final Runnable mFinishedCallback = () -> {
+        mFinishedCallbackCalled = true;
+    };
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        MockitoAnnotations.initMocks(this);
+        mParent = sWm.makeSurfaceBuilder(mSession)
+                .setName("test surface parent")
+                .setSize(3000, 3000)
+                .build();
+        mSurface = sWm.makeSurfaceBuilder(mSession)
+                .setName("test surface")
+                .setSize(1, 1)
+                .build();
+        mFinishedCallbackCalled = false;
+        mLeash = null;
+        mSurfaceAnimator = new SurfaceAnimator(mAnimatable, mFinishedCallback, sWm);
+    }
+
+    @Test
+    public void testRunAnimation() throws Exception {
+        mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+        final ArgumentCaptor<OnAnimationFinishedCallback> callbackCaptor = ArgumentCaptor.forClass(
+                OnAnimationFinishedCallback.class);
+
+        assertTrue(mSurfaceAnimator.isAnimating());
+        assertNotNull(mSurfaceAnimator.getAnimation());
+        verify(mTransaction).reparent(eq(mSurface), eq(mLeash.getHandle()));
+        verify(mSpec).startAnimation(any(), any(), callbackCaptor.capture());
+
+        callbackCaptor.getValue().onAnimationFinished(mSpec);
+        assertFalse(mSurfaceAnimator.isAnimating());
+        assertNull(mSurfaceAnimator.getAnimation());
+        assertTrue(mFinishedCallbackCalled);
+
+        // TODO: Verify reparenting once we use mPendingTransaction to reparent it back
+    }
+
+    @Test
+    public void testOverrideAnimation() throws Exception {
+        mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+        mSurfaceAnimator.startAnimation(mTransaction, mSpec2, true /* hidden */);
+
+        assertFalse(mFinishedCallbackCalled);
+
+        final ArgumentCaptor<OnAnimationFinishedCallback> callbackCaptor = ArgumentCaptor.forClass(
+                OnAnimationFinishedCallback.class);
+        assertTrue(mSurfaceAnimator.isAnimating());
+        assertNotNull(mSurfaceAnimator.getAnimation());
+        verify(mSpec).startAnimation(any(), any(), callbackCaptor.capture());
+
+        // First animation was finished, but this shouldn't cancel the second animation
+        callbackCaptor.getValue().onAnimationFinished(mSpec);
+        assertTrue(mSurfaceAnimator.isAnimating());
+
+        // Second animation was finished
+        verify(mSpec2).startAnimation(any(), any(), callbackCaptor.capture());
+        callbackCaptor.getValue().onAnimationFinished(mSpec2);
+        assertFalse(mSurfaceAnimator.isAnimating());
+        assertTrue(mFinishedCallbackCalled);
+    }
+
+    @Test
+    public void testCancelAnimation() throws Exception {
+        mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+        assertTrue(mSurfaceAnimator.isAnimating());
+        mSurfaceAnimator.cancelAnimation();
+        assertFalse(mSurfaceAnimator.isAnimating());
+        verify(mSpec).onAnimationCancelled(any());
+        assertTrue(mFinishedCallbackCalled);
+    }
+
+    @Test
+    public void testDelayingAnimationStart() throws Exception {
+        mSurfaceAnimator.startDelayingAnimationStart();
+        mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+        verifyZeroInteractions(mSpec);
+        assertTrue(mSurfaceAnimator.isAnimating());
+        mSurfaceAnimator.endDelayingAnimationStart();
+        verify(mSpec).startAnimation(any(), any(), any());
+    }
+
+    @Test
+    public void testDelayingAnimationStartAndCancelled() throws Exception {
+        mSurfaceAnimator.startDelayingAnimationStart();
+        mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+        mSurfaceAnimator.cancelAnimation();
+        verifyZeroInteractions(mSpec);
+        assertFalse(mSurfaceAnimator.isAnimating());
+        assertTrue(mFinishedCallbackCalled);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java
new file mode 100644
index 0000000..89447a9
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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 static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.InputChannel;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+/**
+ * Tests for the {@link TaskPositioningController} class.
+ *
+ * atest com.android.server.wm.TaskPositioningControllerTests
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+@Presubmit
+public class TaskPositioningControllerTests extends WindowTestsBase {
+    private static final int TIMEOUT_MS = 1000;
+    private TaskPositioningController mTarget;
+    private WindowState mWindow;
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+
+        assertNotNull(sWm.mTaskPositioningController);
+        mTarget = sWm.mTaskPositioningController;
+
+        when(sWm.mInputManager.transferTouchFocus(
+                any(InputChannel.class),
+                any(InputChannel.class))).thenReturn(true);
+
+        mWindow = createWindow(null, TYPE_BASE_APPLICATION, "window");
+        mWindow.mInputChannel = new InputChannel();
+        synchronized (sWm.mWindowMap) {
+            sWm.mWindowMap.put(mWindow.mClient.asBinder(), mWindow);
+        }
+    }
+
+    @Test
+    public void testStartAndFinishPositioning() throws Exception {
+        synchronized (sWm.mWindowMap) {
+            assertFalse(mTarget.isPositioningLocked());
+            assertNull(mTarget.getDragWindowHandleLocked());
+        }
+
+        assertTrue(mTarget.startMovingTask(mWindow.mClient, 0, 0));
+
+        synchronized (sWm.mWindowMap) {
+            assertTrue(mTarget.isPositioningLocked());
+            assertNotNull(mTarget.getDragWindowHandleLocked());
+        }
+
+        assertTrue(sWm.mH.runWithScissors(() -> {
+            mTarget.finishPositioning();
+        }, TIMEOUT_MS));
+
+        assertFalse(mTarget.isPositioningLocked());
+        assertNull(mTarget.getDragWindowHandleLocked());
+    }
+
+    @Test
+    public void testHandleTapOutsideTask() throws Exception {
+        synchronized (sWm.mWindowMap) {
+
+            assertFalse(mTarget.isPositioningLocked());
+            assertNull(mTarget.getDragWindowHandleLocked());
+        }
+
+        final DisplayContent content = mock(DisplayContent.class);
+        when(content.findTaskForResizePoint(anyInt(), anyInt())).thenReturn(mWindow.getTask());
+        assertNotNull(mWindow.getTask().getTopVisibleAppMainWindow());
+
+        mTarget.handleTapOutsideTask(content, 0, 0);
+
+        synchronized (sWm.mWindowMap) {
+            assertTrue(mTarget.isPositioningLocked());
+            assertNotNull(mTarget.getDragWindowHandleLocked());
+        }
+
+        assertTrue(sWm.mH.runWithScissors(() -> {
+            mTarget.finishPositioning();
+        }, TIMEOUT_MS));
+
+        assertFalse(mTarget.isPositioningLocked());
+        assertNull(mTarget.getDragWindowHandleLocked());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 4c5e291..c699a94 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -185,6 +185,7 @@
     void waitUntilHandlersIdle() {
         sWm.mH.runWithScissors(() -> { }, 0);
         sWm.mAnimationHandler.runWithScissors(() -> { }, 0);
+        SurfaceAnimationThread.getHandler().runWithScissors(() -> { }, 0);
     }
 
     private WindowToken createWindowToken(
diff --git a/services/usage/Android.bp b/services/usage/Android.bp
new file mode 100644
index 0000000..1064b6e
--- /dev/null
+++ b/services/usage/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+    name: "services.usage",
+    srcs: ["java/**/*.java"],
+    libs: ["services.core"],
+}
diff --git a/services/usage/Android.mk b/services/usage/Android.mk
deleted file mode 100644
index f1cbe98..0000000
--- a/services/usage/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.usage
-
-LOCAL_SRC_FILES += \
-      $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java
index 5aef55b..6ac4b36 100644
--- a/services/usage/java/com/android/server/usage/AppIdleHistory.java
+++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java
@@ -72,14 +72,13 @@
     private static final String ATTR_SCREEN_IDLE = "screenIdleTime";
     // Elapsed timebase time when app was last used
     private static final String ATTR_ELAPSED_IDLE = "elapsedIdleTime";
+    // Elapsed timebase time when the app bucket was last predicted externally
+    private static final String ATTR_LAST_PREDICTED_TIME = "lastPredictedTime";
+    // The standby bucket for the app
     private static final String ATTR_CURRENT_BUCKET = "appLimitBucket";
+    // The reason the app was put in the above bucket
     private static final String ATTR_BUCKETING_REASON = "bucketReason";
 
-    // State that was last informed to listeners, since boot
-    private static final int STATE_UNINFORMED = 0;
-    private static final int STATE_ACTIVE = 1;
-    private static final int STATE_IDLE = 2;
-
     // device on time = mElapsedDuration + (timeNow - mElapsedSnapshot)
     private long mElapsedSnapshot; // Elapsed time snapshot when last write of mDeviceOnDuration
     private long mElapsedDuration; // Total device on duration since device was "born"
@@ -92,13 +91,21 @@
 
     private boolean mScreenOn;
 
-    private static class AppUsageHistory {
+    static class AppUsageHistory {
+        // Debug
         final byte[] recent = new byte[HISTORY_SIZE];
+        // Last used time using elapsed timebase
         long lastUsedElapsedTime;
+        // Last used time using screen_on timebase
         long lastUsedScreenTime;
+        // Last predicted time using elapsed timebase
+        long lastPredictedTime;
+        // Standby bucket
         @UsageStatsManager.StandbyBuckets
         int currentBucket;
+        // Reason for setting the standby bucket. TODO: Switch to int.
         String bucketingReason;
+        // In-memory only, last bucket for which the listeners were informed
         int lastInformedBucket;
     }
 
@@ -269,6 +276,7 @@
             appUsageHistory = new AppUsageHistory();
             appUsageHistory.lastUsedElapsedTime = getElapsedTime(elapsedRealtime);
             appUsageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime);
+            appUsageHistory.lastPredictedTime = getElapsedTime(0);
             appUsageHistory.currentBucket = UsageStatsManager.STANDBY_BUCKET_NEVER;
             appUsageHistory.bucketingReason = UsageStatsManager.REASON_DEFAULT;
             appUsageHistory.lastInformedBucket = -1;
@@ -295,6 +303,14 @@
         }
     }
 
+    public AppUsageHistory getAppUsageHistory(String packageName, int userId,
+            long elapsedRealtime) {
+        ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
+        AppUsageHistory appUsageHistory =
+                getPackageHistory(userHistory, packageName, elapsedRealtime, true);
+        return appUsageHistory;
+    }
+
     public void setAppStandbyBucket(String packageName, int userId, long elapsedRealtime,
             int bucket, String reason) {
         ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
@@ -302,6 +318,9 @@
                 getPackageHistory(userHistory, packageName, elapsedRealtime, true);
         appUsageHistory.currentBucket = bucket;
         appUsageHistory.bucketingReason = reason;
+        if (reason.startsWith(UsageStatsManager.REASON_PREDICTED)) {
+            appUsageHistory.lastPredictedTime = getElapsedTime(elapsedRealtime);
+        }
         if (DEBUG) {
             Slog.d(TAG, "Moved " + packageName + " to bucket=" + appUsageHistory.currentBucket
                     + ", reason=" + appUsageHistory.bucketingReason);
@@ -322,7 +341,7 @@
         return appUsageHistory != null ? appUsageHistory.bucketingReason : null;
     }
 
-    private long getElapsedTime(long elapsedRealtime) {
+    public long getElapsedTime(long elapsedRealtime) {
         return (elapsedRealtime - mElapsedSnapshot + mElapsedDuration);
     }
 
@@ -431,6 +450,12 @@
                                 Long.parseLong(parser.getAttributeValue(null, ATTR_ELAPSED_IDLE));
                         appUsageHistory.lastUsedScreenTime =
                                 Long.parseLong(parser.getAttributeValue(null, ATTR_SCREEN_IDLE));
+                        String lastPredictedTimeString = parser.getAttributeValue(null,
+                                ATTR_LAST_PREDICTED_TIME);
+                        if (lastPredictedTimeString != null) {
+                            appUsageHistory.lastPredictedTime =
+                                    Long.parseLong(lastPredictedTimeString);
+                        }
                         String currentBucketString = parser.getAttributeValue(null,
                                 ATTR_CURRENT_BUCKET);
                         appUsageHistory.currentBucket = currentBucketString == null
@@ -441,6 +466,7 @@
                         if (appUsageHistory.bucketingReason == null) {
                             appUsageHistory.bucketingReason = UsageStatsManager.REASON_DEFAULT;
                         }
+                        appUsageHistory.lastInformedBucket = -1;
                         userHistory.put(packageName, appUsageHistory);
                     }
                 }
@@ -477,6 +503,8 @@
                         Long.toString(history.lastUsedElapsedTime));
                 xml.attribute(null, ATTR_SCREEN_IDLE,
                         Long.toString(history.lastUsedScreenTime));
+                xml.attribute(null, ATTR_LAST_PREDICTED_TIME,
+                        Long.toString(history.lastPredictedTime));
                 xml.attribute(null, ATTR_CURRENT_BUCKET,
                         Integer.toString(history.currentBucket));
                 xml.attribute(null, ATTR_BUCKETING_REASON, history.bucketingReason);
@@ -512,6 +540,8 @@
             TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.lastUsedElapsedTime, idpw);
             idpw.print(" lastUsedScreenOn=");
             TimeUtils.formatDuration(screenOnTime - appUsageHistory.lastUsedScreenTime, idpw);
+            idpw.print(" lastPredictedTime=");
+            TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.lastPredictedTime, idpw);
             idpw.print(" idle=" + (isIdle(packageName, userId, elapsedRealtime) ? "y" : "n"));
             idpw.print(" bucket=" + appUsageHistory.currentBucket
                     + " reason=" + appUsageHistory.bucketingReason);
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 3d20a64..d8086bb 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -18,6 +18,7 @@
 
 import static android.app.usage.UsageStatsManager.REASON_DEFAULT;
 import static android.app.usage.UsageStatsManager.REASON_FORCED;
+import static android.app.usage.UsageStatsManager.REASON_PREDICTED;
 import static android.app.usage.UsageStatsManager.REASON_TIMEOUT;
 import static android.app.usage.UsageStatsManager.REASON_USAGE;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
@@ -118,6 +119,9 @@
             STANDBY_BUCKET_RARE
     };
 
+    // Expiration time for predicted bucket
+    private static final long PREDICTION_TIMEOUT = 12 * ONE_HOUR;
+
     // To name the lock for stack traces
     static class Lock {}
 
@@ -388,25 +392,27 @@
                             STANDBY_BUCKET_EXEMPTED);
                 } else {
                     synchronized (mAppIdleLock) {
-                        String bucketingReason = mAppIdleHistory.getAppStandbyReason(packageName,
+                        AppIdleHistory.AppUsageHistory app =
+                                mAppIdleHistory.getAppUsageHistory(packageName,
                                 userId, elapsedRealtime);
                         // If the bucket was forced by the developer, leave it alone
-                        if (REASON_FORCED.equals(bucketingReason)) {
+                        if (REASON_FORCED.equals(app.bucketingReason)) {
                             continue;
                         }
+                        boolean predictionLate = false;
                         // If the bucket was moved up due to usage, let the timeouts apply.
-                        if (REASON_DEFAULT.equals(bucketingReason)
-                                || REASON_USAGE.equals(bucketingReason)
-                                || REASON_TIMEOUT.equals(bucketingReason)) {
-                            int oldBucket = mAppIdleHistory.getAppStandbyBucket(packageName, userId,
-                                    elapsedRealtime);
+                        if (REASON_DEFAULT.equals(app.bucketingReason)
+                                || REASON_USAGE.equals(app.bucketingReason)
+                                || REASON_TIMEOUT.equals(app.bucketingReason)
+                                || (predictionLate = predictionTimedOut(app, elapsedRealtime))) {
+                            int oldBucket = app.currentBucket;
                             int newBucket = getBucketForLocked(packageName, userId,
                                     elapsedRealtime);
                             if (DEBUG) {
                                 Slog.d(TAG, "     Old bucket=" + oldBucket
                                         + ", newBucket=" + newBucket);
                             }
-                            if (oldBucket < newBucket) {
+                            if (oldBucket < newBucket || predictionLate) {
                                 mAppIdleHistory.setAppStandbyBucket(packageName, userId,
                                         elapsedRealtime, newBucket, REASON_TIMEOUT);
                                 maybeInformListeners(packageName, userId, elapsedRealtime,
@@ -424,6 +430,14 @@
         return true;
     }
 
+    private boolean predictionTimedOut(AppIdleHistory.AppUsageHistory app, long elapsedRealtime) {
+        return app.bucketingReason != null
+                && app.bucketingReason.startsWith(REASON_PREDICTED)
+                && app.lastPredictedTime > 0
+                && mAppIdleHistory.getElapsedTime(elapsedRealtime)
+                    - app.lastPredictedTime > PREDICTION_TIMEOUT;
+    }
+
     private void maybeInformListeners(String packageName, int userId,
             long elapsedRealtime, int bucket) {
         synchronized (mAppIdleLock) {
diff --git a/services/usb/Android.bp b/services/usb/Android.bp
new file mode 100644
index 0000000..0cd9ac3
--- /dev/null
+++ b/services/usb/Android.bp
@@ -0,0 +1,14 @@
+java_library_static {
+    name: "services.usb",
+    srcs: ["java/**/*.java"],
+
+    libs: [
+        "services.core",
+        "android.hidl.manager-V1.0-java",
+    ],
+
+    static_libs: [
+        "android.hardware.usb-V1.0-java",
+        "android.hardware.usb-V1.1-java",
+    ],
+}
diff --git a/services/usb/Android.mk b/services/usb/Android.mk
deleted file mode 100644
index 55bfccf..0000000
--- a/services/usb/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.usb
-
-LOCAL_SRC_FILES += \
-      $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core \
-android.hidl.manager-V1.0-java
-
-LOCAL_STATIC_JAVA_LIBRARIES := android.hardware.usb-V1.0-java \
-android.hardware.usb-V1.1-java
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/voiceinteraction/Android.bp b/services/voiceinteraction/Android.bp
new file mode 100644
index 0000000..390406f
--- /dev/null
+++ b/services/voiceinteraction/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+    name: "services.voiceinteraction",
+    srcs: ["java/**/*.java"],
+    libs: ["services.core"],
+}
diff --git a/services/voiceinteraction/Android.mk b/services/voiceinteraction/Android.mk
deleted file mode 100644
index c9e5dd0..0000000
--- a/services/voiceinteraction/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.voiceinteraction
-
-LOCAL_SRC_FILES += \
-      $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index a5d67c6..dd2a6df 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -83,7 +83,10 @@
     public static final int MAX_USER_DATA_SEPTETS_WITH_HEADER = 153;
 
     /** @hide */
-    @StringDef({FORMAT_3GPP, FORMAT_3GPP2})
+    @StringDef(prefix = { "FORMAT_" }, value = {
+            FORMAT_3GPP,
+            FORMAT_3GPP2
+    })
     @Retention(RetentionPolicy.SOURCE)
     public @interface Format {}
 
diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java
index 8cdad3f..da51c86 100644
--- a/telephony/java/android/telephony/data/DataCallResponse.java
+++ b/telephony/java/android/telephony/data/DataCallResponse.java
@@ -116,7 +116,6 @@
      */
     public int getSuggestedRetryTime() { return mSuggestedRetryTime; }
 
-
     /**
      * @return The unique id of the data connection.
      */
@@ -183,16 +182,57 @@
            .append(" active=").append(mActive)
            .append(" type=").append(mType)
            .append(" ifname=").append(mIfname)
-           .append(" mtu=").append(mMtu)
            .append(" addresses=").append(mAddresses)
            .append(" dnses=").append(mDnses)
            .append(" gateways=").append(mGateways)
            .append(" pcscf=").append(mPcscfs)
+           .append(" mtu=").append(mMtu)
            .append("}");
         return sb.toString();
     }
 
     @Override
+    public boolean equals (Object o) {
+        if (this == o) return true;
+
+        if (o == null || !(o instanceof DataCallResponse)) {
+            return false;
+        }
+
+        DataCallResponse other = (DataCallResponse) o;
+        return this.mStatus == other.mStatus
+                && this.mSuggestedRetryTime == other.mSuggestedRetryTime
+                && this.mCid == other.mCid
+                && this.mActive == other.mActive
+                && this.mType.equals(other.mType)
+                && this.mIfname.equals(other.mIfname)
+                && mAddresses.size() == other.mAddresses.size()
+                && mAddresses.containsAll(other.mAddresses)
+                && mDnses.size() == other.mDnses.size()
+                && mDnses.containsAll(other.mDnses)
+                && mGateways.size() == other.mGateways.size()
+                && mGateways.containsAll(other.mGateways)
+                && mPcscfs.size() == other.mPcscfs.size()
+                && mPcscfs.containsAll(other.mPcscfs)
+                && mMtu == other.mMtu;
+    }
+
+    @Override
+    public int hashCode() {
+        return mStatus * 31
+                + mSuggestedRetryTime * 37
+                + mCid * 41
+                + mActive * 43
+                + mType.hashCode() * 47
+                + mIfname.hashCode() * 53
+                + mAddresses.hashCode() * 59
+                + mDnses.hashCode() * 61
+                + mGateways.hashCode() * 67
+                + mPcscfs.hashCode() * 71
+                + mMtu * 73;
+    }
+
+    @Override
     public int describeContents() {
         return 0;
     }
diff --git a/telephony/java/android/telephony/data/InterfaceAddress.java b/telephony/java/android/telephony/data/InterfaceAddress.java
index 947d0ff..00d212a 100644
--- a/telephony/java/android/telephony/data/InterfaceAddress.java
+++ b/telephony/java/android/telephony/data/InterfaceAddress.java
@@ -78,6 +78,23 @@
      */
     public int getNetworkPrefixLength() { return mPrefixLength; }
 
+    @Override
+    public boolean equals (Object o) {
+        if (this == o) return true;
+
+        if (o == null || !(o instanceof InterfaceAddress)) {
+            return false;
+        }
+
+        InterfaceAddress other = (InterfaceAddress) o;
+        return this.mInetAddress.equals(other.mInetAddress)
+                && this.mPrefixLength == other.mPrefixLength;
+    }
+
+    @Override
+    public int hashCode() {
+        return mInetAddress.hashCode() * 31 + mPrefixLength * 37;
+    }
 
     @Override
     public int describeContents() {
diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
index 5a4db99..1670e6b 100644
--- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -16,15 +16,23 @@
 
 package android.telephony.ims.stub;
 
+import android.content.Context;
+import android.content.Intent;
 import android.os.RemoteException;
+import android.util.Log;
 
 import com.android.ims.ImsConfig;
 import com.android.ims.ImsConfigListener;
 import com.android.ims.internal.IImsConfig;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
+
 
 /**
- * Base implementation of ImsConfig, which implements stub versions of the methods
- * in the IImsConfig AIDL. Override the methods that your implementation of ImsConfig supports.
+ * Base implementation of ImsConfig.
+ * Override the methods that your implementation of ImsConfig supports.
  *
  * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
  * will break other implementations of ImsConfig maintained by other ImsServices.
@@ -34,10 +42,25 @@
  * 1) Items provisioned by the operator.
  * 2) Items configured by user. Mainly service feature class.
  *
+ * The inner class {@link ImsConfigStub} implements methods of IImsConfig AIDL interface.
+ * The IImsConfig AIDL interface is called by ImsConfig, which may exist in many other processes.
+ * ImsConfigImpl access to the configuration parameters may be arbitrarily slow, especially in
+ * during initialization, or times when a lot of configuration parameters are being set/get
+ * (such as during boot up or SIM card change). By providing a cache in ImsConfigStub, we can speed
+ * up access to these configuration parameters, so a query to the ImsConfigImpl does not have to be
+ * performed every time.
  * @hide
  */
 
-public class ImsConfigImplBase extends IImsConfig.Stub {
+public class ImsConfigImplBase {
+
+    static final private String TAG = "ImsConfigImplBase";
+
+    ImsConfigStub mImsConfigStub;
+
+    public ImsConfigImplBase(Context context) {
+        mImsConfigStub = new ImsConfigStub(this, context);
+    }
 
     /**
      * Gets the value for ims service/capabilities parameters from the provisioned
@@ -46,7 +69,6 @@
      * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
      * @return value in Integer format.
      */
-    @Override
     public int getProvisionedValue(int item) throws RemoteException {
         return -1;
     }
@@ -58,7 +80,6 @@
      * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
      * @return value in String format.
      */
-    @Override
     public String getProvisionedStringValue(int item) throws RemoteException {
         return null;
     }
@@ -72,7 +93,6 @@
      * @param value in Integer format.
      * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
      */
-    @Override
     public int setProvisionedValue(int item, int value) throws RemoteException {
         return ImsConfig.OperationStatusConstants.FAILED;
     }
@@ -86,7 +106,6 @@
      * @param value in String format.
      * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
      */
-    @Override
     public int setProvisionedStringValue(int item, String value) throws RemoteException {
         return ImsConfig.OperationStatusConstants.FAILED;
     }
@@ -100,7 +119,6 @@
      * @param network as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX.
      * @param listener feature value returned asynchronously through listener.
      */
-    @Override
     public void getFeatureValue(int feature, int network, ImsConfigListener listener)
             throws RemoteException {
     }
@@ -115,7 +133,6 @@
      * @param value as defined in com.android.ims.ImsConfig#FeatureValueConstants.
      * @param listener, provided if caller needs to be notified for set result.
      */
-    @Override
     public void setFeatureValue(int feature, int network, int value, ImsConfigListener listener)
             throws RemoteException {
     }
@@ -124,7 +141,6 @@
      * Gets the value for IMS VoLTE provisioned.
      * This should be the same as the operator provisioned value if applies.
      */
-    @Override
     public boolean getVolteProvisioned() throws RemoteException {
         return false;
     }
@@ -134,7 +150,6 @@
      *
      * @param listener Video quality value returned asynchronously through listener.
      */
-    @Override
     public void getVideoQuality(ImsConfigListener listener) throws RemoteException {
     }
 
@@ -144,7 +159,233 @@
      * @param quality, defines the value of video quality.
      * @param listener, provided if caller needs to be notified for set result.
      */
-    @Override
     public void setVideoQuality(int quality, ImsConfigListener listener) throws RemoteException {
     }
+
+    public IImsConfig getIImsConfig() { return mImsConfigStub; }
+
+    /**
+     * Updates provisioning value and notifies the framework of the change.
+     * Doesn't call #setProvisionedValue and assumes the result succeeded.
+     * This should only be used by modem when they implicitly changed provisioned values.
+     *
+     * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+     * @param value in Integer format.
+     */
+    public final void notifyProvisionedValueChanged(int item, int value) {
+        mImsConfigStub.updateCachedValue(item, value, true);
+    }
+
+    /**
+     * Updates provisioning value and notifies the framework of the change.
+     * Doesn't call #setProvisionedValue and assumes the result succeeded.
+     * This should only be used by modem when they implicitly changed provisioned values.
+     *
+     * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+     * @param value in String format.
+     */
+    public final void notifyProvisionedValueChanged(int item, String value) {
+        mImsConfigStub.updateCachedValue(item, value, true);
+    }
+
+    /**
+     * Implements the IImsConfig AIDL interface, which is called by potentially many processes
+     * in order to get/set configuration parameters.
+     *
+     * It holds an object of ImsConfigImplBase class which is usually extended by ImsConfigImpl
+     * with actual implementations from vendors. This class caches provisioned values from
+     * ImsConfigImpl layer because queries through ImsConfigImpl can be slow. When query goes in,
+     * it first checks cache layer. If missed, it will call the vendor implementation of
+     * ImsConfigImplBase API.
+     * and cache the return value if the set succeeds.
+     *
+     * Provides APIs to get/set the IMS service feature/capability/parameters.
+     * The config items include:
+     * 1) Items provisioned by the operator.
+     * 2) Items configured by user. Mainly service feature class.
+     *
+     * @hide
+     */
+    @VisibleForTesting
+    static public class ImsConfigStub extends IImsConfig.Stub {
+        Context mContext;
+        WeakReference<ImsConfigImplBase> mImsConfigImplBaseWeakReference;
+        private HashMap<Integer, Integer> mProvisionedIntValue = new HashMap<>();
+        private HashMap<Integer, String> mProvisionedStringValue = new HashMap<>();
+
+        @VisibleForTesting
+        public ImsConfigStub(ImsConfigImplBase imsConfigImplBase, Context context) {
+            mContext = context;
+            mImsConfigImplBaseWeakReference =
+                    new WeakReference<ImsConfigImplBase>(imsConfigImplBase);
+        }
+
+        /**
+         * Gets the value for ims service/capabilities parameters. It first checks its local cache,
+         * if missed, it will call ImsConfigImplBase.getProvisionedValue.
+         * Synchronous blocking call.
+         *
+         * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+         * @return value in Integer format.
+         */
+        @Override
+        public synchronized int getProvisionedValue(int item) throws RemoteException {
+            if (mProvisionedIntValue.containsKey(item)) {
+                return mProvisionedIntValue.get(item);
+            } else {
+                int retVal = getImsConfigImpl().getProvisionedValue(item);
+                if (retVal != ImsConfig.OperationStatusConstants.UNKNOWN) {
+                    updateCachedValue(item, retVal, false);
+                }
+                return retVal;
+            }
+        }
+
+        /**
+         * Gets the value for ims service/capabilities parameters. It first checks its local cache,
+         * if missed, it will call #ImsConfigImplBase.getProvisionedValue.
+         * Synchronous blocking call.
+         *
+         * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+         * @return value in String format.
+         */
+        @Override
+        public synchronized String getProvisionedStringValue(int item) throws RemoteException {
+            if (mProvisionedIntValue.containsKey(item)) {
+                return mProvisionedStringValue.get(item);
+            } else {
+                String retVal = getImsConfigImpl().getProvisionedStringValue(item);
+                if (retVal != null) {
+                    updateCachedValue(item, retVal, false);
+                }
+                return retVal;
+            }
+        }
+
+        /**
+         * Sets the value for IMS service/capabilities parameters by the operator device
+         * management entity. It sets the config item value in the provisioned storage
+         * from which the master value is derived, and write it into local cache.
+         * Synchronous blocking call.
+         *
+         * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+         * @param value in Integer format.
+         * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
+         */
+        @Override
+        public synchronized int setProvisionedValue(int item, int value) throws RemoteException {
+            mProvisionedIntValue.remove(item);
+            int retVal = getImsConfigImpl().setProvisionedValue(item, value);
+            if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) {
+                updateCachedValue(item, retVal, true);
+            } else {
+                Log.d(TAG, "Set provision value of " + item +
+                        " to " + value + " failed with error code " + retVal);
+            }
+
+            return retVal;
+        }
+
+        /**
+         * Sets the value for IMS service/capabilities parameters by the operator device
+         * management entity. It sets the config item value in the provisioned storage
+         * from which the master value is derived, and write it into local cache.
+         * Synchronous blocking call.
+         *
+         * @param item as defined in com.android.ims.ImsConfig#ConfigConstants.
+         * @param value in String format.
+         * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
+         */
+        @Override
+        public synchronized int setProvisionedStringValue(int item, String value)
+                throws RemoteException {
+            mProvisionedStringValue.remove(item);
+            int retVal = getImsConfigImpl().setProvisionedStringValue(item, value);
+            if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) {
+                updateCachedValue(item, retVal, true);
+            }
+
+            return retVal;
+        }
+
+        /**
+         * Wrapper function to call ImsConfigImplBase.getFeatureValue.
+         */
+        @Override
+        public void getFeatureValue(int feature, int network, ImsConfigListener listener)
+                throws RemoteException {
+            getImsConfigImpl().getFeatureValue(feature, network, listener);
+        }
+
+        /**
+         * Wrapper function to call ImsConfigImplBase.setFeatureValue.
+         */
+        @Override
+        public void setFeatureValue(int feature, int network, int value, ImsConfigListener listener)
+                throws RemoteException {
+            getImsConfigImpl().setFeatureValue(feature, network, value, listener);
+        }
+
+        /**
+         * Wrapper function to call ImsConfigImplBase.getVolteProvisioned.
+         */
+        @Override
+        public boolean getVolteProvisioned() throws RemoteException {
+            return getImsConfigImpl().getVolteProvisioned();
+        }
+
+        /**
+         * Wrapper function to call ImsConfigImplBase.getVideoQuality.
+         */
+        @Override
+        public void getVideoQuality(ImsConfigListener listener) throws RemoteException {
+            getImsConfigImpl().getVideoQuality(listener);
+        }
+
+        /**
+         * Wrapper function to call ImsConfigImplBase.setVideoQuality.
+         */
+        @Override
+        public void setVideoQuality(int quality, ImsConfigListener listener)
+                throws RemoteException {
+            getImsConfigImpl().setVideoQuality(quality, listener);
+        }
+
+        private ImsConfigImplBase getImsConfigImpl() throws RemoteException {
+            ImsConfigImplBase ref = mImsConfigImplBaseWeakReference.get();
+            if (ref == null) {
+                throw new RemoteException("Fail to get ImsConfigImpl");
+            } else {
+                return ref;
+            }
+        }
+
+        private void sendImsConfigChangedIntent(int item, int value) {
+            sendImsConfigChangedIntent(item, Integer.toString(value));
+        }
+
+        private void sendImsConfigChangedIntent(int item, String value) {
+            Intent configChangedIntent = new Intent(ImsConfig.ACTION_IMS_CONFIG_CHANGED);
+            configChangedIntent.putExtra(ImsConfig.EXTRA_CHANGED_ITEM, item);
+            configChangedIntent.putExtra(ImsConfig.EXTRA_NEW_VALUE, value);
+            if (mContext != null) {
+                mContext.sendBroadcast(configChangedIntent);
+            }
+        }
+
+        protected synchronized void updateCachedValue(int item, int value, boolean notifyChange) {
+            mProvisionedIntValue.put(item, value);
+            if (notifyChange) {
+                sendImsConfigChangedIntent(item, value);
+            }
+        }
+
+        protected synchronized void updateCachedValue(
+                int item, String value, boolean notifyChange) {
+            mProvisionedStringValue.put(item, value);
+            if (notifyChange) {
+                sendImsConfigChangedIntent(item, value);
+            }
+        }
+    }
 }
diff --git a/telephony/java/com/android/ims/ImsConfig.java b/telephony/java/com/android/ims/ImsConfig.java
index cf4c47b..cd0c4b1 100644
--- a/telephony/java/com/android/ims/ImsConfig.java
+++ b/telephony/java/com/android/ims/ImsConfig.java
@@ -619,6 +619,7 @@
             Rlog.d(TAG, "setProvisionedValue(): item = " + item +
                     " value = " + value + " ret = " + ret);
         }
+
         return ret;
     }
 
@@ -647,6 +648,7 @@
             Rlog.d(TAG, "setProvisionedStringValue(): item = " + item +
                     ", value =" + value);
         }
+
         return ret;
     }
 
diff --git a/test-base/Android.bp b/test-base/Android.bp
new file mode 100644
index 0000000..a3fd345
--- /dev/null
+++ b/test-base/Android.bp
@@ -0,0 +1,88 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Build the android.test.base library
+// ===================================
+// This contains the junit.framework and android.test classes that were in
+// Android API level 25 excluding those from android.test.runner.
+// Also contains the com.android.internal.util.Predicate[s] classes.
+java_library {
+    name: "android.test.base",
+
+    srcs: ["src/**/*.java"],
+
+    no_framework_libs: true,
+    libs: [
+        "framework",
+    ],
+
+}
+
+// Build the legacy-test library
+// =============================
+// This contains the junit.framework and android.test classes that were in
+// Android API level 25 excluding those from android.test.runner.
+// Also contains the com.android.internal.util.Predicate[s] classes.
+java_library {
+    name: "legacy-test",
+    static_libs: ["android.test.base"],
+
+    no_framework_libs: true,
+    libs: [
+        "framework",
+    ],
+}
+
+// Build the repackaged.android.test.base library
+// ==============================================
+// This contains repackaged versions of the classes from legacy-test.
+java_library_static {
+    name: "repackaged.android.test.base",
+
+    static_libs: ["android.test.base"],
+
+    no_framework_libs: true,
+    libs: [
+        "framework",
+    ],
+
+    jarjar_rules: "jarjar-rules.txt",
+}
+
+// Build the legacy-android-test library
+// =====================================
+// This contains the android.test classes that were in Android API level 25,
+// including those from android.test.runner.
+// Also contains the com.android.internal.util.Predicate[s] classes.
+java_library_static {
+    name: "legacy-android-test",
+
+    srcs: [
+        "src/android/**/*.java",
+        "src/com/**/*.java",
+    ],
+
+    static_libs: [
+        "android.test.runner",
+        "android.test.mock",
+    ],
+
+    no_framework_libs: true,
+    libs: [
+        "framework",
+        "junit",
+    ],
+}
diff --git a/test-base/Android.mk b/test-base/Android.mk
index 03bdcf23..5e5d040 100644
--- a/test-base/Android.mk
+++ b/test-base/Android.mk
@@ -16,50 +16,6 @@
 
 LOCAL_PATH:= $(call my-dir)
 
-# Build the android.test.base library
-# ===================================
-# This contains the junit.framework and android.test classes that were in
-# Android API level 25 excluding those from android.test.runner.
-# Also contains the com.android.internal.util.Predicate[s] classes.
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_MODULE := android.test.base
-LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
-
-include $(BUILD_JAVA_LIBRARY)
-
-# Build the legacy-test library
-# =============================
-# This contains the junit.framework and android.test classes that were in
-# Android API level 25 excluding those from android.test.runner.
-# Also contains the com.android.internal.util.Predicate[s] classes.
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_MODULE := legacy-test
-LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
-
-include $(BUILD_JAVA_LIBRARY)
-
-# Build the repackaged.android.test.base library
-# ==============================================
-# This contains repackaged versions of the classes from legacy-test.
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_MODULE := repackaged.android.test.base
-LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
-LOCAL_JARJAR_RULES := $(LOCAL_PATH)/jarjar-rules.txt
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
 # For unbundled build we'll use the prebuilt jar from prebuilts/sdk.
 ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)))
 
@@ -156,24 +112,6 @@
 
 endif  # not TARGET_BUILD_APPS not TARGET_BUILD_PDK=true
 
-# Build the legacy-android-test library
-# =====================================
-# This contains the android.test classes that were in Android API level 25,
-# including those from android.test.runner.
-# Also contains the com.android.internal.util.Predicate[s] classes.
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-    $(call all-java-files-under, src/android) \
-    $(call all-java-files-under, ../test-runner/src/android) \
-    $(call all-java-files-under, ../test-mock/src/android) \
-    $(call all-java-files-under, src/com)
-LOCAL_MODULE := legacy-android-test
-LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core-oj core-libart framework junit
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
 # Build the legacy.test.stubs library
 # ===================================
 include $(CLEAR_VARS)
diff --git a/test-mock/Android.bp b/test-mock/Android.bp
new file mode 100644
index 0000000..8eddec4
--- /dev/null
+++ b/test-mock/Android.bp
@@ -0,0 +1,39 @@
+//
+// 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.
+//
+
+// Build the android.test.mock library
+// ===================================
+java_library {
+    name: "android.test.mock",
+
+    srcs: ["src/**/*.java"],
+
+    no_framework_libs: true,
+    libs: [
+        "framework",
+        "legacy-test",
+    ],
+}
+
+// Build the repackaged.android.test.mock library
+// ==============================================
+java_library_static {
+    name: "repackaged.android.test.mock",
+
+    static_libs: ["android.test.mock"],
+
+    jarjar_rules: "jarjar-rules.txt",
+}
diff --git a/test-mock/Android.mk b/test-mock/Android.mk
index 2c07955..a761a07 100644
--- a/test-mock/Android.mk
+++ b/test-mock/Android.mk
@@ -18,32 +18,6 @@
 
 android_test_mock_source_files := $(call all-java-files-under, src/android/test/mock)
 
-# Build the repackaged.android.test.mock library
-# ==============================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
-
-LOCAL_JARJAR_RULES := $(LOCAL_PATH)/../test-base/jarjar-rules.txt
-
-LOCAL_MODULE:= repackaged.android.test.mock
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-# Build the android.test.mock library
-# ===================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
-
-LOCAL_MODULE:= android.test.mock
-
-include $(BUILD_JAVA_LIBRARY)
-
 # For unbundled build we'll use the prebuilt jar from prebuilts/sdk.
 ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)))
 
diff --git a/test-mock/jarjar-rules.txt b/test-mock/jarjar-rules.txt
new file mode 120000
index 0000000..f6f7913
--- /dev/null
+++ b/test-mock/jarjar-rules.txt
@@ -0,0 +1 @@
+../test-base/jarjar-rules.txt
\ No newline at end of file
diff --git a/test-runner/Android.bp b/test-runner/Android.bp
new file mode 100644
index 0000000..104ae82
--- /dev/null
+++ b/test-runner/Android.bp
@@ -0,0 +1,40 @@
+//
+// 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.
+//
+
+// Build the android.test.runner library
+// =====================================
+java_library {
+    name: "android.test.runner",
+
+    srcs: ["src/**/*.java"],
+
+    no_framework_libs: true,
+    libs: [
+        "framework",
+        "legacy-test",
+        "android.test.mock",
+    ],
+}
+
+// Build the repackaged.android.test.runner library
+// ================================================
+java_library_static {
+    name: "repackaged.android.test.runner",
+
+    static_libs: ["android.test.runner"],
+
+    jarjar_rules: "jarjar-rules.txt",
+}
diff --git a/test-runner/Android.mk b/test-runner/Android.mk
index 87fe831..67f1354 100644
--- a/test-runner/Android.mk
+++ b/test-runner/Android.mk
@@ -16,42 +16,6 @@
 
 LOCAL_PATH:= $(call my-dir)
 
-# Build the android.test.runner library
-# =====================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := \
-    core-oj \
-    core-libart \
-    framework \
-    android.test.base \
-    android.test.mock \
-
-LOCAL_MODULE:= android.test.runner
-
-include $(BUILD_JAVA_LIBRARY)
-
-# Build the repackaged.android.test.runner library
-# ================================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := \
-    core-oj \
-    core-libart \
-    framework \
-    android.test.base \
-    android.test.mock \
-
-LOCAL_JARJAR_RULES := $(LOCAL_PATH)/../test-base/jarjar-rules.txt
-
-LOCAL_MODULE:= repackaged.android.test.runner
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
 # For unbundled build we'll use the prebuilt jar from prebuilts/sdk.
 ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)))
 
diff --git a/test-runner/jarjar-rules.txt b/test-runner/jarjar-rules.txt
new file mode 120000
index 0000000..f6f7913
--- /dev/null
+++ b/test-runner/jarjar-rules.txt
@@ -0,0 +1 @@
+../test-base/jarjar-rules.txt
\ No newline at end of file
diff --git a/tests/BrowserPowerTest/Android.mk b/tests/BrowserPowerTest/Android.mk
index 59bc729..5765575 100644
--- a/tests/BrowserPowerTest/Android.mk
+++ b/tests/BrowserPowerTest/Android.mk
@@ -18,8 +18,8 @@
 # We only want this apk build for tests.
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 
 # Include all test java files.
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/CantSaveState1/Android.mk b/tests/CantSaveState1/Android.mk
deleted file mode 100644
index 6e9db6e..0000000
--- a/tests/CantSaveState1/Android.mk
+++ /dev/null
@@ -1,10 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := CantSaveState1
-
-include $(BUILD_PACKAGE)
diff --git a/tests/CantSaveState1/AndroidManifest.xml b/tests/CantSaveState1/AndroidManifest.xml
deleted file mode 100644
index fadcaeb..0000000
--- a/tests/CantSaveState1/AndroidManifest.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT 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.test.cantsavestate1">
-    <application android:label="Can't Save 1" android:cantSaveState="true">
-        <activity android:name="CantSave1Activity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-    </application>
-</manifest>
diff --git a/tests/CantSaveState1/res/layout/cant_save_1_activity.xml b/tests/CantSaveState1/res/layout/cant_save_1_activity.xml
deleted file mode 100644
index c5bf657..0000000
--- a/tests/CantSaveState1/res/layout/cant_save_1_activity.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT 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"
-    android:orientation="vertical"
->
-
-    <TextView
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="25dp"
-        android:textAppearance="?android:attr/textAppearanceLarge"
-        android:text="This app #1 can't save its state"
-    />
-
-</LinearLayout>
diff --git a/tests/CantSaveState1/src/com/android/test/cantsavestate2/CantSave1Activity.java b/tests/CantSaveState1/src/com/android/test/cantsavestate2/CantSave1Activity.java
deleted file mode 100644
index 8879ed0..0000000
--- a/tests/CantSaveState1/src/com/android/test/cantsavestate2/CantSave1Activity.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS 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.cantsavestate1;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class CantSave1Activity extends Activity {
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.cant_save_1_activity);
-    }
-}
diff --git a/tests/CantSaveState2/Android.mk b/tests/CantSaveState2/Android.mk
deleted file mode 100644
index add9214..0000000
--- a/tests/CantSaveState2/Android.mk
+++ /dev/null
@@ -1,10 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := CantSaveState2
-
-include $(BUILD_PACKAGE)
diff --git a/tests/CantSaveState2/AndroidManifest.xml b/tests/CantSaveState2/AndroidManifest.xml
deleted file mode 100644
index 8f4f01d..0000000
--- a/tests/CantSaveState2/AndroidManifest.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT 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.test.cantsavestate2">
-    <application android:label="Can't Save 2" android:cantSaveState="true">
-        <activity android:name="CantSave2Activity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-    </application>
-</manifest>
diff --git a/tests/CantSaveState2/res/layout/cant_save_2_activity.xml b/tests/CantSaveState2/res/layout/cant_save_2_activity.xml
deleted file mode 100644
index c5b8e3d..0000000
--- a/tests/CantSaveState2/res/layout/cant_save_2_activity.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT 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"
-    android:orientation="vertical"
->
-
-    <TextView
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="25dp"
-        android:textAppearance="?android:attr/textAppearanceLarge"
-        android:text="This app #2 can't save its state"
-    />
-
-</LinearLayout>
diff --git a/tests/CantSaveState2/src/com/android/test/cantsavestate2/CantSave2Activity.java b/tests/CantSaveState2/src/com/android/test/cantsavestate2/CantSave2Activity.java
deleted file mode 100644
index 3ce63c7..0000000
--- a/tests/CantSaveState2/src/com/android/test/cantsavestate2/CantSave2Activity.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS 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.cantsavestate2;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class CantSave2Activity extends Activity {
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.cant_save_2_activity);
-    }
-}
diff --git a/tests/CanvasCompare/Android.mk b/tests/CanvasCompare/Android.mk
index 90de503..b071ec4 100644
--- a/tests/CanvasCompare/Android.mk
+++ b/tests/CanvasCompare/Android.mk
@@ -23,7 +23,7 @@
 
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 
 include $(BUILD_PACKAGE)
diff --git a/tests/CoreTests/android/Android.mk b/tests/CoreTests/android/Android.mk
index c9f1161..56d7918 100644
--- a/tests/CoreTests/android/Android.mk
+++ b/tests/CoreTests/android/Android.mk
@@ -6,8 +6,14 @@
 LOCAL_SRC_FILES := \
 	$(call all-subdir-java-files)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner bouncycastle conscrypt org.apache.http.legacy
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := \
+    android.test.runner \
+    bouncycastle \
+    conscrypt \
+    org.apache.http.legacy \
+    android.test.base \
+
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 
 LOCAL_PACKAGE_NAME := CoreTests
 
diff --git a/tests/DataIdleTest/Android.mk b/tests/DataIdleTest/Android.mk
index 4e15729..85f7edf 100644
--- a/tests/DataIdleTest/Android.mk
+++ b/tests/DataIdleTest/Android.mk
@@ -20,8 +20,8 @@
 LOCAL_MODULE_TAGS := tests
 
 LOCAL_PACKAGE_NAME := DataIdleTest
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 # We need to sign it to get access to the network usage history.
diff --git a/tests/FrameworkPerf/Android.mk b/tests/FrameworkPerf/Android.mk
index d2ec753..1873cc1 100644
--- a/tests/FrameworkPerf/Android.mk
+++ b/tests/FrameworkPerf/Android.mk
@@ -7,8 +7,8 @@
 
 LOCAL_PACKAGE_NAME := FrameworkPerf
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 
 LOCAL_AAPT_FLAGS = -c 120dpi,240dpi,160dpi,161dpi,320dpi,nodpi
 
diff --git a/tests/HierarchyViewerTest/Android.mk b/tests/HierarchyViewerTest/Android.mk
index f8c8656..8550d70 100644
--- a/tests/HierarchyViewerTest/Android.mk
+++ b/tests/HierarchyViewerTest/Android.mk
@@ -7,7 +7,7 @@
 
 LOCAL_PACKAGE_NAME := HierarchyViewerTest
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 
 include $(BUILD_PACKAGE)
diff --git a/tests/ImfTest/tests/Android.mk b/tests/ImfTest/tests/Android.mk
index 6042471..a0df959 100644
--- a/tests/ImfTest/tests/Android.mk
+++ b/tests/ImfTest/tests/Android.mk
@@ -7,8 +7,8 @@
 # Include all test java files.
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 
 LOCAL_PACKAGE_NAME := ImfTestTests
 
diff --git a/tests/Internal/Android.mk b/tests/Internal/Android.mk
index fc001e9..73181ec 100644
--- a/tests/Internal/Android.mk
+++ b/tests/Internal/Android.mk
@@ -11,7 +11,6 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 LOCAL_STATIC_JAVA_LIBRARIES := junit \
-    legacy-android-test \
     android-support-test \
     mockito-target-minus-junit4
 
diff --git a/tests/MemoryUsage/Android.mk b/tests/MemoryUsage/Android.mk
index 578e628..e186e9f 100644
--- a/tests/MemoryUsage/Android.mk
+++ b/tests/MemoryUsage/Android.mk
@@ -9,8 +9,8 @@
 LOCAL_PACKAGE_NAME := MemoryUsage
 
 LOCAL_CERTIFICATE := platform
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 
 include $(BUILD_PACKAGE)
 
diff --git a/tests/NetworkSecurityConfigTest/Android.mk b/tests/NetworkSecurityConfigTest/Android.mk
index dd9ff11..6fb6025 100644
--- a/tests/NetworkSecurityConfigTest/Android.mk
+++ b/tests/NetworkSecurityConfigTest/Android.mk
@@ -5,8 +5,13 @@
 LOCAL_MODULE_TAGS := tests
 LOCAL_CERTIFICATE := platform
 
-LOCAL_JAVA_LIBRARIES := android.test.runner bouncycastle conscrypt
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := \
+    android.test.runner \
+    bouncycastle \
+    conscrypt \
+    android.test.base \
+
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 
 # Include all test java files.
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/SoundTriggerTests/Android.mk b/tests/SoundTriggerTests/Android.mk
index 359484e..030d5f4 100644
--- a/tests/SoundTriggerTests/Android.mk
+++ b/tests/SoundTriggerTests/Android.mk
@@ -27,8 +27,8 @@
   LOCAL_SRC_FILES := src/android/hardware/soundtrigger/SoundTriggerTest.java
 endif
 
-LOCAL_STATIC_JAVA_LIBRARIES := mockito-target legacy-android-test
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
 
 LOCAL_PACKAGE_NAME := SoundTriggerTests
 
diff --git a/tests/SurfaceComposition/Android.mk b/tests/SurfaceComposition/Android.mk
index d97c3f4..1962791 100644
--- a/tests/SurfaceComposition/Android.mk
+++ b/tests/SurfaceComposition/Android.mk
@@ -27,7 +27,9 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_STATIC_JAVA_LIBRARIES := legacy-android-test junit
+LOCAL_STATIC_JAVA_LIBRARIES := junit
+
+LOCAL_JAVA_LIBRARIES := android.test.runner.stubs
 
 LOCAL_PACKAGE_NAME := SurfaceComposition
 
diff --git a/tests/TtsTests/Android.mk b/tests/TtsTests/Android.mk
index 3c3cd77..2fa1950 100644
--- a/tests/TtsTests/Android.mk
+++ b/tests/TtsTests/Android.mk
@@ -20,8 +20,8 @@
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
-LOCAL_STATIC_JAVA_LIBRARIES := mockito-target legacy-android-test
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
 
 LOCAL_PACKAGE_NAME := TtsTests
 
diff --git a/tests/WindowAnimationJank/Android.mk b/tests/WindowAnimationJank/Android.mk
index f356afb..8aac8a1 100644
--- a/tests/WindowAnimationJank/Android.mk
+++ b/tests/WindowAnimationJank/Android.mk
@@ -27,7 +27,6 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
     ub-uiautomator \
     ub-janktesthelper \
-    legacy-android-test \
     junit
 
 LOCAL_SDK_VERSION := current
diff --git a/tests/net/java/android/net/ip/IpManagerTest.java b/tests/net/java/android/net/ip/IpManagerTest.java
index ebf121a..22d88fb 100644
--- a/tests/net/java/android/net/ip/IpManagerTest.java
+++ b/tests/net/java/android/net/ip/IpManagerTest.java
@@ -69,8 +69,6 @@
 
 /**
  * Tests for IpManager.
- *
- * TODO: Rename to IpClientTest.
  */
 @RunWith(AndroidJUnit4.class)
 @SmallTest
@@ -113,10 +111,6 @@
         verify(mNMService, times(1)).registerObserver(arg.capture());
         mObserver = arg.getValue();
         reset(mNMService);
-        final LinkProperties emptyLp = new LinkProperties();
-        emptyLp.setInterfaceName(ifname);
-        verify(mCb, timeout(100)).onLinkPropertiesChange(eq(emptyLp));
-        reset(mCb);
         return ipm;
     }
 
diff --git a/tests/permission/Android.mk b/tests/permission/Android.mk
index 54688c8..7f81d9a 100644
--- a/tests/permission/Android.mk
+++ b/tests/permission/Android.mk
@@ -7,8 +7,8 @@
 # Include all test java files.
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 LOCAL_PACKAGE_NAME := FrameworkPermissionTests
 
 include $(BUILD_PACKAGE)
diff --git a/tests/testables/tests/Android.mk b/tests/testables/tests/Android.mk
index 16fe535..6e20d797 100644
--- a/tests/testables/tests/Android.mk
+++ b/tests/testables/tests/Android.mk
@@ -28,10 +28,9 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
     android-support-test \
     mockito-target-minus-junit4 \
-    legacy-android-test \
 	testables
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base android.test.mock
 
 LOCAL_CERTIFICATE := platform
 
diff --git a/tools/aapt2/LoadedApk.cpp b/tools/aapt2/LoadedApk.cpp
index 33b5a8b..20a9f41 100644
--- a/tools/aapt2/LoadedApk.cpp
+++ b/tools/aapt2/LoadedApk.cpp
@@ -57,31 +57,30 @@
 
 std::unique_ptr<LoadedApk> LoadedApk::LoadProtoApkFromFileCollection(
     const Source& source, unique_ptr<io::IFileCollection> collection, IDiagnostics* diag) {
+  std::unique_ptr<ResourceTable> table;
+
   io::IFile* table_file = collection->FindFile(kProtoResourceTablePath);
-  if (table_file == nullptr) {
-    diag->Error(DiagMessage(source) << "failed to find " << kProtoResourceTablePath);
-    return {};
-  }
+  if (table_file != nullptr) {
+    pb::ResourceTable pb_table;
+    std::unique_ptr<io::InputStream> in = table_file->OpenInputStream();
+    if (in == nullptr) {
+      diag->Error(DiagMessage(source) << "failed to open " << kProtoResourceTablePath);
+      return {};
+    }
 
-  std::unique_ptr<io::InputStream> in = table_file->OpenInputStream();
-  if (in == nullptr) {
-    diag->Error(DiagMessage(source) << "failed to open " << kProtoResourceTablePath);
-    return {};
-  }
+    io::ZeroCopyInputAdaptor adaptor(in.get());
+    if (!pb_table.ParseFromZeroCopyStream(&adaptor)) {
+      diag->Error(DiagMessage(source) << "failed to read " << kProtoResourceTablePath);
+      return {};
+    }
 
-  pb::ResourceTable pb_table;
-  io::ZeroCopyInputAdaptor adaptor(in.get());
-  if (!pb_table.ParseFromZeroCopyStream(&adaptor)) {
-    diag->Error(DiagMessage(source) << "failed to read " << kProtoResourceTablePath);
-    return {};
-  }
-
-  std::string error;
-  std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();
-  if (!DeserializeTableFromPb(pb_table, collection.get(), table.get(), &error)) {
-    diag->Error(DiagMessage(source)
-                << "failed to deserialize " << kProtoResourceTablePath << ": " << error);
-    return {};
+    std::string error;
+    table = util::make_unique<ResourceTable>();
+    if (!DeserializeTableFromPb(pb_table, collection.get(), table.get(), &error)) {
+      diag->Error(DiagMessage(source)
+                  << "failed to deserialize " << kProtoResourceTablePath << ": " << error);
+      return {};
+    }
   }
 
   io::IFile* manifest_file = collection->FindFile(kAndroidManifestPath);
@@ -103,6 +102,7 @@
     return {};
   }
 
+  std::string error;
   std::unique_ptr<xml::XmlResource> manifest = DeserializeXmlResourceFromPb(pb_node, &error);
   if (manifest == nullptr) {
     diag->Error(DiagMessage(source)
@@ -115,24 +115,21 @@
 
 std::unique_ptr<LoadedApk> LoadedApk::LoadBinaryApkFromFileCollection(
     const Source& source, unique_ptr<io::IFileCollection> collection, IDiagnostics* diag) {
+  std::unique_ptr<ResourceTable> table;
+
   io::IFile* table_file = collection->FindFile(kApkResourceTablePath);
-  if (table_file == nullptr) {
-    diag->Error(DiagMessage(source) << "failed to find " << kApkResourceTablePath);
-
-    return {};
-  }
-
-  std::unique_ptr<io::IData> data = table_file->OpenAsData();
-  if (data == nullptr) {
-    diag->Error(DiagMessage(source) << "failed to open " << kApkResourceTablePath);
-    return {};
-  }
-
-  std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();
-  BinaryResourceParser parser(diag, table.get(), source, data->data(), data->size(),
-                              collection.get());
-  if (!parser.Parse()) {
-    return {};
+  if (table_file != nullptr) {
+    table = util::make_unique<ResourceTable>();
+    std::unique_ptr<io::IData> data = table_file->OpenAsData();
+    if (data == nullptr) {
+      diag->Error(DiagMessage(source) << "failed to open " << kApkResourceTablePath);
+      return {};
+    }
+    BinaryResourceParser parser(diag, table.get(), source, data->data(), data->size(),
+                                collection.get());
+    if (!parser.Parse()) {
+      return {};
+    }
   }
 
   io::IFile* manifest_file = collection->FindFile(kAndroidManifestPath);
diff --git a/tools/aapt2/cmd/Convert.cpp b/tools/aapt2/cmd/Convert.cpp
index 2bd2405..964dacf 100644
--- a/tools/aapt2/cmd/Convert.cpp
+++ b/tools/aapt2/cmd/Convert.cpp
@@ -64,37 +64,39 @@
     return false;
   }
 
-  // Resource table
-  if (!serializer->SerializeTable(apk->GetResourceTable(), writer)) {
-    context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
-                                     << "failed to serialize the resource table");
-    return false;
+  if (apk->GetResourceTable() != nullptr) {
+    // Resource table
+    if (!serializer->SerializeTable(apk->GetResourceTable(), writer)) {
+      context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
+                                       << "failed to serialize the resource table");
+      return false;
+    }
+
+    // Resources
+    for (const auto& package : apk->GetResourceTable()->packages) {
+      for (const auto& type : package->types) {
+        for (const auto& entry : type->entries) {
+          for (const auto& config_value : entry->values) {
+            const FileReference* file = ValueCast<FileReference>(config_value->value.get());
+            if (file != nullptr) {
+              if (file->file == nullptr) {
+                context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
+                                                 << "no file associated with " << *file);
+                return false;
+              }
+
+              if (!serializer->SerializeFile(file, writer)) {
+                context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
+                                                 << "failed to serialize file " << *file->path);
+                return false;
+              }
+            } // file
+          } // config_value
+        } // entry
+      } // type
+    } // package
   }
 
-  // Resources
-  for (const auto& package : apk->GetResourceTable()->packages) {
-    for (const auto& type : package->types) {
-      for (const auto& entry : type->entries) {
-        for (const auto& config_value : entry->values) {
-          const FileReference* file = ValueCast<FileReference>(config_value->value.get());
-          if (file != nullptr) {
-            if (file->file == nullptr) {
-              context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
-                                               << "no file associated with " << *file);
-              return false;
-            }
-
-            if (!serializer->SerializeFile(file, writer)) {
-              context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
-                                               << "failed to serialize file " << *file->path);
-              return false;
-            }
-          } // file
-        } // config_value
-      } // entry
-    } // type
-  } // package
-
   // Other files
   std::unique_ptr<io::IFileCollectionIterator> iterator = apk->GetFileCollection()->Iterator();
   while (iterator->HasNext()) {
diff --git a/tools/locked_region_code_injection/Android.bp b/tools/locked_region_code_injection/Android.bp
index 6dd6059..5f81a2e 100644
--- a/tools/locked_region_code_injection/Android.bp
+++ b/tools/locked_region_code_injection/Android.bp
@@ -1,4 +1,4 @@
-java_library_host {
+java_binary_host {
     name: "lockedregioncodeinjection",
     manifest: "manifest.txt",
     srcs: ["src/**/*.java"],
diff --git a/wifi/java/android/net/wifi/rtt/WifiRttManager.java b/wifi/java/android/net/wifi/rtt/WifiRttManager.java
index 735e872..b4c690f 100644
--- a/wifi/java/android/net/wifi/rtt/WifiRttManager.java
+++ b/wifi/java/android/net/wifi/rtt/WifiRttManager.java
@@ -41,7 +41,7 @@
  *
  * @hide RTT_API
  */
-@SystemService(Context.WIFI_RTT2_SERVICE)
+@SystemService(Context.WIFI_RTT_RANGING_SERVICE)
 public class WifiRttManager {
     private static final String TAG = "WifiRttManager";
     private static final boolean VDBG = false;
diff --git a/wifi/java/android/net/wifi/rtt/package.html b/wifi/java/android/net/wifi/rtt/package.html
index 221b94b7..a0d407a 100644
--- a/wifi/java/android/net/wifi/rtt/package.html
+++ b/wifi/java/android/net/wifi/rtt/package.html
@@ -5,7 +5,7 @@
 <p>The primary entry point to Wi-Fi RTT capabilities is the
     {@link android.net.wifi.rtt.WifiRttManager} class, which is acquired by calling
     {@link android.content.Context#getSystemService(String)
-    Context.getSystemService(Context.WIFI_RTT_SERVICE)}</p>
+    Context.getSystemService(Context.WIFI_RTT_RANGING_SERVICE)}</p>
 
 <p>Some APIs may require the following user permissions:</p>
 <ul>