Merge "Fixed an issue with a test that didn't work properly"
diff --git a/api/current.txt b/api/current.txt
index bc2d893..ed114703 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7267,6 +7267,7 @@
     method public void registerSliceCallback(android.net.Uri, java.util.List<android.app.slice.SliceSpec>, java.util.concurrent.Executor, android.app.slice.SliceManager.SliceCallback);
     method public void unpinSlice(android.net.Uri);
     method public void unregisterSliceCallback(android.net.Uri, android.app.slice.SliceManager.SliceCallback);
+    field public static final java.lang.String SLICE_METADATA_KEY = "android.metadata.SLICE_URI";
   }
 
   public static abstract interface SliceManager.SliceCallback {
@@ -24075,13 +24076,14 @@
     method public static final android.media.MediaPlayer2 create();
     method public abstract void deselectTrack(int);
     method public abstract android.media.DataSourceDesc editPlaylistItem(int, android.media.DataSourceDesc);
+    method public abstract android.media.AudioAttributes getAudioAttributes();
     method public abstract int getAudioSessionId();
     method public abstract android.media.DataSourceDesc getCurrentDataSource();
     method public abstract int getCurrentPlaylistItemIndex();
-    method public abstract int getCurrentPosition();
+    method public abstract long getCurrentPosition();
     method public abstract android.media.MediaPlayer2.DrmInfo getDrmInfo();
     method public abstract java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer2.NoDrmSchemeException;
-    method public abstract int getDuration();
+    method public abstract long getDuration();
     method public abstract android.media.MediaDrm.KeyRequest getKeyRequest(byte[], byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer2.NoDrmSchemeException;
     method public abstract int getLoopingMode();
     method public abstract android.os.PersistableBundle getMetrics();
@@ -24167,8 +24169,8 @@
 
   public static abstract class MediaPlayer2.DrmEventCallback {
     ctor public MediaPlayer2.DrmEventCallback();
-    method public void onDrmInfo(android.media.MediaPlayer2, android.media.MediaPlayer2.DrmInfo);
-    method public void onDrmPrepared(android.media.MediaPlayer2, int);
+    method public void onDrmInfo(android.media.MediaPlayer2, long, android.media.MediaPlayer2.DrmInfo);
+    method public void onDrmPrepared(android.media.MediaPlayer2, long, int);
   }
 
   public static abstract class MediaPlayer2.DrmInfo {
@@ -24206,7 +24208,7 @@
   }
 
   public static abstract interface MediaPlayer2.OnDrmConfigHelper {
-    method public abstract void onDrmConfig(android.media.MediaPlayer2);
+    method public abstract void onDrmConfig(android.media.MediaPlayer2, long);
   }
 
   public static abstract class MediaPlayer2.ProvisioningNetworkErrorException extends android.media.MediaDrmException {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index ccbf21b..a45c500 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -7624,6 +7624,19 @@
 
     /** @hide */
     @Override
+    public final void autofillClientDispatchUnhandledKey(@NonNull View anchor,
+            @NonNull KeyEvent keyEvent) {
+        ViewRootImpl rootImpl = anchor.getViewRootImpl();
+        if (rootImpl != null) {
+            // dont care if anchorView is current focus, for example a custom view may only receive
+            // touchEvent, not focusable but can still trigger autofill window. The Key handling
+            // might be inside parent of the custom view.
+            rootImpl.dispatchKeyFromAutofill(keyEvent);
+        }
+    }
+
+    /** @hide */
+    @Override
     public final boolean autofillClientRequestHideFillUi() {
         if (mAutofillPopupWindow == null) {
             return false;
diff --git a/core/java/android/app/slice/Slice.java b/core/java/android/app/slice/Slice.java
index 126deef..0a5795e 100644
--- a/core/java/android/app/slice/Slice.java
+++ b/core/java/android/app/slice/Slice.java
@@ -71,16 +71,6 @@
     public @interface SliceHint {}
 
     /**
-     * The meta-data key that allows an activity to easily be linked directly to a slice.
-     * <p>
-     * An activity can be statically linked to a slice uri by including a meta-data item
-     * for this key that contains a valid slice uri for the same application declaring
-     * the activity.
-     * @hide
-     */
-    public static final String SLICE_METADATA_KEY = "android.metadata.SLICE_URI";
-
-    /**
      * Hint that this content is a title of other content in the slice. This can also indicate that
      * the content should be used in the shortcut representation of the slice (icon, label, action),
      * normally this should be indicated by adding the hint on the action containing that content.
diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java
index 3f13fff..a978e5b 100644
--- a/core/java/android/app/slice/SliceManager.java
+++ b/core/java/android/app/slice/SliceManager.java
@@ -60,6 +60,15 @@
     public static final String ACTION_REQUEST_SLICE_PERMISSION =
             "android.intent.action.REQUEST_SLICE_PERMISSION";
 
+    /**
+     * The meta-data key that allows an activity to easily be linked directly to a slice.
+     * <p>
+     * An activity can be statically linked to a slice uri by including a meta-data item
+     * for this key that contains a valid slice uri for the same application declaring
+     * the activity.
+     */
+    public static final String SLICE_METADATA_KEY = "android.metadata.SLICE_URI";
+
     private final ISliceManager mService;
     private final Context mContext;
     private final ArrayMap<Pair<Uri, SliceCallback>, ISliceListener> mListenerLookup =
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 1e4f568..3c76242 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -7309,7 +7309,7 @@
     }
 
     private boolean isAccessibilityPane() {
-        return !TextUtils.isEmpty(mAccessibilityPaneTitle);
+        return mAccessibilityPaneTitle != null;
     }
 
     /**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 810864e..01d9265 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -3925,6 +3925,7 @@
     private final static int MSG_DISPATCH_APP_VISIBILITY = 8;
     private final static int MSG_DISPATCH_GET_NEW_SURFACE = 9;
     private final static int MSG_DISPATCH_KEY_FROM_IME = 11;
+    private final static int MSG_DISPATCH_KEY_FROM_AUTOFILL = 12;
     private final static int MSG_CHECK_FOCUS = 13;
     private final static int MSG_CLOSE_SYSTEM_DIALOGS = 14;
     private final static int MSG_DISPATCH_DRAG_EVENT = 15;
@@ -3966,6 +3967,8 @@
                     return "MSG_DISPATCH_GET_NEW_SURFACE";
                 case MSG_DISPATCH_KEY_FROM_IME:
                     return "MSG_DISPATCH_KEY_FROM_IME";
+                case MSG_DISPATCH_KEY_FROM_AUTOFILL:
+                    return "MSG_DISPATCH_KEY_FROM_AUTOFILL";
                 case MSG_CHECK_FOCUS:
                     return "MSG_CHECK_FOCUS";
                 case MSG_CLOSE_SYSTEM_DIALOGS:
@@ -4143,6 +4146,15 @@
                     }
                     enqueueInputEvent(event, null, QueuedInputEvent.FLAG_DELIVER_POST_IME, true);
                 } break;
+                case MSG_DISPATCH_KEY_FROM_AUTOFILL: {
+                    if (LOCAL_LOGV) {
+                        Log.v(TAG, "Dispatching key " + msg.obj + " from Autofill to " + mView);
+                    }
+                    KeyEvent event = (KeyEvent) msg.obj;
+                    // send InputEvent to pre IME, set FLAG_FROM_AUTOFILL so the InputEvent
+                    // wont be dropped as app window is not focus.
+                    enqueueInputEvent(event, null, QueuedInputEvent.FLAG_FROM_AUTOFILL, true);
+                } break;
                 case MSG_CHECK_FOCUS: {
                     InputMethodManager imm = InputMethodManager.peekInstance();
                     if (imm != null) {
@@ -4433,7 +4445,8 @@
                 Slog.w(mTag, "Dropping event due to root view being removed: " + q.mEvent);
                 return true;
             } else if ((!mAttachInfo.mHasWindowFocus
-                    && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) || mStopped
+                    && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)
+                    && (q.mFlags & QueuedInputEvent.FLAG_FROM_AUTOFILL) == 0) || mStopped
                     || (mIsAmbientMode && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_BUTTON))
                     || (mPausedForTransition && !isBack(q.mEvent))) {
                 // This is a focus event and the window doesn't currently have input focus or
@@ -6805,6 +6818,7 @@
         public static final int FLAG_FINISHED_HANDLED = 1 << 3;
         public static final int FLAG_RESYNTHESIZED = 1 << 4;
         public static final int FLAG_UNHANDLED = 1 << 5;
+        public static final int FLAG_FROM_AUTOFILL = 1 << 6;
 
         public QueuedInputEvent mNext;
 
@@ -7262,6 +7276,12 @@
         mHandler.sendMessage(msg);
     }
 
+    public void dispatchKeyFromAutofill(KeyEvent event) {
+        Message msg = mHandler.obtainMessage(MSG_DISPATCH_KEY_FROM_AUTOFILL, event);
+        msg.setAsynchronous(true);
+        mHandler.sendMessage(msg);
+    }
+
     /**
      * Reinject unhandled {@link InputEvent}s in order to synthesize fallbacks events.
      *
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 7792fa6..dd9b69f 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -46,6 +46,7 @@
 import android.util.Log;
 import android.util.SparseArray;
 import android.view.Choreographer;
+import android.view.KeyEvent;
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
@@ -411,6 +412,13 @@
                 @Nullable Rect virtualBounds, IAutofillWindowPresenter presenter);
 
         /**
+         * Dispatch unhandled keyevent from Autofill window
+         * @param anchor The real view the UI needs to anchor to.
+         * @param keyEvent Unhandled KeyEvent from autofill window.
+         */
+        void autofillClientDispatchUnhandledKey(@NonNull View anchor, @NonNull KeyEvent keyEvent);
+
+        /**
          * Request hiding the autofill UI.
          *
          * @return Whether the UI was hidden.
@@ -1668,6 +1676,24 @@
         }
     }
 
+    private void dispatchUnhandledKey(int sessionId, AutofillId id, KeyEvent keyEvent) {
+        final View anchor = findView(id);
+        if (anchor == null) {
+            return;
+        }
+
+        AutofillCallback callback = null;
+        synchronized (mLock) {
+            if (mSessionId == sessionId) {
+                AutofillClient client = getClient();
+
+                if (client != null) {
+                    client.autofillClientDispatchUnhandledKey(anchor, keyEvent);
+                }
+            }
+        }
+    }
+
     /** @hide */
     public static final int SET_STATE_FLAG_ENABLED = 0x01;
     /** @hide */
@@ -2610,6 +2636,14 @@
         }
 
         @Override
+        public void dispatchUnhandledKey(int sessionId, AutofillId id, KeyEvent fullScreen) {
+            final AutofillManager afm = mAfm.get();
+            if (afm != null) {
+                afm.post(() -> afm.dispatchUnhandledKey(sessionId, id, fullScreen));
+            }
+        }
+
+        @Override
         public void startIntentSender(IntentSender intentSender, Intent intent) {
             final AutofillManager afm = mAfm.get();
             if (afm != null) {
diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
index 254c8a5..0ff7a0b 100644
--- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl
+++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
@@ -25,6 +25,7 @@
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
 import android.view.autofill.IAutofillWindowPresenter;
+import android.view.KeyEvent;
 
 /**
  * Object running in the application process and responsible for autofilling it.
@@ -74,6 +75,13 @@
     void notifyNoFillUi(int sessionId, in AutofillId id, int sessionFinishedState);
 
     /**
+     * Dispatches unhandled keyevent from autofill ui. Autofill ui handles DPAD and ENTER events,
+     * other unhandled keyevents are dispatched to app's window to filter autofill result.
+     * Note this method is not called when autofill ui is in fullscreen mode (TV only).
+     */
+    void dispatchUnhandledKey(int sessionId, in AutofillId id, in KeyEvent keyEvent);
+
+    /**
      * Starts the provided intent sender.
      */
     void startIntentSender(in IntentSender intentSender, in Intent intent);
diff --git a/core/res/res/layout/autofill_dataset_picker.xml b/core/res/res/layout/autofill_dataset_picker.xml
index a88836e..ef19f87 100644
--- a/core/res/res/layout/autofill_dataset_picker.xml
+++ b/core/res/res/layout/autofill_dataset_picker.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 
-<FrameLayout  xmlns:android="http://schemas.android.com/apk/res/android"
+<view  xmlns:android="http://schemas.android.com/apk/res/android"
+    class="com.android.server.autofill.ui.FillUi$AutofillFrameLayout"
     android:id="@+id/autofill_dataset_picker"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
@@ -30,4 +31,4 @@
         android:visibility="gone">
     </ListView>
 
-</FrameLayout>
+</view>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e6186023..f4be888 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2106,6 +2106,10 @@
     <string name="keyguard_accessibility_face_unlock">Face unlock.</string>
     <!-- Accessibility description of the pin lock. [CHAR_LIMIT=none] -->
     <string name="keyguard_accessibility_pin_unlock">Pin unlock.</string>
+    <!-- Accessibility description of the sim pin lock. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_sim_pin_unlock">Sim Pin unlock.</string>
+    <!-- Accessibility description of the sim puk lock. [CHAR_LIMIT=none] -->
+    <string name="keyguard_accessibility_sim_puk_unlock">Sim Puk unlock.</string>
     <!-- Accessibility description of the password lock. [CHAR_LIMIT=none] -->
     <string name="keyguard_accessibility_password_unlock">Password unlock.</string>
     <!-- Accessibility description of the unlock pattern area. [CHAR_LIMIT=none] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ab4c12b..fc4d4e7 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3234,6 +3234,11 @@
   <java-symbol type="string" name="unsupported_compile_sdk_check_update" />
 
   <java-symbol type="string" name="battery_saver_warning_title" />
+  <java-symbol type="string" name="keyguard_accessibility_pattern_unlock" />
+  <java-symbol type="string" name="keyguard_accessibility_pin_unlock" />
+  <java-symbol type="string" name="keyguard_accessibility_sim_pin_unlock" />
+  <java-symbol type="string" name="keyguard_accessibility_sim_puk_unlock" />
+  <java-symbol type="string" name="keyguard_accessibility_password_unlock" />
 
   <java-symbol type="string" name="global_action_logout" />
   <java-symbol type="string" name="config_mainBuiltInDisplayCutout" />
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index 2f3d972..1446660 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -1223,7 +1223,7 @@
      *
      * @return the current position in milliseconds
      */
-    public abstract int getCurrentPosition();
+    public abstract long getCurrentPosition();
 
     /**
      * Gets the duration of the file.
@@ -1231,7 +1231,7 @@
      * @return the duration in milliseconds, if no duration is available
      *         (for example, if streaming live content), -1 is returned.
      */
-    public abstract int getDuration();
+    public abstract long getDuration();
 
     /**
      * Gets the media metadata.
@@ -1278,27 +1278,6 @@
     }
 
     /**
-     * Set the MediaPlayer2 to start when this MediaPlayer2 finishes playback
-     * (i.e. reaches the end of the stream).
-     * The media framework will attempt to transition from this player to
-     * the next as seamlessly as possible. The next player can be set at
-     * any time before completion, but shall be after setDataSource has been
-     * called successfully. The next player must be prepared by the
-     * app, and the application should not call play() on it.
-     * The next MediaPlayer2 must be different from 'this'. An exception
-     * will be thrown if next == this.
-     * The application may call setNextMediaPlayer(null) to indicate no
-     * next player should be started at the end of playback.
-     * If the current player is looping, it will keep looping and the next
-     * player will not be started.
-     *
-     * @param next the player to start after this one completes playback.
-     *
-     * @hide
-     */
-    public void setNextMediaPlayer(MediaPlayer2 next) { }
-
-    /**
      * Resets the MediaPlayer2 to its uninitialized state. After calling
      * this method, you will have to initialize it again by setting the
      * data source and calling prepareAsync().
@@ -1326,6 +1305,13 @@
     public abstract void setAudioAttributes(AudioAttributes attributes);
 
     /**
+     * Gets the audio attributes for this MediaPlayer2.
+     * @return attributes a set of audio attributes
+     * @throws IllegalArgumentException if the attributes are null or invalid.
+     */
+    public abstract AudioAttributes getAudioAttributes();
+
+    /**
      * Sets the player to be looping or non-looping.
      *
      * @param looping whether to loop or not
@@ -2029,8 +2015,9 @@
          * Called to give the app the opportunity to configure DRM before the session is created
          *
          * @param mp the {@code MediaPlayer2} associated with this callback
+         * @param srcId the Id of this data source
          */
-        public void onDrmConfig(MediaPlayer2 mp);
+        public void onDrmConfig(MediaPlayer2 mp, long srcId);
     }
 
     /**
@@ -2051,24 +2038,25 @@
         /**
          * Called to indicate DRM info is available
          *
-         * @param mp       the {@code MediaPlayer2} associated with this callback
-         * @param drmInfo  DRM info of the source including PSSH, and subset
-         *                 of crypto schemes supported by this device
+         * @param mp the {@code MediaPlayer2} associated with this callback
+         * @param srcId the Id of this data source
+         * @param drmInfo DRM info of the source including PSSH, and subset
+         *                of crypto schemes supported by this device
          */
-        public void onDrmInfo(MediaPlayer2 mp, DrmInfo drmInfo) { }
+        public void onDrmInfo(MediaPlayer2 mp, long srcId, DrmInfo drmInfo) { }
 
         /**
          * Called to notify the client that {@code prepareDrm} is finished and ready for key request/response.
          *
-         * @param mp      the {@code MediaPlayer2} associated with this callback
-         * @param status  the result of DRM preparation which can be
+         * @param mp the {@code MediaPlayer2} associated with this callback
+         * @param srcId the Id of this data source
+         * @param status the result of DRM preparation which can be
          * {@link #PREPARE_DRM_STATUS_SUCCESS},
          * {@link #PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR},
          * {@link #PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR}, or
          * {@link #PREPARE_DRM_STATUS_PREPARATION_ERROR}.
          */
-        public void onDrmPrepared(MediaPlayer2 mp, @PrepareDrmStatusCode int status) { }
-
+        public void onDrmPrepared(MediaPlayer2 mp, long srcId, @PrepareDrmStatusCode int status) { }
     }
 
     /**
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index 1b21b5b..7794e08 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -1889,7 +1889,7 @@
      * @return the current position in milliseconds
      */
     @Override
-    public native int getCurrentPosition();
+    public native long getCurrentPosition();
 
     /**
      * Gets the duration of the file.
@@ -1898,7 +1898,7 @@
      *         (for example, if streaming live content), -1 is returned.
      */
     @Override
-    public native int getDuration();
+    public native long getDuration();
 
     /**
      * Gets the media metadata.
@@ -1986,28 +1986,6 @@
     }
 
     /**
-     * Set the MediaPlayer2 to start when this MediaPlayer2 finishes playback
-     * (i.e. reaches the end of the stream).
-     * The media framework will attempt to transition from this player to
-     * the next as seamlessly as possible. The next player can be set at
-     * any time before completion, but shall be after setDataSource has been
-     * called successfully. The next player must be prepared by the
-     * app, and the application should not call play() on it.
-     * The next MediaPlayer2 must be different from 'this'. An exception
-     * will be thrown if next == this.
-     * The application may call setNextMediaPlayer(null) to indicate no
-     * next player should be started at the end of playback.
-     * If the current player is looping, it will keep looping and the next
-     * player will not be started.
-     *
-     * @param next the player to start after this one completes playback.
-     *
-     * @hide
-     */
-    @Override
-    public native void setNextMediaPlayer(MediaPlayer2 next);
-
-    /**
      * Resets the MediaPlayer2 to its uninitialized state. After calling
      * this method, you will have to initialize it again by setting the
      * data source and calling prepareAsync().
@@ -2078,10 +2056,11 @@
      * @param key key indicates the parameter to be set.
      * @param value value of the parameter to be set.
      * @return true if the parameter is set successfully, false otherwise
-     * {@hide}
      */
     private native boolean setParameter(int key, Parcel value);
 
+    private native Parcel getParameter(int key);
+
     /**
      * Sets the audio attributes for this MediaPlayer2.
      * See {@link AudioAttributes} for how to build and configure an instance of this class.
@@ -2105,6 +2084,14 @@
         pattributes.recycle();
     }
 
+    @Override
+    public AudioAttributes getAudioAttributes() {
+        Parcel pattributes = getParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES);
+        AudioAttributes attributes = AudioAttributes.CREATOR.createFromParcel(pattributes);
+        pattributes.recycle();
+        return attributes;
+    }
+
     /**
      * Sets the player to be looping or non-looping.
      *
@@ -3211,11 +3198,12 @@
                     }
 
                     // notifying the client outside the lock
+                    // TODO: get srcId
                     if (drmInfo != null) {
                         synchronized (mEventCbLock) {
                             for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) {
                                 cb.first.execute(() -> cb.second.onDrmInfo(
-                                        mMediaPlayer, drmInfo));
+                                        mMediaPlayer, 0, drmInfo));
                             }
                         }
                     }
@@ -3747,8 +3735,9 @@
 
 
         // call the callback outside the lock
+        // TODO: get srcId
         if (mOnDrmConfigHelper != null)  {
-            mOnDrmConfigHelper.onDrmConfig(this);
+            mOnDrmConfigHelper.onDrmConfig(this, 0);
         }
 
         synchronized (mDrmLock) {
@@ -3818,11 +3807,12 @@
 
 
         // if finished successfully without provisioning, call the callback outside the lock
+        // TODO: get srcId
         if (allDoneWithoutProvisioning) {
             synchronized (mDrmEventCbLock) {
                 for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) {
                     cb.first.execute(() -> cb.second.onDrmPrepared(
-                            this, PREPARE_DRM_STATUS_SUCCESS));
+                            this, 0, PREPARE_DRM_STATUS_SUCCESS));
                 }
             }
         }
@@ -4488,9 +4478,10 @@
                 } // synchronized
 
                 // calling the callback outside the lock
+                // TODO: get srcId
                 synchronized (mDrmEventCbLock) {
                     for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) {
-                        cb.first.execute(() -> cb.second.onDrmPrepared(mediaPlayer, status));
+                        cb.first.execute(() -> cb.second.onDrmPrepared(mediaPlayer, 0, status));
                     }
                 }
             } else {   // blocking mode already has the lock
diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp
index cf115a4..2258c78 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -760,7 +760,8 @@
         return;
     }
     ALOGV("seekTo: %lld(msec), mode=%d", (long long)msec, mode);
-    process_media_player_call( env, thiz, mp->seekTo((int)msec, (MediaPlayer2SeekMode)mode), NULL, NULL );
+    process_media_player_call(env, thiz, mp->seekTo((int64_t)msec, (MediaPlayer2SeekMode)mode),
+                              NULL, NULL);
 }
 
 static void
@@ -838,7 +839,7 @@
     return mybundle;
 }
 
-static jint
+static jlong
 android_media_MediaPlayer2_getCurrentPosition(JNIEnv *env, jobject thiz)
 {
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
@@ -846,13 +847,13 @@
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
         return 0;
     }
-    int msec;
+    int64_t msec;
     process_media_player_call( env, thiz, mp->getCurrentPosition(&msec), NULL, NULL );
-    ALOGV("getCurrentPosition: %d (msec)", msec);
-    return (jint) msec;
+    ALOGV("getCurrentPosition: %lld (msec)", (long long)msec);
+    return (jlong) msec;
 }
 
-static jint
+static jlong
 android_media_MediaPlayer2_getDuration(JNIEnv *env, jobject thiz)
 {
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
@@ -860,10 +861,10 @@
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
         return 0;
     }
-    int msec;
+    int64_t msec;
     process_media_player_call( env, thiz, mp->getDuration(&msec), NULL, NULL );
-    ALOGV("getDuration: %d (msec)", msec);
-    return (jint) msec;
+    ALOGV("getDuration: %lld (msec)", (long long)msec);
+    return (jlong) msec;
 }
 
 static void
@@ -911,6 +912,28 @@
     }
 }
 
+static jobject
+android_media_MediaPlayer2_getParameter(JNIEnv *env, jobject thiz, jint key)
+{
+    ALOGV("getParameter: key %d", key);
+    sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return NULL;
+    }
+
+    jobject jParcel = createJavaParcelObject(env);
+    if (jParcel != NULL) {
+        Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
+        status_t err = mp->getParameter(key, nativeParcel);
+        if (err != OK) {
+            env->DeleteLocalRef(jParcel);
+            return NULL;
+        }
+    }
+    return jParcel;
+}
+
 static void
 android_media_MediaPlayer2_setLooping(JNIEnv *env, jobject thiz, jboolean looping)
 {
@@ -1171,33 +1194,6 @@
     process_media_player_call( env, thiz, mp->attachAuxEffect(effectId), NULL, NULL );
 }
 
-static void
-android_media_MediaPlayer2_setNextMediaPlayer(JNIEnv *env, jobject thiz, jobject java_player)
-{
-    ALOGV("setNextMediaPlayer");
-    sp<MediaPlayer2> thisplayer = getMediaPlayer(env, thiz);
-    if (thisplayer == NULL) {
-        jniThrowException(env, "java/lang/IllegalStateException", "This player not initialized");
-        return;
-    }
-    sp<MediaPlayer2> nextplayer = (java_player == NULL) ? NULL : getMediaPlayer(env, java_player);
-    if (nextplayer == NULL && java_player != NULL) {
-        jniThrowException(env, "java/lang/IllegalStateException", "That player not initialized");
-        return;
-    }
-
-    if (nextplayer == thisplayer) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", "Next player can't be self");
-        return;
-    }
-    // tie the two players together
-    process_media_player_call(
-            env, thiz, thisplayer->setNextMediaPlayer(nextplayer),
-            "java/lang/IllegalArgumentException",
-            "setNextMediaPlayer failed." );
-    ;
-}
-
 /////////////////////////////////////////////////////////////////////////////////////
 // Modular DRM begin
 
@@ -1498,12 +1494,13 @@
     {"_notifyAt",           "(J)V",                             (void *)android_media_MediaPlayer2_notifyAt},
     {"_pause",              "()V",                              (void *)android_media_MediaPlayer2_pause},
     {"isPlaying",           "()Z",                              (void *)android_media_MediaPlayer2_isPlaying},
-    {"getCurrentPosition",  "()I",                              (void *)android_media_MediaPlayer2_getCurrentPosition},
-    {"getDuration",         "()I",                              (void *)android_media_MediaPlayer2_getDuration},
+    {"getCurrentPosition",  "()J",                              (void *)android_media_MediaPlayer2_getCurrentPosition},
+    {"getDuration",         "()J",                              (void *)android_media_MediaPlayer2_getDuration},
     {"_release",            "()V",                              (void *)android_media_MediaPlayer2_release},
     {"_reset",              "()V",                              (void *)android_media_MediaPlayer2_reset},
     {"_getAudioStreamType", "()I",                              (void *)android_media_MediaPlayer2_getAudioStreamType},
     {"setParameter",        "(ILandroid/os/Parcel;)Z",          (void *)android_media_MediaPlayer2_setParameter},
+    {"getParameter",        "(I)Landroid/os/Parcel;",           (void *)android_media_MediaPlayer2_getParameter},
     {"setLooping",          "(Z)V",                             (void *)android_media_MediaPlayer2_setLooping},
     {"isLooping",           "()Z",                              (void *)android_media_MediaPlayer2_isLooping},
     {"_setVolume",          "(FF)V",                            (void *)android_media_MediaPlayer2_setVolume},
@@ -1517,7 +1514,6 @@
     {"setAudioSessionId",   "(I)V",                             (void *)android_media_MediaPlayer2_set_audio_session_id},
     {"_setAuxEffectSendLevel", "(F)V",                          (void *)android_media_MediaPlayer2_setAuxEffectSendLevel},
     {"attachAuxEffect",     "(I)V",                             (void *)android_media_MediaPlayer2_attachAuxEffect},
-    {"setNextMediaPlayer",  "(Landroid/media/MediaPlayer2;)V",  (void *)android_media_MediaPlayer2_setNextMediaPlayer},
     // Modular DRM
     { "_prepareDrm", "([B[B)V",                                 (void *)android_media_MediaPlayer2_prepareDrm },
     { "_releaseDrm", "()V",                                     (void *)android_media_MediaPlayer2_releaseDrm },
diff --git a/packages/InputDevices/res/values-as/strings.xml b/packages/InputDevices/res/values-as/strings.xml
new file mode 100644
index 0000000..26da1b1
--- /dev/null
+++ b/packages/InputDevices/res/values-as/strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label" msgid="8016145283189546017">"ইনপুট ডিভাইচসমূহ"</string>
+    <string name="keyboard_layouts_label" msgid="6688773268302087545">"Android কীব\'ৰ্ড"</string>
+    <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"ইংৰাজী (ইউ. কে.)"</string>
+    <string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"ইংৰাজী ( ইউ. এছ.)"</string>
+    <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"ইংৰাজী (ইউ. কে.), আন্তঃৰাষ্ট্ৰীয় ষ্টাইল"</string>
+    <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"ইংৰাজী (ইউ. কে.), ক\'লমেক ষ্টাইল"</string>
+    <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"ইংৰাজী (ইউ. কে.), ডভ\'ৰাক ষ্টাইল"</string>
+    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
+    <skip />
+    <string name="keyboard_layout_german_label" msgid="8451565865467909999">"জাৰ্মান"</string>
+    <string name="keyboard_layout_french_label" msgid="813450119589383723">"ফৰাচী"</string>
+    <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"ফৰাচী (কানাডা)"</string>
+    <string name="keyboard_layout_russian_label" msgid="8724879775815042968">"ৰাছিয়ান"</string>
+    <string name="keyboard_layout_russian_mac_label" msgid="3795866869038264796">"ৰাছিয়ান, মেক ষ্টাইল"</string>
+    <string name="keyboard_layout_spanish_label" msgid="7091555148131908240">"স্পেনিশ্ব"</string>
+    <string name="keyboard_layout_swiss_french_label" msgid="4659191025396371684">"ছুইছ ফৰাচী"</string>
+    <string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"ছুইছ জাৰ্মান"</string>
+    <string name="keyboard_layout_belgian" msgid="2011984572838651558">"বেলজিয়ান"</string>
+    <string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"বুলগেৰিয়ান"</string>
+    <string name="keyboard_layout_italian" msgid="6497079660449781213">"ইটালিয়ান"</string>
+    <string name="keyboard_layout_danish" msgid="8036432066627127851">"ডেনিশ্ব"</string>
+    <string name="keyboard_layout_norwegian" msgid="9090097917011040937">"ন\'ৰৱেয়ান"</string>
+    <string name="keyboard_layout_swedish" msgid="732959109088479351">"ছুইডিশ্ব"</string>
+    <string name="keyboard_layout_finnish" msgid="5585659438924315466">"ফিনিশ্ব"</string>
+    <string name="keyboard_layout_croatian" msgid="4172229471079281138">"ক্ৰ\'ৱেশ্বিয়ান"</string>
+    <string name="keyboard_layout_czech" msgid="1349256901452975343">"চ্চেক"</string>
+    <string name="keyboard_layout_estonian" msgid="8775830985185665274">"ইষ্ট\'নিয়া"</string>
+    <string name="keyboard_layout_hungarian" msgid="4154963661406035109">"হাংগেৰিয়ান"</string>
+    <string name="keyboard_layout_icelandic" msgid="5836645650912489642">"আইচলেণ্ডিক"</string>
+    <string name="keyboard_layout_brazilian" msgid="5117896443147781939">"ব্ৰাজিলিয়ান"</string>
+    <string name="keyboard_layout_portuguese" msgid="2888198587329660305">"পৰ্টুগীজ"</string>
+    <string name="keyboard_layout_slovak" msgid="2469379934672837296">"শ্ল\'ভাক"</string>
+    <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"শ্ল\'ভেনিয়া"</string>
+    <string name="keyboard_layout_turkish" msgid="7736163250907964898">"তুৰ্কী"</string>
+    <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ইউক্ৰেনিয়ান"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"আৰবী"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"গ্ৰীক"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"হিব্ৰু"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"লিথুৱানিয়ান"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"স্পেনিশ্ব (লেটিন)"</string>
+    <string name="keyboard_layout_latvian" msgid="4405417142306250595">"লাটভিয়ান"</string>
+    <!-- no translation found for keyboard_layout_persian (3920643161015888527) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_azerbaijani (7315895417176467567) -->
+    <skip />
+</resources>
diff --git a/packages/InputDevices/res/values-or/strings.xml b/packages/InputDevices/res/values-or/strings.xml
new file mode 100644
index 0000000..2b982da
--- /dev/null
+++ b/packages/InputDevices/res/values-or/strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label" msgid="8016145283189546017">"ଇନପୁଟ୍‌ ଡିଭାଇସ୍"</string>
+    <string name="keyboard_layouts_label" msgid="6688773268302087545">"Android କୀ’ବୋର୍ଡ"</string>
+    <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"ଇଂରାଜୀ (ୟୁକେ)"</string>
+    <string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"ଇଂରାଜୀ (ୟୁଏସ୍‍)"</string>
+    <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"ଇଂରାଜୀ (ୟୁଏସ୍‍), ଇଣ୍ଟରନେସନାଲ୍‍ ଷ୍ଟାଇଲ୍‍"</string>
+    <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"ଇଂରାଜୀ (ୟୁଏସ୍‍), କୋଲେମକ୍‍ ଷ୍ଟାଇଲ୍‍"</string>
+    <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"ଇଂରାଜୀ (ୟୁଏସ୍‍), ଡଭୋରାକ୍‌ ଷ୍ଟାଇଲ୍‍"</string>
+    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
+    <skip />
+    <string name="keyboard_layout_german_label" msgid="8451565865467909999">"ଜର୍ମାନ୍‌"</string>
+    <string name="keyboard_layout_french_label" msgid="813450119589383723">"ଫ୍ରେଞ୍ଚ"</string>
+    <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"ଫ୍ରେଞ୍ଚ (କାନାଡ଼ା)"</string>
+    <string name="keyboard_layout_russian_label" msgid="8724879775815042968">"ଋଷିଆ‍ନ୍‍"</string>
+    <string name="keyboard_layout_russian_mac_label" msgid="3795866869038264796">"ଋଷିଆନ୍‍, ମ୍ୟାକ୍‍ ଷ୍ଟାଇଲ୍‍"</string>
+    <string name="keyboard_layout_spanish_label" msgid="7091555148131908240">"ସ୍ପାନିଶ୍‍"</string>
+    <string name="keyboard_layout_swiss_french_label" msgid="4659191025396371684">"ସୁଇସ୍ ଫ୍ରେଞ୍ଚ"</string>
+    <string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"ସୁଇସ୍ ଜର୍ମାନ୍‍"</string>
+    <string name="keyboard_layout_belgian" msgid="2011984572838651558">"ବେଲ୍‍ଜିଆନ୍‍"</string>
+    <string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"ବୁଲଗାରିଆନ୍‍"</string>
+    <string name="keyboard_layout_italian" msgid="6497079660449781213">"ଇଟାଲିୟାନ୍‌"</string>
+    <string name="keyboard_layout_danish" msgid="8036432066627127851">"ଡାନିଶ୍‍"</string>
+    <string name="keyboard_layout_norwegian" msgid="9090097917011040937">"ନରୱେଜିଆନ୍"</string>
+    <string name="keyboard_layout_swedish" msgid="732959109088479351">"ସ୍ଵେଡିଶ୍‌"</string>
+    <string name="keyboard_layout_finnish" msgid="5585659438924315466">"ଫିନ୍ନିଶ୍‍"</string>
+    <string name="keyboard_layout_croatian" msgid="4172229471079281138">"କ୍ରୋଆଶିଆନ୍"</string>
+    <string name="keyboard_layout_czech" msgid="1349256901452975343">"ଚେକ୍"</string>
+    <string name="keyboard_layout_estonian" msgid="8775830985185665274">"ଇଷ୍ଟୋନିଆନ୍"</string>
+    <string name="keyboard_layout_hungarian" msgid="4154963661406035109">"ହଙ୍ଗେରିଆନ୍"</string>
+    <string name="keyboard_layout_icelandic" msgid="5836645650912489642">"ଆଇସଲାଣ୍ଡିକ୍"</string>
+    <string name="keyboard_layout_brazilian" msgid="5117896443147781939">"ବ୍ରାଜିଲିୟାନ୍"</string>
+    <string name="keyboard_layout_portuguese" msgid="2888198587329660305">"ପର୍ତ୍ତୁଗୀଜ୍"</string>
+    <string name="keyboard_layout_slovak" msgid="2469379934672837296">"ସ୍ଲୋଭାକ୍"</string>
+    <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"ସ୍ଲୋଭେନିଆନ୍"</string>
+    <string name="keyboard_layout_turkish" msgid="7736163250907964898">"ତୁର୍କିସ୍"</string>
+    <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ୟୁକ୍ରାନିଆନ୍"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"ଆରବିକ୍‍"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"ଗ୍ରୀକ୍"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"ହିବ୍ର୍ୟୁ"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"ଲିଥୁଆନିଆନ୍"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"ସ୍ପାନିଶ୍‍ (ଲାଟିନ୍‌)"</string>
+    <string name="keyboard_layout_latvian" msgid="4405417142306250595">"ଲାଟିଭିଆନ୍‍"</string>
+    <!-- no translation found for keyboard_layout_persian (3920643161015888527) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_azerbaijani (7315895417176467567) -->
+    <skip />
+</resources>
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index d919d6a..d284bf9 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -145,6 +145,8 @@
         android:name="android.permission.MANAGE_WIFI_WHEN_PERMISSION_REVIEW_REQUIRED" />
     <uses-permission android:name="android.permission.WATCH_APPOPS" />
 
+    <uses-permission android:name="android.permission.CONTROL_KEYGUARD" />
+
     <application android:label="@string/app_label"
                  android:defaultToDeviceProtectedStorage="true"
                  android:directBootAware="true">
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
index f1a5ca9..474fc90 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
@@ -197,16 +197,6 @@
         return false;
     }
 
-    @Override
-    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
-        if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
-            event.getText().add(mSecurityContainer.getCurrentSecurityModeContentDescription());
-            return true;
-        } else {
-            return super.dispatchPopulateAccessibilityEvent(event);
-        }
-    }
-
     protected KeyguardSecurityContainer getSecurityContainer() {
         return mSecurityContainer;
     }
@@ -255,6 +245,10 @@
         }
     }
 
+    public CharSequence getAccessibilityTitleForCurrentMode() {
+        return mSecurityContainer.getTitle();
+    }
+
     public void userActivity() {
         if (mViewMediatorCallback != null) {
             mViewMediatorCallback.userActivity();
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index ff5f5e7..75c52d8 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -361,4 +361,10 @@
         }
         return false;
     }
+
+    @Override
+    public CharSequence getTitle() {
+        return getContext().getString(
+                com.android.internal.R.string.keyguard_accessibility_password_unlock);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
index cb066a1..651831e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
@@ -491,4 +491,10 @@
     public boolean hasOverlappingRendering() {
         return false;
     }
+
+    @Override
+    public CharSequence getTitle() {
+        return getContext().getString(
+                com.android.internal.R.string.keyguard_accessibility_pattern_unlock);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
index 6539ccf..1d3f9a1 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -252,4 +252,10 @@
         }
         return false;
     }
+
+    @Override
+    public CharSequence getTitle() {
+        return getContext().getString(
+                com.android.internal.R.string.keyguard_accessibility_pin_unlock);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 8dc4609..c3413d9 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -119,19 +119,8 @@
         return false;
     }
 
-    public void announceCurrentSecurityMethod() {
-        View v = (View) getSecurityView(mCurrentSecuritySelection);
-        if (v != null) {
-            v.announceForAccessibility(v.getContentDescription());
-        }
-    }
-
-    public CharSequence getCurrentSecurityModeContentDescription() {
-        View v = (View) getSecurityView(mCurrentSecuritySelection);
-        if (v != null) {
-            return v.getContentDescription();
-        }
-        return "";
+    public CharSequence getTitle() {
+        return mSecurityViewFlipper.getTitle();
     }
 
     private KeyguardSecurityView getSecurityView(SecurityMode securityMode) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
index 360dba3..6e445ff 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
@@ -127,4 +127,12 @@
      *         animation started and {@code finishRunnable} will not be run
      */
     boolean startDisappearAnimation(Runnable finishRunnable);
+
+    /**
+     * The localized name of the security view, provided to accessibility. This may be the content
+     * description, but content descriptions have other implications, so the title is kept separate.
+     *
+     * @return The View's title.
+     */
+    CharSequence getTitle();
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
index a2ff8f7..3aede56 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
@@ -173,6 +173,15 @@
     }
 
     @Override
+    public CharSequence getTitle() {
+        KeyguardSecurityView ksv = getSecurityView();
+        if (ksv != null) {
+            return ksv.getTitle();
+        }
+        return "";
+    }
+
+    @Override
     protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
         return p instanceof LayoutParams;
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
index 703b205..c71c433 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
@@ -390,5 +390,11 @@
     public boolean startDisappearAnimation(Runnable finishRunnable) {
         return false;
     }
+
+    @Override
+    public CharSequence getTitle() {
+        return getContext().getString(
+                com.android.internal.R.string.keyguard_accessibility_sim_pin_unlock);
+    }
 }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
index 347c979..1b61568 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
@@ -460,6 +460,12 @@
     public boolean startDisappearAnimation(Runnable finishRunnable) {
         return false;
     }
+
+    @Override
+    public CharSequence getTitle() {
+        return getContext().getString(
+                com.android.internal.R.string.keyguard_accessibility_sim_puk_unlock);
+    }
 }
 
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 699e8cf..380c08e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -152,7 +152,6 @@
                 mKeyguardView.requestLayout();
             }
             mShowingSoon = false;
