Merge "MediaSession2: Ensure NonNull/Nullable for parameters of public methods" into pi-dev
diff --git a/cmds/statsd/OWNERS b/cmds/statsd/OWNERS
index 362d411..1315750 100644
--- a/cmds/statsd/OWNERS
+++ b/cmds/statsd/OWNERS
@@ -1,6 +1,11 @@
 bookatz@google.com
+cjyu@google.com
+dwchen@google.com
 jinyithu@google.com
+joeo@google.com
 kwekua@google.com
+singhtejinder@google.com
 stlafon@google.com
 yaochen@google.com
 yanglu@google.com
+yro@google.com
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.cpp b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
index 6ee51f3..133f33b 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.cpp
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
@@ -59,6 +59,12 @@
 }
 
 size_t AnomalyTracker::index(int64_t bucketNum) const {
+    if (bucketNum < 0) {
+        // To support this use-case, we can easily modify index to wrap around. But currently
+        // AnomalyTracker should never need this, so if it happens, it's a bug we should log.
+        // TODO: Audit this.
+        ALOGE("index() was passed a negative bucket number (%lld)!", (long long)bucketNum);
+    }
     return bucketNum % mNumOfPastBuckets;
 }
 
@@ -72,9 +78,7 @@
     // The past packets are ancient. Empty out old mPastBuckets[i] values and reset
     // mSumOverPastBuckets.
     if (latestPastBucketNum - mMostRecentBucketNum >= mNumOfPastBuckets) {
-        mPastBuckets.clear();
-        mPastBuckets.resize(mNumOfPastBuckets);
-        mSumOverPastBuckets.clear();
+        resetStorage();
     } else {
         for (int64_t i = std::max(0LL, (long long)(mMostRecentBucketNum - mNumOfPastBuckets + 1));
              i <= latestPastBucketNum - mNumOfPastBuckets; i++) {
@@ -150,7 +154,7 @@
 
 int64_t AnomalyTracker::getPastBucketValue(const MetricDimensionKey& key,
                                            const int64_t& bucketNum) const {
-    if (mNumOfPastBuckets == 0) {
+    if (mNumOfPastBuckets == 0 || bucketNum < 0) {
         return 0;
     }
 
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.h b/cmds/statsd/src/anomaly/AnomalyTracker.h
index e3f493c..d27dee8 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.h
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.h
@@ -110,7 +110,7 @@
 
     // Number of past buckets. One less than the total number of buckets needed
     // for the anomaly detection (since the current bucket is not in the past).
-    int mNumOfPastBuckets;
+    const int mNumOfPastBuckets;
 
     // The existing bucket list.
     std::vector<shared_ptr<DimToValMap>> mPastBuckets;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index c717dd9..e952cab 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10911,6 +10911,15 @@
         private static final Validator LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR =
                 new SettingsValidators.InclusiveIntegerRangeValidator(0, 100);
 
+
+        /**
+         * The max value for {@link #LOW_POWER_MODE_TRIGGER_LEVEL}. If this setting is not set
+         * or the value is 0, the default max will be used.
+         *
+         * @hide
+         */
+        public static final String LOW_POWER_MODE_TRIGGER_LEVEL_MAX = "low_power_trigger_level_max";
+
          /**
          * If not 0, the activity manager will aggressively finish activities and
          * processes as soon as they are no longer needed.  If 0, the normal
@@ -11587,6 +11596,8 @@
             VALIDATORS.put(DOCK_AUDIO_MEDIA_ENABLED, DOCK_AUDIO_MEDIA_ENABLED_VALIDATOR);
             VALIDATORS.put(ENCODED_SURROUND_OUTPUT, ENCODED_SURROUND_OUTPUT_VALIDATOR);
             VALIDATORS.put(LOW_POWER_MODE_TRIGGER_LEVEL, LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR);
+            VALIDATORS.put(LOW_POWER_MODE_TRIGGER_LEVEL_MAX,
+                    LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR);
             VALIDATORS.put(BLUETOOTH_ON, BLUETOOTH_ON_VALIDATOR);
             VALIDATORS.put(PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_VALIDATOR);
             VALIDATORS.put(PRIVATE_DNS_SPECIFIER, PRIVATE_DNS_SPECIFIER_VALIDATOR);
diff --git a/core/proto/README.md b/core/proto/README.md
new file mode 100644
index 0000000..d2b89a5
--- /dev/null
+++ b/core/proto/README.md
@@ -0,0 +1,41 @@
+Conventions for the protos in this directory:
+
+1. As in the rest of Android, use 4 spaces to indent instead of 2.
+
+1. For protos based on Java files, use the same package as the Java file. For
+   example, `com.android.server.thing` instead of `com.android.server.thing.proto`.
+
+1. If the proto describes the top level output of dumpsys, it should contain
+   `Dump`. This makes it easy to understand that the proto is the dumpsys output
+   of a certain service, not the data structure of that service, e.g.
+   `WindowManagerServiceDumpProto` vs `WindowManagerServiceDumpProto`.
+
+   * Inner messages whose containing messages have the `Proto` suffix do not
+     need to have a `Proto` suffix. E.g:
+
+```
+message FooProto {
+    message Bar {
+        ...
+    }
+}
+```
+
+     vs
+
+```
+message FooProto {
+    message BarProto {
+        ...
+    }
+}
+```
+
+1. If the proto represents the structure of an object, it should have `Proto` as
+   its suffix. Please also include the full package path of the original object
+   as a comment to the proto message.
+
+1. Include units in the field names. For example, `screen_time_ms` vs
+   `screen_time`, or `file_size_bytes` or `file_size_mebibytes` vs `file_size`.
+
+1. Leave field numbers 50,000 - 100,000 reserved for OEMs.
diff --git a/core/proto/android/bluetooth/enums.proto b/core/proto/android/bluetooth/enums.proto
index 06ae2d3..9e459e6 100644
--- a/core/proto/android/bluetooth/enums.proto
+++ b/core/proto/android/bluetooth/enums.proto
@@ -21,10 +21,23 @@
 option java_multiple_files = true;
 
 // Bluetooth connection states.
-// Primarily used by android/bluetooth/BluetoothAdapter.java
 enum ConnectionStateEnum {
   CONNECTION_STATE_DISCONNECTED = 0;
   CONNECTION_STATE_CONNECTING = 1;
   CONNECTION_STATE_CONNECTED = 2;
   CONNECTION_STATE_DISCONNECTING = 3;
+}
+
+// Bluetooth Adapter Enable and Disable Reasons
+enum EnableDisableReasonEnum {
+  ENABLE_DISABLE_REASON_UNSPECIFIED = 0;
+  ENABLE_DISABLE_REASON_APPLICATION_REQUEST = 1;
+  ENABLE_DISABLE_REASON_AIRPLANE_MODE = 2;
+  ENABLE_DISABLE_REASON_DISALLOWED = 3;
+  ENABLE_DISABLE_REASON_RESTARTED = 4;
+  ENABLE_DISABLE_REASON_START_ERROR = 5;
+  ENABLE_DISABLE_REASON_SYSTEM_BOOT = 6;
+  ENABLE_DISABLE_REASON_CRASH = 7;
+  ENABLE_DISABLE_REASON_USER_SWITCH = 8;
+  ENABLE_DISABLE_REASON_RESTORE_USER_SETTING = 9;
 }
\ No newline at end of file
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index bb9568b..4657dc4 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -280,4 +280,7 @@
         (section).type = SECTION_DUMPSYS,
         (section).args = "usb --proto"
     ];
+
+    // Reserved for OEMs.
+    extensions 50000 to 100000;
 }
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 6c72ac1..22a261e 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -263,6 +263,7 @@
                     Settings.Global.LOW_BATTERY_SOUND,
                     Settings.Global.LOW_BATTERY_SOUND_TIMEOUT,
                     Settings.Global.LOW_POWER_MODE,
+                    Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX,
                     Settings.Global.LTE_SERVICE_FORCED,
                     Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE,
                     Settings.Global.MDC_INITIAL_MAX_RETRY,
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index 7c114df..b2b609e 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -311,26 +311,34 @@
         return 0;
     }
 
-    /**
-     * Gets the current player state.
-     *
-     * @return the current player state, one of the following:
-     * @throws IllegalStateException if the internal player engine has not been
-     * initialized or has been released.
-     */
     @Override
     public @PlayerState int getPlayerState() {
-        // TODO: use cached state or call native function.
-        return PLAYER_STATE_IDLE;
+        int mediaplayer2State = getMediaPlayer2State();
+        int playerState;
+        switch (mediaplayer2State) {
+            case MEDIAPLAYER2_STATE_IDLE:
+                playerState = PLAYER_STATE_IDLE;
+                break;
+            case MEDIAPLAYER2_STATE_PREPARED:
+            case MEDIAPLAYER2_STATE_PAUSED:
+                playerState = PLAYER_STATE_PAUSED;
+                break;
+            case MEDIAPLAYER2_STATE_PLAYING:
+                playerState = PLAYER_STATE_PLAYING;
+                break;
+            case MEDIAPLAYER2_STATE_ERROR:
+            default:
+                playerState = PLAYER_STATE_ERROR;
+                break;
+        }
+
+        return playerState;
     }
 
     /**
      * Gets the current buffering state of the player.
      * During buffering, see {@link #getBufferedPosition()} for the quantifying the amount already
      * buffered.
-     * @return the buffering state, one of the following:
-     * @throws IllegalStateException if the internal player engine has not been
-     * initialized or has been released.
      */
     @Override
     public @BuffState int getBufferingState() {
diff --git a/media/java/android/media/MediaSession2.java b/media/java/android/media/MediaSession2.java
index 67dafed..65378b4 100644
--- a/media/java/android/media/MediaSession2.java
+++ b/media/java/android/media/MediaSession2.java
@@ -904,9 +904,8 @@
         }
 
         /**
-         * Set the underlying {@link MediaPlayerBase} for this session to dispatch incoming event
+         * Sets the underlying {@link MediaPlayerBase} for this session to dispatch incoming event
          * to.
-         * <p>
          *
          * @param player a {@link MediaPlayerBase} that handles actual media playback in your app.
          */
@@ -916,21 +915,24 @@
         }
 
         /**
-         * Set the {@link MediaPlaylistAgent} for this session to manages playlist of the
-         * underlying {@link MediaPlayerBase player}.
+         * Sets the {@link MediaPlaylistAgent} for this session to manages playlist of the
+         * underlying {@link MediaPlayerBase}. The playlist agent should manage
+         * {@link MediaPlayerBase} for calling {@link MediaPlayerBase#setNextDataSources(List)}.
+         * <p>
+         * If the {@link MediaPlaylistAgent} isn't set, session will create the default playlist
+         * agent.
          *
          * @param playlistAgent a {@link MediaPlaylistAgent} that manages playlist of the
-         * {@code player}
+         *                      {@code player}
          */
         U setPlaylistAgent(@NonNull MediaPlaylistAgent playlistAgent) {
-            // TODO(jaewan): fix this
             mProvider.setPlaylistAgent_impl(playlistAgent);
             return (U) this;
         }
 
         /**
-         * Set the {@link VolumeProvider2} for this session to receive volume button events. If not
-         * set, system will adjust the appropriate stream volume for this session's player.
+         * Sets the {@link VolumeProvider2} for this session to handle volume events. If not set,
+         * system will adjust the appropriate stream volume for this session's player.
          *
          * @param volumeProvider The provider that will receive volume button events.
          */
@@ -1371,15 +1373,19 @@
     }
 
     /**
-     * Set the underlying {@link MediaPlayerBase} for this session to dispatch incoming event
-     * to. Events from the {@link MediaController2} will be sent directly to the underlying
-     * player on the {@link Handler} where the session is created on.
+     * Sets the underlying {@link MediaPlayerBase} and {@link MediaPlaylistAgent} for this session
+     * to dispatch incoming event to.
+     * <p>
+     * When a {@link MediaPlaylistAgent} is specified here, the playlist agent should manage
+     * {@link MediaPlayerBase} for calling {@link MediaPlayerBase#setNextDataSources(List)}.
+     * <p>
+     * If the {@link MediaPlaylistAgent} isn't set, session will recreate the default playlist
+     * agent.
      *
-     * @param player a {@link MediaPlayerBase} that handles actual media playback in your app.
-     * @param playlistAgent a {@link MediaPlaylistAgent} that manages playlist of the
-     * {@code player}
-     * @param volumeProvider The provider that will receive volume button events. If
-     * {@code null}, system will adjust the appropriate stream volume for this session's player.
+     * @param player a {@link MediaPlayerBase} that handles actual media playback in your app
+     * @param playlistAgent a {@link MediaPlaylistAgent} that manages playlist of the {@code player}
+     * @param volumeProvider a {@link VolumeProvider2}. If {@code null}, system will adjust the
+     *                       appropriate stream volume for this session's player.
      */
     public void updatePlayer(@NonNull MediaPlayerBase player,
             @Nullable MediaPlaylistAgent playlistAgent, @Nullable VolumeProvider2 volumeProvider) {
@@ -1394,18 +1400,15 @@
     /**
      * @return player
      */
-    public @NonNull
-    MediaPlayerBase getPlayer() {
+    public @NonNull MediaPlayerBase getPlayer() {
         return mProvider.getPlayer_impl();
     }
 
     /**
-     * @return playlist manager
+     * @return playlist agent
      */
-    public @Nullable
-    MediaPlaylistAgent getPlaylistAgent() {
-        // TODO(jaewan): implement this (b/74090741)
-        return null;
+    public @NonNull MediaPlaylistAgent getPlaylistAgent() {
+        return mProvider.getPlaylistAgent_impl();
     }
 
     /**
diff --git a/media/java/android/media/update/MediaSession2Provider.java b/media/java/android/media/update/MediaSession2Provider.java
index 4845e16..142650a 100644
--- a/media/java/android/media/update/MediaSession2Provider.java
+++ b/media/java/android/media/update/MediaSession2Provider.java
@@ -47,6 +47,7 @@
     void updatePlayer_impl(MediaPlayerBase player, MediaPlaylistAgent playlistAgent,
             VolumeProvider2 volumeProvider);
     MediaPlayerBase getPlayer_impl();
+    MediaPlaylistAgent getPlaylistAgent_impl();
     VolumeProvider2 getVolumeProvider_impl();
     SessionToken2 getToken_impl();
     List<ControllerInfo> getConnectedControllers_impl();
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 55ad8cc..02b1380 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -21,6 +21,7 @@
 import android.app.AppGlobals;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothProtoEnums;
 import android.bluetooth.IBluetooth;
 import android.bluetooth.IBluetoothCallback;
 import android.bluetooth.IBluetoothGatt;
@@ -87,14 +88,6 @@
 
     private static final int ACTIVE_LOG_MAX_SIZE = 20;
     private static final int CRASH_LOG_MAX_SIZE = 100;
-    private static final String REASON_AIRPLANE_MODE = "airplane mode";
-    private static final String REASON_DISALLOWED = "disallowed by system";
-    private static final String REASON_RESTARTED = "automatic restart";
-    private static final String REASON_START_CRASH = "turn-on crash";
-    private static final String REASON_SYSTEM_BOOT = "system boot";
-    private static final String REASON_UNEXPECTED = "unexpected crash";
-    private static final String REASON_USER_SWITCH = "user switch";
-    private static final String REASON_RESTORE_USER_SETTING = "restore user setting";
 
     private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind
     //Maximum msec to wait for service restart
@@ -163,7 +156,7 @@
     private boolean mQuietEnable = false;
     private boolean mEnable;
 
-    private CharSequence timeToLog(long timestamp) {
+    private static CharSequence timeToLog(long timestamp) {
         return android.text.format.DateFormat.format("MM-dd HH:mm:ss", timestamp);
     }
 
@@ -171,29 +164,27 @@
      * Used for tracking apps that enabled / disabled Bluetooth.
      */
     private class ActiveLog {
+        private int mReason;
         private String mPackageName;
         private boolean mEnable;
         private long mTimestamp;
 
-        ActiveLog(String packageName, boolean enable, long timestamp) {
+        ActiveLog(int reason, String packageName, boolean enable, long timestamp) {
+            mReason = reason;
             mPackageName = packageName;
             mEnable = enable;
             mTimestamp = timestamp;
         }
 
-        public long getTime() {
-            return mTimestamp;
-        }
-
         public String toString() {
-            return timeToLog(mTimestamp) + (mEnable ? "  Enabled " : " Disabled ") + " by "
-                    + mPackageName;
+            return timeToLog(mTimestamp) + (mEnable ? "  Enabled " : " Disabled ")
+                    + " due to " + getEnableDisableReasonString(mReason) + " by " + mPackageName;
         }
 
     }
 
-    private LinkedList<ActiveLog> mActiveLogs;
-    private LinkedList<Long> mCrashTimestamps;
+    private final LinkedList<ActiveLog> mActiveLogs = new LinkedList<>();
+    private final LinkedList<Long> mCrashTimestamps = new LinkedList<>();
     private int mCrashes;
     private long mLastEnabledTime;
 
@@ -213,8 +204,7 @@
 
     // Save a ProfileServiceConnections object for each of the bound
     // bluetooth profile services
-    private final Map<Integer, ProfileServiceConnections> mProfileServices =
-            new HashMap<Integer, ProfileServiceConnections>();
+    private final Map<Integer, ProfileServiceConnections> mProfileServices = new HashMap<>();
 
     private final boolean mPermissionReviewRequired;
 
@@ -246,7 +236,8 @@
                         if (userId == UserHandle.USER_SYSTEM && newRestrictions.getBoolean(
                                 UserManager.DISALLOW_BLUETOOTH)) {
                             updateOppLauncherComponentState(userId, true); // Sharing disallowed
-                            sendDisableMsg(REASON_DISALLOWED);
+                            sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED,
+                                    mContext.getPackageName());
                         } else {
                             updateOppLauncherComponentState(userId, newRestrictions.getBoolean(
                                     UserManager.DISALLOW_BLUETOOTH_SHARING));
@@ -303,10 +294,13 @@
                             mBluetoothLock.readLock().unlock();
                         }
                     } else if (st == BluetoothAdapter.STATE_ON) {
-                        sendDisableMsg(REASON_AIRPLANE_MODE);
+                        sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
+                                mContext.getPackageName());
                     }
                 } else if (mEnableExternal) {
-                    sendEnableMsg(mQuietEnableExternal, REASON_AIRPLANE_MODE);
+                    sendEnableMsg(mQuietEnableExternal,
+                            BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
+                            mContext.getPackageName());
                 }
             }
         }