-            mKeyguardView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
         }
     };
 
@@ -264,6 +263,7 @@
         mStatusBarHeight = mRoot.getResources().getDimensionPixelOffset(
                 com.android.systemui.R.dimen.status_bar_height);
         mRoot.setVisibility(View.INVISIBLE);
+        mRoot.setAccessibilityPaneTitle(mKeyguardView.getAccessibilityTitleForCurrentMode());
 
         final WindowInsets rootInsets = mRoot.getRootWindowInsets();
         if (rootInsets != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index dc400e6..e86d88d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -580,8 +580,7 @@
 
     private boolean shouldDisableNavbarGestures() {
         return !mStatusBar.isDeviceProvisioned()
-                || (mDisabledFlags1 & StatusBarManager.DISABLE_SEARCH) != 0
-                || mNavigationBarView.getRecentsButton().getVisibility() != View.VISIBLE;
+                || (mDisabledFlags1 & StatusBarManager.DISABLE_SEARCH) != 0;
     }
 
     private void repositionNavigationBar() {
@@ -600,13 +599,10 @@
 
         // Change the cancel pin gesture to home and back if recents button is invisible
         boolean recentsVisible = mNavigationBarView.isRecentsButtonVisible();
-        ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
         ButtonDispatcher backButton = mNavigationBarView.getBackButton();
         if (recentsVisible) {
-            homeButton.setOnLongClickListener(this::onHomeLongClick);
             backButton.setOnLongClickListener(this::onLongPressBackRecents);
         } else {
-            homeButton.setOnLongClickListener(this::onLongPressBackHome);
             backButton.setOnLongClickListener(this::onLongPressBackHome);
         }
     }
@@ -629,6 +625,7 @@
 
         ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
         homeButton.setOnTouchListener(this::onHomeTouch);
+        homeButton.setOnLongClickListener(this::onHomeLongClick);
 
         ButtonDispatcher accessibilityButton = mNavigationBarView.getAccessibilityButton();
         accessibilityButton.setOnClickListener(this::onAccessibilityClick);
@@ -681,6 +678,9 @@
 
     @VisibleForTesting
     boolean onHomeLongClick(View v) {
+        if (!mNavigationBarView.isRecentsButtonVisible() && mNavigationBarView.inScreenPinning()) {
+            return onLongPressBackHome(v);
+        }
         if (shouldDisableNavbarGestures()) {
             return false;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
index dd4d1f6..b82b0ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
@@ -380,7 +380,7 @@
     }
 
     private void startQuickScrub() {
-        if (!mQuickScrubActive) {
+        if (!mQuickScrubActive && mDraggingActive) {
             mQuickScrubActive = true;
             mLightTrackColor = mContext.getColor(R.color.quick_step_track_background_light);
             mDarkTrackColor = mContext.getColor(R.color.quick_step_track_background_dark);
@@ -394,6 +394,9 @@
             } catch (RemoteException e) {
                 Log.e(TAG, "Failed to send start of quick scrub.", e);
             }
+        } else {
+            // After long press do not allow quick scrub/switch
+            mTouchDownX = -1;
         }
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
index fc043c5..944e888 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
@@ -26,6 +26,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.res.Resources;
+import android.support.test.filters.FlakyTest;
 import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -76,6 +77,7 @@
         mSpacing = res.getDimensionPixelSize(R.dimen.smart_reply_button_spacing);
     }
 
+    @FlakyTest
     @Test
     public void testSendSmartReply_intentContainsResultsAndSource() throws InterruptedException {
         setRepliesFromRemoteInput(TEST_CHOICES);
@@ -180,6 +182,7 @@
         assertEqualLayouts(expectedView.getChildAt(2), mView.getChildAt(2));
     }
 
+    @FlakyTest
     @Test
     public void testMeasure_choiceWithThreeLines() {
         final CharSequence[] choices = new CharSequence[]{"Hi", "Hello\nevery\nbody", "Bye"};
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 32f03b3..bcfe1b6 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -76,6 +76,7 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.TimeUtils;
+import android.view.KeyEvent;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillManager;
 import android.view.autofill.AutofillValue;
@@ -812,6 +813,27 @@
         }
     }
 
+    @Override
+    public void dispatchUnhandledKey(AutofillId id, KeyEvent keyEvent) {
+        synchronized (mLock) {
+            if (mDestroyed) {
+                Slog.w(TAG, "Call to Session#dispatchUnhandledKey() rejected - session: "
+                        + id + " destroyed");
+                return;
+            }
+            if (id.equals(mCurrentViewId)) {
+                try {
+                    mClient.dispatchUnhandledKey(this.id, id, keyEvent);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Error requesting to dispatch unhandled key", e);
+                }
+            } else {
+                Slog.w(TAG, "Do not dispatch unhandled key on " + id
+                        + " as it is not the current view (" + mCurrentViewId + ") anymore");
+            }
+        }
+    }
+
     // AutoFillUiCallback
     @Override
     public void requestHideFillUi(AutofillId id) {
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index dc36518..e28a204 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -34,6 +34,7 @@
 import android.service.autofill.ValueFinder;
 import android.text.TextUtils;
 import android.util.Slog;
+import android.view.KeyEvent;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillManager;
 import android.view.autofill.IAutofillWindowPresenter;
@@ -78,6 +79,7 @@
                 IAutofillWindowPresenter presenter);
         void requestHideFillUi(AutofillId id);
         void startIntentSender(IntentSender intentSender);
+        void dispatchUnhandledKey(AutofillId id, KeyEvent keyEvent);
     }
 
     public AutoFillUI(@NonNull Context context) {
@@ -240,6 +242,13 @@
                         mCallback.startIntentSender(intentSender);
                     }
                 }