@@ -369,8 +363,6 @@
         mPermissionReviewRequired = context.getResources()
                 .getBoolean(com.android.internal.R.bool.config_permissionReviewRequired);
 
-        mActiveLogs = new LinkedList<ActiveLog>();
-        mCrashTimestamps = new LinkedList<Long>();
         mCrashes = 0;
         mBluetooth = null;
         mBluetoothBinder = null;
@@ -671,8 +663,8 @@
             return false;
         }
         try {
-            return (Settings.Global.getInt(mContentResolver,
-                    Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE)) != 0;
+            return Settings.Global.getInt(mContentResolver,
+                    Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE) != 0;
         } catch (SettingNotFoundException e) {
         }
         return false;
@@ -867,7 +859,8 @@
         synchronized (mReceiver) {
             mQuietEnableExternal = true;
             mEnableExternal = true;
-            sendEnableMsg(true, packageName);
+            sendEnableMsg(true,
+                    BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
         }
         return true;
     }
@@ -907,7 +900,8 @@
             mQuietEnableExternal = false;
             mEnableExternal = true;
             // waive WRITE_SECURE_SETTINGS permission check
-            sendEnableMsg(false, packageName);
+            sendEnableMsg(false,
+                    BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
         }
         if (DBG) {
             Slog.d(TAG, "enable returning");
@@ -943,7 +937,8 @@
                 persistBluetoothSetting(BLUETOOTH_OFF);
             }
             mEnableExternal = false;
-            sendDisableMsg(packageName);
+            sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
+                    packageName);
         }
         return true;
     }
@@ -1127,7 +1122,9 @@
             if (DBG) {
                 Slog.d(TAG, "Auto-enabling Bluetooth.");
             }
-            sendEnableMsg(mQuietEnableExternal, REASON_SYSTEM_BOOT);
+            sendEnableMsg(mQuietEnableExternal,
+                    BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT,
+                    mContext.getPackageName());
         } else if (!isNameAndAddressSet()) {
             if (DBG) {
                 Slog.d(TAG, "Getting adapter name and address");
@@ -1569,20 +1566,25 @@
                     break;
 
                 case MESSAGE_RESTORE_USER_SETTING:
-                    try {
-                        if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) {
-                            if (DBG) {
-                                Slog.d(TAG, "Restore Bluetooth state to disabled");
-                            }
-                            disable(REASON_RESTORE_USER_SETTING, true);
-                        } else if ((msg.arg1 == RESTORE_SETTING_TO_ON) && !mEnable) {
-                            if (DBG) {
-                                Slog.d(TAG, "Restore Bluetooth state to enabled");
-                            }
-                            enable(REASON_RESTORE_USER_SETTING);
+                    if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) {
+                        if (DBG) {
+                            Slog.d(TAG, "Restore Bluetooth state to disabled");
                         }
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "Unable to change Bluetooth On setting", e);
+                        persistBluetoothSetting(BLUETOOTH_OFF);
+                        mEnableExternal = false;
+                        sendDisableMsg(
+                                BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING,
+                                mContext.getPackageName());
+                    } else if ((msg.arg1 == RESTORE_SETTING_TO_ON) && !mEnable) {
+                        if (DBG) {
+                            Slog.d(TAG, "Restore Bluetooth state to enabled");
+                        }
+                        mQuietEnableExternal = false;
+                        mEnableExternal = true;
+                        // waive WRITE_SECURE_SETTINGS permission check
+                        sendEnableMsg(false,
+                                BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING,
+                                mContext.getPackageName());
                     }
                     break;
 
@@ -1609,7 +1611,7 @@
                     break;
                 }
                 case MESSAGE_ADD_PROXY_DELAYED: {
-                    ProfileServiceConnections psc = mProfileServices.get(new Integer(msg.arg1));
+                    ProfileServiceConnections psc = mProfileServices.get(msg.arg1);
                     if (psc == null) {
                         break;
                     }
@@ -1758,7 +1760,8 @@
 
                     // log the unexpected crash
                     addCrashLog();
-                    addActiveLog(REASON_UNEXPECTED, false);
+                    addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH,
+                            mContext.getPackageName(), false);
                     if (mEnable) {
                         mEnable = false;
                         // Send a Bluetooth Restart message
@@ -1792,7 +1795,8 @@
                      it doesnt change when IBluetooth
                      service restarts */
                     mEnable = true;
-                    addActiveLog(REASON_RESTARTED, true);
+                    addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED,
+                            mContext.getPackageName(), true);
                     handleEnable(mQuietEnable);
                     break;
                 }