+
+                @Override
+                public void dispatchUnhandledKey(KeyEvent keyEvent) {
+                    if (mCallback != null) {
+                        mCallback.dispatchUnhandledKey(focusedId, keyEvent);
+                    }
+                }
             });
         });
     }
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index d64244d..7278e83 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -18,6 +18,7 @@
 import static com.android.server.autofill.Helper.sDebug;
 import static com.android.server.autofill.Helper.sVerbose;
 
+import android.annotation.AttrRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.PendingIntent;
@@ -31,8 +32,10 @@
 import android.service.autofill.Dataset.DatasetFieldFilter;
 import android.service.autofill.FillResponse;
 import android.text.TextUtils;
+import android.util.AttributeSet;
 import android.util.Slog;
 import android.util.TypedValue;
+import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
@@ -47,6 +50,7 @@
 import android.widget.BaseAdapter;
 import android.widget.Filter;
 import android.widget.Filterable;
+import android.widget.FrameLayout;
 import android.widget.ListView;
 import android.widget.RemoteViews;
 
@@ -69,6 +73,28 @@
 
     private static final TypedValue sTempTypedValue = new TypedValue();
 
+    public static final class AutofillFrameLayout extends FrameLayout {
+
+        OnKeyListener mUnhandledListener;
+
+        public AutofillFrameLayout(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+
+        public AutofillFrameLayout(Context context, AttributeSet attrs, @AttrRes int defStyleAttr) {
+            super(context, attrs, defStyleAttr);
+        }
+
+        @Override
+        public boolean dispatchKeyEvent(KeyEvent event) {
+            boolean handled = super.dispatchKeyEvent(event);
+            if (!handled) {
+                handled = mUnhandledListener.onKey(this, event.getKeyCode(), event);
+            }
+            return handled;
+        }
+    }
+
     interface Callback {
         void onResponsePicked(@NonNull FillResponse response);
         void onDatasetPicked(@NonNull Dataset dataset);
@@ -78,6 +104,7 @@
                 IAutofillWindowPresenter windowPresenter);
         void requestHideFillUi();
         void startIntentSender(IntentSender intentSender);
+        void dispatchUnhandledKey(KeyEvent keyEvent);
     }
 
     private final @NonNull Point mTempPoint = new Point();