@@ -1848,7 +1852,8 @@
 
                         unbindAllBluetoothProfileServices();
                         // disable
-                        addActiveLog(REASON_USER_SWITCH, false);
+                        addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH,
+                                mContext.getPackageName(), false);
                         handleDisable();
                         // Pbap service need receive STATE_TURNING_OFF intent to close
                         bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
@@ -1886,7 +1891,8 @@
                         mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
                         mState = BluetoothAdapter.STATE_OFF;
                         // enable
-                        addActiveLog(REASON_USER_SWITCH, true);
+                        addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH,
+                                mContext.getPackageName(), true);
                         // mEnable flag could have been reset on disableBLE. Reenable it.
                         mEnable = true;
                         handleEnable(mQuietEnable);
@@ -2153,23 +2159,24 @@
         return false;
     }
 
-    private void sendDisableMsg(String packageName) {
+    private void sendDisableMsg(int reason, String packageName) {
         mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE));
-        addActiveLog(packageName, false);
+        addActiveLog(reason, packageName, false);
     }
 
-    private void sendEnableMsg(boolean quietMode, String packageName) {
+    private void sendEnableMsg(boolean quietMode, int reason, String packageName) {
         mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0));
-        addActiveLog(packageName, true);
+        addActiveLog(reason, packageName, true);
         mLastEnabledTime = SystemClock.elapsedRealtime();
     }
 
-    private void addActiveLog(String packageName, boolean enable) {
+    private void addActiveLog(int reason, String packageName, boolean enable) {
         synchronized (mActiveLogs) {
             if (mActiveLogs.size() > ACTIVE_LOG_MAX_SIZE) {
                 mActiveLogs.remove();
             }
-            mActiveLogs.add(new ActiveLog(packageName, enable, System.currentTimeMillis()));
+            mActiveLogs.add(
+                    new ActiveLog(reason, packageName, enable, System.currentTimeMillis()));
         }
     }
 
@@ -2200,7 +2207,8 @@
         SystemClock.sleep(500);
 
         // disable
-        addActiveLog(REASON_START_CRASH, false);
+        addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR,
+                mContext.getPackageName(), false);
         handleDisable();
 
         waitForOnOff(false, true);
@@ -2344,4 +2352,29 @@
             writer.println(errorMsg);
         }
     }
+
+    private static String getEnableDisableReasonString(int reason) {
+        switch (reason) {
+            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST:
+                return "APPLICATION_REQUEST";
+            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE:
+                return "AIRPLANE_MODE";
+            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED:
+                return "DISALLOWED";
+            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED:
+                return "RESTARTED";
+            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR:
+                return "START_ERROR";
+            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT:
+                return "SYSTEM_BOOT";
+            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH:
+                return "CRASH";
+            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH:
+                return "USER_SWITCH";
+            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING:
+                return "RESTORE_USER_SETTING";
+            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_UNSPECIFIED:
+            default: return "UNKNOWN[" + reason + "]";
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 62d91a8..55512f4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5152,26 +5152,14 @@
         enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "startRecentsActivity()");
         final long origId = Binder.clearCallingIdentity();
         try {
+            final int recentsUid;
+            final String recentsPackage;
+            final List<IBinder> topVisibleActivities;
             synchronized (this) {
-                final int recentsUid = mRecentTasks.getRecentsComponentUid();
                 final ComponentName recentsComponent = mRecentTasks.getRecentsComponent();
-                final String recentsPackage = recentsComponent.getPackageName();
-
-                // If provided, kick off the request for the assist data in the background before
-                // starting the activity
-                if (assistDataReceiver != null) {
-                    final AppOpsManager appOpsManager = (AppOpsManager)
-                            mContext.getSystemService(Context.APP_OPS_SERVICE);
-                    final AssistDataReceiverProxy proxy = new AssistDataReceiverProxy(
-                            assistDataReceiver, recentsPackage);
-                    final AssistDataRequester requester = new AssistDataRequester(mContext, this,
-                            mWindowManager, appOpsManager, proxy, this,
-                            OP_ASSIST_STRUCTURE, OP_NONE);
-                    requester.requestAssistData(mStackSupervisor.getTopVisibleActivities(),
-                            true /* fetchData */, false /* fetchScreenshots */,
-                            true /* allowFetchData */, false /* alloweFetchScreenshots */,
-                            recentsUid, recentsPackage);
-                }
+                recentsPackage = recentsComponent.getPackageName();
+                recentsUid = mRecentTasks.getRecentsComponentUid();
+                topVisibleActivities = mStackSupervisor.getTopVisibleActivities();
 
                 // Start a new recents animation
                 final RecentsAnimation anim = new RecentsAnimation(this, mStackSupervisor,
@@ -5179,6 +5167,21 @@
                 anim.startRecentsActivity(intent, recentsAnimationRunner, recentsComponent,
                         recentsUid);
             }
+
+            // If provided, kick off the request for the assist data in the background. Do not hold
+            // the AM lock as this will just proxy directly to the assist data receiver provided.
+            if (assistDataReceiver != null) {
+                final AppOpsManager appOpsManager = (AppOpsManager)
+                        mContext.getSystemService(Context.APP_OPS_SERVICE);
+                final AssistDataReceiverProxy proxy = new AssistDataReceiverProxy(
+                        assistDataReceiver, recentsPackage);
+                final AssistDataRequester requester = new AssistDataRequester(mContext, this,
+                        mWindowManager, appOpsManager, proxy, this, OP_ASSIST_STRUCTURE, OP_NONE);
+                requester.requestAssistData(topVisibleActivities,
+                        true /* fetchData */, false /* fetchScreenshots */,
+                        true /* allowFetchData */, false /* allowFetchScreenshots */,
+                        recentsUid, recentsPackage);
+            }
         } finally {
             Binder.restoreCallingIdentity(origId);
         }
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 9bba9ed..24abf86 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -65,6 +65,8 @@
     public static final int DEXOPT_IDLE_BACKGROUND_JOB = 1 << 9;
     /** Indicates that dexopt should restrict access to private APIs. */
     public static final int DEXOPT_ENABLE_HIDDEN_API_CHECKS = 1 << 10;
+    /** Indicates that dexopt should convert to CompactDex. */
+    public static final int DEXOPT_GENERATE_COMPACT_DEX = 1 << 11;
 
     // NOTE: keep in sync with installd
     public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8;
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 9420a6c..5a7893a 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -266,8 +266,8 @@
                     throws InstallerException {
                 final StringBuilder builder = new StringBuilder();
 
-                // The version. Right now it's 7.
-                builder.append("7 ");
+                // The current version.
+                builder.append("8 ");
 
                 builder.append("dexopt");
 
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 77bf67d..9e7ad47 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -57,6 +57,7 @@
 import static com.android.server.pm.Installer.DEXOPT_STORAGE_DE;
 import static com.android.server.pm.Installer.DEXOPT_IDLE_BACKGROUND_JOB;
 import static com.android.server.pm.Installer.DEXOPT_ENABLE_HIDDEN_API_CHECKS;
+import static com.android.server.pm.Installer.DEXOPT_GENERATE_COMPACT_DEX;
 import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
 import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
 
@@ -532,12 +533,22 @@
         // Some apps are executed with restrictions on hidden API usage. If this app is one
         // of them, pass a flag to dexopt to enable the same restrictions during compilation.
         int hiddenApiFlag = info.isAllowedToUseHiddenApi() ? 0 : DEXOPT_ENABLE_HIDDEN_API_CHECKS;
+        // Avoid generating CompactDex for modes that are latency critical.
+        final int compilationReason = options.getCompilationReason();
+        boolean generateCompactDex = true;
+        switch (compilationReason) {
+            case PackageManagerService.REASON_FIRST_BOOT:
+            case PackageManagerService.REASON_BOOT:
+            case PackageManagerService.REASON_INSTALL:
+                 generateCompactDex = false;
+        }
         int dexFlags =
                 (isPublic ? DEXOPT_PUBLIC : 0)
                 | (debuggable ? DEXOPT_DEBUGGABLE : 0)
                 | profileFlag
                 | (options.isBootComplete() ? DEXOPT_BOOTCOMPLETE : 0)
                 | (options.isDexoptIdleBackgroundJob() ? DEXOPT_IDLE_BACKGROUND_JOB : 0)
+                | (generateCompactDex ? DEXOPT_GENERATE_COMPACT_DEX : 0)
                 | hiddenApiFlag;
         return adjustDexoptFlags(dexFlags);
     }
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index e31e20c..064e077 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -33,7 +33,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
-import org.junit.Ignore;
+import android.support.test.filters.FlakyTest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -300,7 +300,7 @@
     }
 
     @Test
-    @Ignore
+    @FlakyTest(bugId = 37908381)
     public void testFocusedWindowMultipleDisplays() throws Exception {
         // Create a focusable window and check that focus is calculated correctly
         final WindowState window1 =
diff --git a/wifi/java/android/net/wifi/rtt/WifiRttManager.java b/wifi/java/android/net/wifi/rtt/WifiRttManager.java
index d119579..457e904 100644
--- a/wifi/java/android/net/wifi/rtt/WifiRttManager.java
+++ b/wifi/java/android/net/wifi/rtt/WifiRttManager.java
@@ -16,7 +16,7 @@
 
 package android.net.wifi.rtt;
 
-import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
 import static android.Manifest.permission.ACCESS_WIFI_STATE;
 import static android.Manifest.permission.CHANGE_WIFI_STATE;
 import static android.Manifest.permission.LOCATION_HARDWARE;
@@ -109,7 +109,7 @@
      * @param executor The Executor on which to run the callback.
      * @param callback A callback for the result of the ranging request.
      */
-    @RequiresPermission(allOf = {ACCESS_COARSE_LOCATION, CHANGE_WIFI_STATE, ACCESS_WIFI_STATE})
+    @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, CHANGE_WIFI_STATE, ACCESS_WIFI_STATE})
     public void startRanging(@NonNull RangingRequest request,
             @NonNull @CallbackExecutor Executor executor, @NonNull RangingResultCallback callback) {
         startRanging(null, request, executor, callback);
@@ -128,7 +128,7 @@
      * @hide
      */
     @SystemApi
-    @RequiresPermission(allOf = {LOCATION_HARDWARE, ACCESS_COARSE_LOCATION, CHANGE_WIFI_STATE,
+    @RequiresPermission(allOf = {LOCATION_HARDWARE, ACCESS_FINE_LOCATION, CHANGE_WIFI_STATE,
             ACCESS_WIFI_STATE})
     public void startRanging(@Nullable WorkSource workSource, @NonNull RangingRequest request,
             @NonNull @CallbackExecutor Executor executor, @NonNull RangingResultCallback callback) {
diff --git a/wifi/java/android/net/wifi/rtt/package.html b/wifi/java/android/net/wifi/rtt/package.html
index 11ac058..e639282 100644
--- a/wifi/java/android/net/wifi/rtt/package.html
+++ b/wifi/java/android/net/wifi/rtt/package.html
@@ -11,7 +11,7 @@
 <ul>
     <li>{@link android.Manifest.permission#ACCESS_WIFI_STATE}</li>
     <li>{@link android.Manifest.permission#CHANGE_WIFI_STATE}</li>
-    <li>{@link android.Manifest.permission#ACCESS_COARSE_LOCATION}</li>
+    <li>{@link android.Manifest.permission#ACCESS_FINE_LOCATION}</li>
 </ul>
 <p>Usage of the API is also gated by the device's Location Mode: whether it permits Wi-Fi based
 location to be queried.</p>