@@ -122,6 +149,31 @@
                 mFullScreen ? R.layout.autofill_dataset_picker_fullscreen
                         : R.layout.autofill_dataset_picker, null);
 
+        // if autofill ui is not fullscreen, send unhandled keyevent to app window.
+        if (!mFullScreen) {
+            if (decor instanceof AutofillFrameLayout) {
+                ((AutofillFrameLayout) decor).mUnhandledListener =
+                        (View view, int keyCode, KeyEvent event) -> {
+                            switch (keyCode) {
+                                case KeyEvent.KEYCODE_BACK:
+                                case KeyEvent.KEYCODE_ESCAPE:
+                                case KeyEvent.KEYCODE_ENTER:
+                                case KeyEvent.KEYCODE_DPAD_CENTER:
+                                case KeyEvent.KEYCODE_DPAD_LEFT:
+                                case KeyEvent.KEYCODE_DPAD_UP:
+                                case KeyEvent.KEYCODE_DPAD_RIGHT:
+                                case KeyEvent.KEYCODE_DPAD_DOWN:
+                                    return false;
+                                default:
+                                    mCallback.dispatchUnhandledKey(event);
+                                    return true;
+                            }
+                        };
+            } else {
+                Slog.wtf(TAG, "Unable to send unhandled key");
+            }
+        }
+
         final RemoteViews.OnClickHandler interceptionHandler = new RemoteViews.OnClickHandler() {
             @Override
             public boolean onClickHandler(View view, PendingIntent pendingIntent,
diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java
index d3a97b3..1f370a5 100644
--- a/services/net/java/android/net/ip/IpClient.java
+++ b/services/net/java/android/net/ip/IpClient.java
@@ -72,6 +72,7 @@
 import java.util.List;
 import java.util.Set;
 import java.util.StringJoiner;
+import java.util.concurrent.CountDownLatch;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
@@ -100,6 +101,11 @@
 
     /**
      * Callbacks for handling IpClient events.
+     *
+     * These methods are called by IpClient on its own thread. Implementations
+     * of this class MUST NOT carry out long-running computations or hold locks
+     * for which there might be contention with other code calling public
+     * methods of the same IpClient instance.
      */
     public static class Callback {
         // In order to receive onPreDhcpAction(), call #withPreDhcpAction()
@@ -545,6 +551,7 @@
     private final String mClatInterfaceName;
     @VisibleForTesting
     protected final Callback mCallback;
+    private final CountDownLatch mShutdownLatch;
     private final INetworkManagementService mNwService;
     private final NetlinkTracker mNetlinkTracker;
     private final WakeupMessage mProvisioningTimeoutAlarm;
@@ -597,6 +604,7 @@
         mInterfaceName = ifName;
         mClatInterfaceName = CLAT_PREFIX + ifName;
         mCallback = new LoggingCallbackWrapper(callback);
+        mShutdownLatch = new CountDownLatch(1);
         mNwService = nwService;
 
         mLog = new SharedLog(MAX_LOG_RECORDS, mTag);
@@ -704,6 +712,7 @@
     @Override
     protected void onQuitting() {
         mCallback.onQuit();
+        mShutdownLatch.countDown();
     }
 
     // Shut down this IpClient instance altogether.
@@ -712,6 +721,17 @@
         sendMessage(CMD_TERMINATE_AFTER_STOP);
     }
 
+    // In order to avoid deadlock, this method MUST NOT be called on the
+    // IpClient instance's thread. This prohibition includes code executed by
+    // when methods on the passed-in IpClient.Callback instance are called.
+    public void awaitShutdown() {
+        try {
+            mShutdownLatch.await();
+        } catch (InterruptedException e) {
+            mLog.e("Interrupted while awaiting shutdown: " + e);
+        }
+    }
+
     public static ProvisioningConfiguration.Builder buildProvisioningConfiguration() {
         return new ProvisioningConfiguration.Builder();
     }