Merge "media: don't expose private keys in MediaFormat" into nyc-dev
diff --git a/api/current.txt b/api/current.txt
index 9e0af76..50e0de4 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3442,7 +3442,7 @@
     method public android.view.View getCurrentFocus();
     method public android.app.FragmentManager getFragmentManager();
     method public android.content.Intent getIntent();
-    method public deprecated java.lang.Object getLastNonConfigurationInstance();
+    method public java.lang.Object getLastNonConfigurationInstance();
     method public android.view.LayoutInflater getLayoutInflater();
     method public android.app.LoaderManager getLoaderManager();
     method public java.lang.String getLocalClassName();
@@ -3543,7 +3543,7 @@
     method protected void onRestoreInstanceState(android.os.Bundle);
     method public void onRestoreInstanceState(android.os.Bundle, android.os.PersistableBundle);
     method protected void onResume();
-    method public deprecated java.lang.Object onRetainNonConfigurationInstance();
+    method public java.lang.Object onRetainNonConfigurationInstance();
     method protected void onSaveInstanceState(android.os.Bundle);
     method public void onSaveInstanceState(android.os.Bundle, android.os.PersistableBundle);
     method public boolean onSearchRequested(android.view.SearchEvent);
@@ -9454,6 +9454,7 @@
     method public int getShortcutIconResId(android.content.pm.ShortcutInfo, android.os.UserHandle);
     method public java.util.List<android.content.pm.ShortcutInfo> getShortcutInfo(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
     method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle);
+    method public boolean hasShortcutHostPermission();
     method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
     method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle);
     method public void pinShortcuts(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
@@ -10116,7 +10117,6 @@
     method public static deprecated android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public int describeContents();
-    method public int getChangingConfigurations();
     method public int getColorForState(int[], int);
     method public int getDefaultColor();
     method public boolean isOpaque();
@@ -10128,6 +10128,7 @@
 
   public abstract class ComplexColor {
     ctor public ComplexColor();
+    method public int getChangingConfigurations();
     method public abstract int getDefaultColor();
     method public boolean isStateful();
   }
@@ -13035,9 +13036,9 @@
     method public void setPaddingMode(int);
     method public void setPaddingRelative(int, int, int, int);
     method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+    field public static final int INSET_UNDEFINED = -2147483648; // 0x80000000
     field public static final int PADDING_MODE_NEST = 0; // 0x0
     field public static final int PADDING_MODE_STACK = 1; // 0x1
-    field public static final int UNDEFINED_INSET = -2147483648; // 0x80000000
   }
 
   public class LevelListDrawable extends android.graphics.drawable.DrawableContainer {
@@ -30762,6 +30763,7 @@
   public static class CallLog.Calls implements android.provider.BaseColumns {
     ctor public CallLog.Calls();
     method public static java.lang.String getLastOutgoingCall(android.content.Context);
+    field public static final int ANSWERED_EXTERNALLY_TYPE = 7; // 0x7
     field public static final int BLOCKED_TYPE = 6; // 0x6
     field public static final java.lang.String CACHED_FORMATTED_NUMBER = "formatted_number";
     field public static final java.lang.String CACHED_LOOKUP_URI = "lookup_uri";
@@ -30784,6 +30786,7 @@
     field public static final java.lang.String DURATION = "duration";
     field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.CALL_TYPE_FILTER";
     field public static final java.lang.String FEATURES = "features";
+    field public static final int FEATURES_PULLED_EXTERNALLY = 2; // 0x2
     field public static final int FEATURES_VIDEO = 1; // 0x1
     field public static final java.lang.String GEOCODED_LOCATION = "geocoded_location";
     field public static final int INCOMING_TYPE = 1; // 0x1
@@ -36058,9 +36061,11 @@
     method public void phoneAccountSelected(android.telecom.PhoneAccountHandle, boolean);
     method public void playDtmfTone(char);
     method public void postDialContinue(boolean);
+    method public void pullExternalCall();
     method public void registerCallback(android.telecom.Call.Callback);
     method public void registerCallback(android.telecom.Call.Callback, android.os.Handler);
     method public void reject(boolean, java.lang.String);
+    method public void sendCallEvent(java.lang.String, android.os.Bundle);
     method public void splitFromConference();
     method public void stopDtmfTone();
     method public void swapConference();
@@ -36074,6 +36079,7 @@
     field public static final int STATE_DISCONNECTING = 10; // 0xa
     field public static final int STATE_HOLDING = 3; // 0x3
     field public static final int STATE_NEW = 0; // 0x0
+    field public static final int STATE_PULLING_CALL = 11; // 0xb
     field public static final int STATE_RINGING = 2; // 0x2
     field public static final int STATE_SELECT_PHONE_ACCOUNT = 8; // 0x8
   }
@@ -36084,6 +36090,7 @@
     method public void onCannedTextResponsesLoaded(android.telecom.Call, java.util.List<java.lang.String>);
     method public void onChildrenChanged(android.telecom.Call, java.util.List<android.telecom.Call>);
     method public void onConferenceableCallsChanged(android.telecom.Call, java.util.List<android.telecom.Call>);
+    method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle);
     method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details);
     method public void onParentChanged(android.telecom.Call, android.telecom.Call);
     method public void onPostDialWait(android.telecom.Call, java.lang.String);
@@ -36114,6 +36121,7 @@
     method public static java.lang.String propertiesToString(int);
     field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 4194304; // 0x400000
     field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
+    field public static final int CAPABILITY_CAN_PULL_CALL = 8388608; // 0x800000
     field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
     field public static final int CAPABILITY_HOLD = 1; // 0x1
     field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
@@ -36133,6 +36141,7 @@
     field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 4; // 0x4
     field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2
     field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10
+    field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40
     field public static final int PROPERTY_WIFI = 8; // 0x8
     field public static final int PROPERTY_WORK_CALL = 32; // 0x20
   }
@@ -36247,15 +36256,19 @@
     method public void onAnswer(int);
     method public void onAnswer();
     method public void onCallAudioStateChanged(android.telecom.CallAudioState);
+    method public void onCallEvent(java.lang.String, android.os.Bundle);
     method public void onDisconnect();
     method public void onHold();
     method public void onPlayDtmfTone(char);
     method public void onPostDialContinue(boolean);
+    method public void onPullExternalCall();
     method public void onReject();
+    method public void onReject(java.lang.String);
     method public void onSeparate();
     method public void onStateChanged(int);
     method public void onStopDtmfTone();
     method public void onUnhold();
+    method public void sendConnectionEvent(java.lang.String, android.os.Bundle);
     method public final void setActive();
     method public final void setAddress(android.net.Uri, int);
     method public final void setAudioModeIsVoip(boolean);
@@ -36279,9 +36292,12 @@
     method public static java.lang.String stateToString(int);
     field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 8388608; // 0x800000
     field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
+    field public static final int CAPABILITY_CAN_PULL_CALL = 33554432; // 0x2000000
+    field public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 4194304; // 0x400000
     field public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 524288; // 0x80000
     field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
     field public static final int CAPABILITY_HOLD = 1; // 0x1
+    field public static final int CAPABILITY_IS_EXTERNAL_CALL = 16777216; // 0x1000000
     field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
     field public static final int CAPABILITY_MERGE_CONFERENCE = 4; // 0x4
     field public static final int CAPABILITY_MUTE = 64; // 0x40
@@ -36295,6 +36311,7 @@
     field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 2048; // 0x800
     field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2
     field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8
+    field public static final java.lang.String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED";
     field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
     field public static final java.lang.String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS";
     field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER";
@@ -36304,6 +36321,7 @@
     field public static final int STATE_HOLDING = 5; // 0x5
     field public static final int STATE_INITIALIZING = 0; // 0x0
     field public static final int STATE_NEW = 1; // 0x1
+    field public static final int STATE_PULLING_CALL = 7; // 0x7
     field public static final int STATE_RINGING = 2; // 0x2
   }
 
@@ -36381,7 +36399,9 @@
     method public java.lang.String getReason();
     method public int getTone();
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final int ANSWERED_ELSEWHERE = 11; // 0xb
     field public static final int BUSY = 7; // 0x7
+    field public static final int CALL_PULLED = 12; // 0xc
     field public static final int CANCELED = 4; // 0x4
     field public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10; // 0xa
     field public static final android.os.Parcelable.Creator<android.telecom.DisconnectCause> CREATOR;
@@ -36417,6 +36437,7 @@
     method public void onCallAudioStateChanged(android.telecom.CallAudioState);
     method public void onCallRemoved(android.telecom.Call);
     method public void onCanAddCallChanged(boolean);
+    method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle);
     method public void onSilenceRinger();
     method public final void setAudioRoute(int);
     method public final void setMuted(boolean);
@@ -36567,6 +36588,7 @@
     method public boolean isVoipAudioMode();
     method public void playDtmfTone(char);
     method public void postDialContinue(boolean);
+    method public void pullExternalCall();
     method public void registerCallback(android.telecom.RemoteConnection.Callback);
     method public void registerCallback(android.telecom.RemoteConnection.Callback, android.os.Handler);
     method public void reject();
@@ -36583,6 +36605,7 @@
     method public void onConferenceChanged(android.telecom.RemoteConnection, android.telecom.RemoteConference);
     method public void onConferenceableConnectionsChanged(android.telecom.RemoteConnection, java.util.List<android.telecom.RemoteConnection>);
     method public void onConnectionCapabilitiesChanged(android.telecom.RemoteConnection, int);
+    method public void onConnectionEvent(android.telecom.RemoteConnection, java.lang.String, android.os.Bundle);
     method public void onDestroyed(android.telecom.RemoteConnection);
     method public void onDisconnected(android.telecom.RemoteConnection, android.telecom.DisconnectCause);
     method public void onExtrasChanged(android.telecom.RemoteConnection, android.os.Bundle);
@@ -36680,6 +36703,7 @@
     field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
     field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
     field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
+    field public static final java.lang.String METADATA_INCLUDE_EXTERNAL_CALLS = "android.telecom.INCLUDE_EXTERNAL_CALLS";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI";
     field public static final int PRESENTATION_ALLOWED = 1; // 0x1
@@ -57344,6 +57368,7 @@
     method public void ensureCapacity(int);
     method public void forEach(java.util.function.Consumer<? super E>);
     method public E get(int);
+    method public boolean removeIf(java.util.function.Predicate<? super E>);
     method public int size();
     method public java.util.Spliterator<E> spliterator();
     method public void trimToSize();
@@ -57428,6 +57453,24 @@
     method public static int hashCode(float[]);
     method public static int hashCode(double[]);
     method public static int hashCode(java.lang.Object[]);
+    method public static void parallelSort(byte[]);
+    method public static void parallelSort(byte[], int, int);
+    method public static void parallelSort(char[]);
+    method public static void parallelSort(char[], int, int);
+    method public static void parallelSort(short[]);
+    method public static void parallelSort(short[], int, int);
+    method public static void parallelSort(int[]);
+    method public static void parallelSort(int[], int, int);
+    method public static void parallelSort(long[]);
+    method public static void parallelSort(long[], int, int);
+    method public static void parallelSort(float[]);
+    method public static void parallelSort(float[], int, int);
+    method public static void parallelSort(double[]);
+    method public static void parallelSort(double[], int, int);
+    method public static void parallelSort(T[]);
+    method public static void parallelSort(T[], int, int);
+    method public static void parallelSort(T[], java.util.Comparator<? super T>);
+    method public static void parallelSort(T[], int, int, java.util.Comparator<? super T>);
     method public static void sort(int[]);
     method public static void sort(int[], int, int);
     method public static void sort(long[]);
@@ -57615,6 +57658,7 @@
     method public abstract java.util.Iterator<E> iterator();
     method public abstract boolean remove(java.lang.Object);
     method public abstract boolean removeAll(java.util.Collection<?>);
+    method public default boolean removeIf(java.util.function.Predicate<? super E>);
     method public abstract boolean retainAll(java.util.Collection<?>);
     method public abstract int size();
     method public abstract java.lang.Object[] toArray();
@@ -58248,18 +58292,28 @@
 
   public abstract interface Map {
     method public abstract void clear();
+    method public default V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public default V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
+    method public default V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public abstract boolean containsKey(java.lang.Object);
     method public abstract boolean containsValue(java.lang.Object);
     method public abstract java.util.Set<java.util.Map.Entry<K, V>> entrySet();
     method public abstract boolean equals(java.lang.Object);
     method public default void forEach(java.util.function.BiConsumer<? super K, ? super V>);
     method public abstract V get(java.lang.Object);
+    method public default V getOrDefault(java.lang.Object, V);
     method public abstract int hashCode();
     method public abstract boolean isEmpty();
     method public abstract java.util.Set<K> keySet();
+    method public default V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
     method public abstract V put(K, V);
     method public abstract void putAll(java.util.Map<? extends K, ? extends V>);
+    method public default V putIfAbsent(K, V);
     method public abstract V remove(java.lang.Object);
+    method public default boolean remove(java.lang.Object, java.lang.Object);
+    method public default boolean replace(K, V, V);
+    method public default V replace(K, V);
+    method public default void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public abstract int size();
     method public abstract java.util.Collection<V> values();
   }
@@ -58267,6 +58321,8 @@
   public static abstract interface Map.Entry {
     method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey();
     method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey(java.util.Comparator<? super K>);
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue();
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue(java.util.Comparator<? super V>);
     method public abstract boolean equals(java.lang.Object);
     method public abstract K getKey();
     method public abstract V getValue();
@@ -58997,6 +59053,7 @@
     method public synchronized void removeAllElements();
     method public synchronized boolean removeElement(java.lang.Object);
     method public synchronized void removeElementAt(int);
+    method public synchronized boolean removeIf(java.util.function.Predicate<? super E>);
     method public synchronized void setElementAt(E, int);
     method public synchronized void setSize(int);
     method public synchronized int size();
@@ -59048,6 +59105,7 @@
     method public void put(E) throws java.lang.InterruptedException;
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -59111,6 +59169,78 @@
     ctor public CancellationException(java.lang.String);
   }
 
+  public class CompletableFuture implements java.util.concurrent.CompletionStage java.util.concurrent.Future {
+    ctor public CompletableFuture();
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Void> allOf(java.util.concurrent.CompletableFuture<?>...);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Object> anyOf(java.util.concurrent.CompletableFuture<?>...);
+    method public java.util.concurrent.CompletableFuture<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
+    method public boolean cancel(boolean);
+    method public boolean complete(T);
+    method public boolean completeExceptionally(java.lang.Throwable);
+    method public static java.util.concurrent.CompletableFuture<U> completedFuture(U);
+    method public java.util.concurrent.CompletableFuture<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>);
+    method public T get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
+    method public T get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
+    method public T getNow(T);
+    method public int getNumberOfDependents();
+    method public java.util.concurrent.CompletableFuture<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
+    method public boolean isCancelled();
+    method public boolean isCompletedExceptionally();
+    method public boolean isDone();
+    method public T join();
+    method public void obtrudeException(java.lang.Throwable);
+    method public void obtrudeValue(T);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBoth(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEither(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable, java.util.concurrent.Executor);
+    method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>);
+    method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<U> thenApply(java.util.function.Function<? super T, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRun(java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<T> toCompletableFuture();
+    method public java.util.concurrent.CompletableFuture<T> whenComplete(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public java.util.concurrent.CompletableFuture<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public java.util.concurrent.CompletableFuture<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>, java.util.concurrent.Executor);
+  }
+
+  public static abstract interface CompletableFuture.AsynchronousCompletionTask {
+  }
+
+  public class CompletionException extends java.lang.RuntimeException {
+    ctor protected CompletionException();
+    ctor protected CompletionException(java.lang.String);
+    ctor public CompletionException(java.lang.String, java.lang.Throwable);
+    ctor public CompletionException(java.lang.Throwable);
+  }
+
   public abstract interface CompletionService {
     method public abstract java.util.concurrent.Future<V> poll();
     method public abstract java.util.concurrent.Future<V> poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
@@ -59119,20 +59249,130 @@
     method public abstract java.util.concurrent.Future<V> take() throws java.lang.InterruptedException;
   }
 
+  public abstract interface CompletionStage {
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>);
+    method public abstract java.util.concurrent.CompletionStage<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBoth(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEither(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<U> thenApply(java.util.function.Function<? super T, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRun(java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletableFuture<T> toCompletableFuture();
+    method public abstract java.util.concurrent.CompletionStage<T> whenComplete(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public abstract java.util.concurrent.CompletionStage<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public abstract java.util.concurrent.CompletionStage<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>, java.util.concurrent.Executor);
+  }
+
   public class ConcurrentHashMap extends java.util.AbstractMap implements java.util.concurrent.ConcurrentMap java.io.Serializable {
     ctor public ConcurrentHashMap();
     ctor public ConcurrentHashMap(int);
     ctor public ConcurrentHashMap(java.util.Map<? extends K, ? extends V>);
     ctor public ConcurrentHashMap(int, float);
     ctor public ConcurrentHashMap(int, float, int);
+    method public V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
+    method public V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public boolean contains(java.lang.Object);
     method public java.util.Enumeration<V> elements();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
+    method public void forEach(long, java.util.function.BiConsumer<? super K, ? super V>);
+    method public void forEach(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.Consumer<? super U>);
+    method public void forEachEntry(long, java.util.function.Consumer<? super java.util.Map.Entry<K, V>>);
+    method public void forEachEntry(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.Consumer<? super U>);
+    method public void forEachKey(long, java.util.function.Consumer<? super K>);
+    method public void forEachKey(long, java.util.function.Function<? super K, ? extends U>, java.util.function.Consumer<? super U>);
+    method public void forEachValue(long, java.util.function.Consumer<? super V>);
+    method public void forEachValue(long, java.util.function.Function<? super V, ? extends U>, java.util.function.Consumer<? super U>);
+    method public V getOrDefault(java.lang.Object, V);
+    method public java.util.concurrent.ConcurrentHashMap.KeySetView<K, V> keySet(V);
     method public java.util.Enumeration<K> keys();
+    method public long mappingCount();
+    method public V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
+    method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet();
+    method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet(int);
     method public V putIfAbsent(K, V);
+    method public U reduce(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public java.util.Map.Entry<K, V> reduceEntries(long, java.util.function.BiFunction<java.util.Map.Entry<K, V>, java.util.Map.Entry<K, V>, ? extends java.util.Map.Entry<K, V>>);
+    method public U reduceEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public double reduceEntriesToDouble(long, java.util.function.ToDoubleFunction<java.util.Map.Entry<K, V>>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceEntriesToInt(long, java.util.function.ToIntFunction<java.util.Map.Entry<K, V>>, int, java.util.function.IntBinaryOperator);
+    method public long reduceEntriesToLong(long, java.util.function.ToLongFunction<java.util.Map.Entry<K, V>>, long, java.util.function.LongBinaryOperator);
+    method public K reduceKeys(long, java.util.function.BiFunction<? super K, ? super K, ? extends K>);
+    method public U reduceKeys(long, java.util.function.Function<? super K, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public double reduceKeysToDouble(long, java.util.function.ToDoubleFunction<? super K>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceKeysToInt(long, java.util.function.ToIntFunction<? super K>, int, java.util.function.IntBinaryOperator);
+    method public long reduceKeysToLong(long, java.util.function.ToLongFunction<? super K>, long, java.util.function.LongBinaryOperator);
+    method public double reduceToDouble(long, java.util.function.ToDoubleBiFunction<? super K, ? super V>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceToInt(long, java.util.function.ToIntBiFunction<? super K, ? super V>, int, java.util.function.IntBinaryOperator);
+    method public long reduceToLong(long, java.util.function.ToLongBiFunction<? super K, ? super V>, long, java.util.function.LongBinaryOperator);
+    method public V reduceValues(long, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
+    method public U reduceValues(long, java.util.function.Function<? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public double reduceValuesToDouble(long, java.util.function.ToDoubleFunction<? super V>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceValuesToInt(long, java.util.function.ToIntFunction<? super V>, int, java.util.function.IntBinaryOperator);
+    method public long reduceValuesToLong(long, java.util.function.ToLongFunction<? super V>, long, java.util.function.LongBinaryOperator);
     method public boolean remove(java.lang.Object, java.lang.Object);
     method public boolean replace(K, V, V);
     method public V replace(K, V);
+    method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public U search(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>);
+    method public U searchEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>);
+    method public U searchKeys(long, java.util.function.Function<? super K, ? extends U>);
+    method public U searchValues(long, java.util.function.Function<? super V, ? extends U>);
+  }
+
+   static abstract class ConcurrentHashMap.CollectionView implements java.util.Collection java.io.Serializable {
+    method public final void clear();
+    method public abstract boolean contains(java.lang.Object);
+    method public final boolean containsAll(java.util.Collection<?>);
+    method public java.util.concurrent.ConcurrentHashMap<K, V> getMap();
+    method public final boolean isEmpty();
+    method public abstract java.util.Iterator<E> iterator();
+    method public abstract boolean remove(java.lang.Object);
+    method public final boolean removeAll(java.util.Collection<?>);
+    method public final boolean retainAll(java.util.Collection<?>);
+    method public final int size();
+    method public final java.lang.Object[] toArray();
+    method public final T[] toArray(T[]);
+    method public final java.lang.String toString();
+  }
+
+  public static class ConcurrentHashMap.KeySetView extends java.util.concurrent.ConcurrentHashMap.CollectionView implements java.io.Serializable java.util.Set {
+    method public boolean add(K);
+    method public boolean addAll(java.util.Collection<? extends K>);
+    method public boolean contains(java.lang.Object);
+    method public void forEach(java.util.function.Consumer<? super K>);
+    method public V getMappedValue();
+    method public java.util.Iterator<K> iterator();
+    method public boolean remove(java.lang.Object);
+    method public java.util.Spliterator<K> spliterator();
   }
 
   public class ConcurrentLinkedDeque extends java.util.AbstractCollection implements java.util.Deque java.io.Serializable {
@@ -59162,6 +59402,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class ConcurrentLinkedQueue extends java.util.AbstractQueue implements java.util.Queue java.io.Serializable {
@@ -59172,6 +59413,7 @@
     method public E peek();
     method public E poll();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public abstract interface ConcurrentMap implements java.util.Map {
@@ -59203,6 +59445,9 @@
     method public K ceilingKey(K);
     method public java.util.concurrent.ConcurrentSkipListMap<K, V> clone();
     method public java.util.Comparator<? super K> comparator();
+    method public V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
+    method public V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public java.util.NavigableSet<K> descendingKeySet();
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> descendingMap();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
@@ -59210,6 +59455,8 @@
     method public K firstKey();
     method public java.util.Map.Entry<K, V> floorEntry(K);
     method public K floorKey(K);
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
+    method public V getOrDefault(java.lang.Object, V);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K, boolean);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K);
     method public java.util.Map.Entry<K, V> higherEntry(K);
@@ -59218,6 +59465,7 @@
     method public K lastKey();
     method public java.util.Map.Entry<K, V> lowerEntry(K);
     method public K lowerKey(K);
+    method public V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
     method public java.util.NavigableSet<K> navigableKeySet();
     method public java.util.Map.Entry<K, V> pollFirstEntry();
     method public java.util.Map.Entry<K, V> pollLastEntry();
@@ -59225,6 +59473,7 @@
     method public boolean remove(java.lang.Object, java.lang.Object);
     method public boolean replace(K, V, V);
     method public V replace(K, V);
+    method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> subMap(K, boolean, K, boolean);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> subMap(K, K);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> tailMap(K, boolean);
@@ -59252,6 +59501,7 @@
     method public E pollFirst();
     method public E pollLast();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public java.util.NavigableSet<E> subSet(E, boolean, E, boolean);
     method public java.util.NavigableSet<E> subSet(E, E);
     method public java.util.NavigableSet<E> tailSet(E, boolean);
@@ -59262,31 +59512,34 @@
     ctor public CopyOnWriteArrayList();
     ctor public CopyOnWriteArrayList(java.util.Collection<? extends E>);
     ctor public CopyOnWriteArrayList(E[]);
-    method public synchronized boolean add(E);
-    method public synchronized void add(int, E);
-    method public synchronized boolean addAll(java.util.Collection<? extends E>);
-    method public synchronized boolean addAll(int, java.util.Collection<? extends E>);
-    method public synchronized int addAllAbsent(java.util.Collection<? extends E>);
-    method public synchronized boolean addIfAbsent(E);
-    method public synchronized void clear();
+    method public boolean add(E);
+    method public void add(int, E);
+    method public boolean addAll(java.util.Collection<? extends E>);
+    method public boolean addAll(int, java.util.Collection<? extends E>);
+    method public int addAllAbsent(java.util.Collection<? extends E>);
+    method public boolean addIfAbsent(E);
+    method public void clear();
     method public java.lang.Object clone();
     method public boolean contains(java.lang.Object);
     method public boolean containsAll(java.util.Collection<?>);
+    method public void forEach(java.util.function.Consumer<? super E>);
     method public E get(int);
-    method public int indexOf(E, int);
     method public int indexOf(java.lang.Object);
+    method public int indexOf(E, int);
     method public boolean isEmpty();
     method public java.util.Iterator<E> iterator();
-    method public int lastIndexOf(E, int);
     method public int lastIndexOf(java.lang.Object);
-    method public java.util.ListIterator<E> listIterator(int);
+    method public int lastIndexOf(E, int);
     method public java.util.ListIterator<E> listIterator();
-    method public synchronized E remove(int);
-    method public synchronized boolean remove(java.lang.Object);
-    method public synchronized boolean removeAll(java.util.Collection<?>);
-    method public synchronized boolean retainAll(java.util.Collection<?>);
-    method public synchronized E set(int, E);
+    method public java.util.ListIterator<E> listIterator(int);
+    method public E remove(int);
+    method public boolean remove(java.lang.Object);
+    method public boolean removeAll(java.util.Collection<?>);
+    method public void replaceAll(java.util.function.UnaryOperator<E>);
+    method public boolean retainAll(java.util.Collection<?>);
+    method public E set(int, E);
     method public int size();
+    method public void sort(java.util.Comparator<? super E>);
     method public java.util.List<E> subList(int, int);
     method public java.lang.Object[] toArray();
     method public T[] toArray(T[]);
@@ -59295,8 +59548,11 @@
   public class CopyOnWriteArraySet extends java.util.AbstractSet implements java.io.Serializable {
     ctor public CopyOnWriteArraySet();
     ctor public CopyOnWriteArraySet(java.util.Collection<? extends E>);
+    method public void forEach(java.util.function.Consumer<? super E>);
     method public java.util.Iterator<E> iterator();
+    method public boolean removeIf(java.util.function.Predicate<? super E>);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class CountDownLatch {
@@ -59307,6 +59563,32 @@
     method public long getCount();
   }
 
+  public abstract class CountedCompleter extends java.util.concurrent.ForkJoinTask {
+    ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>, int);
+    ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>);
+    ctor protected CountedCompleter();
+    method public final void addToPendingCount(int);
+    method public final boolean compareAndSetPendingCount(int, int);
+    method public void complete(T);
+    method public abstract void compute();
+    method public final int decrementPendingCountUnlessZero();
+    method protected final boolean exec();
+    method public final java.util.concurrent.CountedCompleter<?> firstComplete();
+    method public final java.util.concurrent.CountedCompleter<?> getCompleter();
+    method public final int getPendingCount();
+    method public T getRawResult();
+    method public final java.util.concurrent.CountedCompleter<?> getRoot();
+    method public final void helpComplete(int);
+    method public final java.util.concurrent.CountedCompleter<?> nextComplete();
+    method public void onCompletion(java.util.concurrent.CountedCompleter<?>);
+    method public boolean onExceptionalCompletion(java.lang.Throwable, java.util.concurrent.CountedCompleter<?>);
+    method public final void propagateCompletion();
+    method public final void quietlyCompleteRoot();
+    method public final void setPendingCount(int);
+    method protected void setRawResult(T);
+    method public final void tryComplete();
+  }
+
   public class CyclicBarrier {
     ctor public CyclicBarrier(int, java.lang.Runnable);
     ctor public CyclicBarrier(int);
@@ -59397,6 +59679,8 @@
     method public static java.util.concurrent.ExecutorService newSingleThreadExecutor(java.util.concurrent.ThreadFactory);
     method public static java.util.concurrent.ScheduledExecutorService newSingleThreadScheduledExecutor();
     method public static java.util.concurrent.ScheduledExecutorService newSingleThreadScheduledExecutor(java.util.concurrent.ThreadFactory);
+    method public static java.util.concurrent.ExecutorService newWorkStealingPool(int);
+    method public static java.util.concurrent.ExecutorService newWorkStealingPool();
     method public static java.util.concurrent.Callable<T> privilegedCallable(java.util.concurrent.Callable<T>);
     method public static java.util.concurrent.Callable<T> privilegedCallableUsingCurrentClassLoader(java.util.concurrent.Callable<T>);
     method public static java.util.concurrent.ThreadFactory privilegedThreadFactory();
@@ -59410,11 +59694,13 @@
     ctor public ForkJoinPool(int, java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory, java.lang.Thread.UncaughtExceptionHandler, boolean);
     method public boolean awaitQuiescence(long, java.util.concurrent.TimeUnit);
     method public boolean awaitTermination(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public static java.util.concurrent.ForkJoinPool commonPool();
     method protected int drainTasksTo(java.util.Collection<? super java.util.concurrent.ForkJoinTask<?>>);
     method public void execute(java.util.concurrent.ForkJoinTask<?>);
     method public void execute(java.lang.Runnable);
     method public int getActiveThreadCount();
     method public boolean getAsyncMode();
+    method public static int getCommonPoolParallelism();
     method public java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory getFactory();
     method public int getParallelism();
     method public int getPoolSize();
@@ -59452,6 +59738,7 @@
     method public static java.util.concurrent.ForkJoinTask<T> adapt(java.lang.Runnable, T);
     method public static java.util.concurrent.ForkJoinTask<T> adapt(java.util.concurrent.Callable<? extends T>);
     method public boolean cancel(boolean);
+    method public final boolean compareAndSetForkJoinTaskTag(short, short);
     method public void complete(V);
     method public void completeExceptionally(java.lang.Throwable);
     method protected abstract boolean exec();
@@ -59459,6 +59746,7 @@
     method public final V get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
     method public final V get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
     method public final java.lang.Throwable getException();
+    method public final short getForkJoinTaskTag();
     method public static java.util.concurrent.ForkJoinPool getPool();
     method public static int getQueuedTaskCount();
     method public abstract V getRawResult();
@@ -59477,9 +59765,11 @@
     method protected static java.util.concurrent.ForkJoinTask<?> peekNextLocalTask();
     method protected static java.util.concurrent.ForkJoinTask<?> pollNextLocalTask();
     method protected static java.util.concurrent.ForkJoinTask<?> pollTask();
+    method public final void quietlyComplete();
     method public final void quietlyInvoke();
     method public final void quietlyJoin();
     method public void reinitialize();
+    method public final short setForkJoinTaskTag(short);
     method protected abstract void setRawResult(V);
     method public boolean tryUnfork();
   }
@@ -59553,6 +59843,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
     method public E takeFirst() throws java.lang.InterruptedException;
     method public E takeLast() throws java.lang.InterruptedException;
@@ -59573,6 +59864,7 @@
     method public void put(E) throws java.lang.InterruptedException;
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -59592,6 +59884,7 @@
     method public void put(E);
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
     method public void transfer(E) throws java.lang.InterruptedException;
     method public boolean tryTransfer(E);
@@ -59639,6 +59932,7 @@
     method public void put(E);
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -59742,6 +60036,7 @@
     method public void put(E) throws java.lang.InterruptedException;
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -59871,112 +60166,136 @@
   public class AtomicInteger extends java.lang.Number implements java.io.Serializable {
     ctor public AtomicInteger(int);
     ctor public AtomicInteger();
+    method public final int accumulateAndGet(int, java.util.function.IntBinaryOperator);
     method public final int addAndGet(int);
     method public final boolean compareAndSet(int, int);
     method public final int decrementAndGet();
     method public double doubleValue();
     method public float floatValue();
     method public final int get();
+    method public final int getAndAccumulate(int, java.util.function.IntBinaryOperator);
     method public final int getAndAdd(int);
     method public final int getAndDecrement();
     method public final int getAndIncrement();
     method public final int getAndSet(int);
+    method public final int getAndUpdate(java.util.function.IntUnaryOperator);
     method public final int incrementAndGet();
     method public int intValue();
     method public final void lazySet(int);
     method public long longValue();
     method public final void set(int);
+    method public final int updateAndGet(java.util.function.IntUnaryOperator);
     method public final boolean weakCompareAndSet(int, int);
   }
 
   public class AtomicIntegerArray implements java.io.Serializable {
     ctor public AtomicIntegerArray(int);
     ctor public AtomicIntegerArray(int[]);
+    method public final int accumulateAndGet(int, int, java.util.function.IntBinaryOperator);
     method public final int addAndGet(int, int);
     method public final boolean compareAndSet(int, int, int);
     method public final int decrementAndGet(int);
     method public final int get(int);
+    method public final int getAndAccumulate(int, int, java.util.function.IntBinaryOperator);
     method public final int getAndAdd(int, int);
     method public final int getAndDecrement(int);
     method public final int getAndIncrement(int);
     method public final int getAndSet(int, int);
+    method public final int getAndUpdate(int, java.util.function.IntUnaryOperator);
     method public final int incrementAndGet(int);
     method public final void lazySet(int, int);
     method public final int length();
     method public final void set(int, int);
+    method public final int updateAndGet(int, java.util.function.IntUnaryOperator);
     method public final boolean weakCompareAndSet(int, int, int);
   }
 
   public abstract class AtomicIntegerFieldUpdater {
     ctor protected AtomicIntegerFieldUpdater();
+    method public final int accumulateAndGet(T, int, java.util.function.IntBinaryOperator);
     method public int addAndGet(T, int);
     method public abstract boolean compareAndSet(T, int, int);
     method public int decrementAndGet(T);
     method public abstract int get(T);
+    method public final int getAndAccumulate(T, int, java.util.function.IntBinaryOperator);
     method public int getAndAdd(T, int);
     method public int getAndDecrement(T);
     method public int getAndIncrement(T);
     method public int getAndSet(T, int);
+    method public final int getAndUpdate(T, java.util.function.IntUnaryOperator);
     method public int incrementAndGet(T);
     method public abstract void lazySet(T, int);
     method public static java.util.concurrent.atomic.AtomicIntegerFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
     method public abstract void set(T, int);
+    method public final int updateAndGet(T, java.util.function.IntUnaryOperator);
     method public abstract boolean weakCompareAndSet(T, int, int);
   }
 
   public class AtomicLong extends java.lang.Number implements java.io.Serializable {
     ctor public AtomicLong(long);
     ctor public AtomicLong();
+    method public final long accumulateAndGet(long, java.util.function.LongBinaryOperator);
     method public final long addAndGet(long);
     method public final boolean compareAndSet(long, long);
     method public final long decrementAndGet();
     method public double doubleValue();
     method public float floatValue();
     method public final long get();
+    method public final long getAndAccumulate(long, java.util.function.LongBinaryOperator);
     method public final long getAndAdd(long);
     method public final long getAndDecrement();
     method public final long getAndIncrement();
     method public final long getAndSet(long);
+    method public final long getAndUpdate(java.util.function.LongUnaryOperator);
     method public final long incrementAndGet();
     method public int intValue();
     method public final void lazySet(long);
     method public long longValue();
     method public final void set(long);
+    method public final long updateAndGet(java.util.function.LongUnaryOperator);
     method public final boolean weakCompareAndSet(long, long);
   }
 
   public class AtomicLongArray implements java.io.Serializable {
     ctor public AtomicLongArray(int);
     ctor public AtomicLongArray(long[]);
+    method public final long accumulateAndGet(int, long, java.util.function.LongBinaryOperator);
     method public long addAndGet(int, long);
     method public final boolean compareAndSet(int, long, long);
     method public final long decrementAndGet(int);
     method public final long get(int);
+    method public final long getAndAccumulate(int, long, java.util.function.LongBinaryOperator);
     method public final long getAndAdd(int, long);
     method public final long getAndDecrement(int);
     method public final long getAndIncrement(int);
     method public final long getAndSet(int, long);
+    method public final long getAndUpdate(int, java.util.function.LongUnaryOperator);
     method public final long incrementAndGet(int);
     method public final void lazySet(int, long);
     method public final int length();
     method public final void set(int, long);
+    method public final long updateAndGet(int, java.util.function.LongUnaryOperator);
     method public final boolean weakCompareAndSet(int, long, long);
   }
 
   public abstract class AtomicLongFieldUpdater {
     ctor protected AtomicLongFieldUpdater();
+    method public final long accumulateAndGet(T, long, java.util.function.LongBinaryOperator);
     method public long addAndGet(T, long);
     method public abstract boolean compareAndSet(T, long, long);
     method public long decrementAndGet(T);
     method public abstract long get(T);
+    method public final long getAndAccumulate(T, long, java.util.function.LongBinaryOperator);
     method public long getAndAdd(T, long);
     method public long getAndDecrement(T);
     method public long getAndIncrement(T);
     method public long getAndSet(T, long);
+    method public final long getAndUpdate(T, java.util.function.LongUnaryOperator);
     method public long incrementAndGet(T);
     method public abstract void lazySet(T, long);
     method public static java.util.concurrent.atomic.AtomicLongFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
     method public abstract void set(T, long);
+    method public final long updateAndGet(T, java.util.function.LongUnaryOperator);
     method public abstract boolean weakCompareAndSet(T, long, long);
   }
 
@@ -59994,34 +60313,46 @@
   public class AtomicReference implements java.io.Serializable {
     ctor public AtomicReference(V);
     ctor public AtomicReference();
+    method public final V accumulateAndGet(V, java.util.function.BinaryOperator<V>);
     method public final boolean compareAndSet(V, V);
     method public final V get();
+    method public final V getAndAccumulate(V, java.util.function.BinaryOperator<V>);
     method public final V getAndSet(V);
+    method public final V getAndUpdate(java.util.function.UnaryOperator<V>);
     method public final void lazySet(V);
     method public final void set(V);
+    method public final V updateAndGet(java.util.function.UnaryOperator<V>);
     method public final boolean weakCompareAndSet(V, V);
   }
 
   public class AtomicReferenceArray implements java.io.Serializable {
     ctor public AtomicReferenceArray(int);
     ctor public AtomicReferenceArray(E[]);
+    method public final E accumulateAndGet(int, E, java.util.function.BinaryOperator<E>);
     method public final boolean compareAndSet(int, E, E);
     method public final E get(int);
+    method public final E getAndAccumulate(int, E, java.util.function.BinaryOperator<E>);
     method public final E getAndSet(int, E);
+    method public final E getAndUpdate(int, java.util.function.UnaryOperator<E>);
     method public final void lazySet(int, E);
     method public final int length();
     method public final void set(int, E);
+    method public final E updateAndGet(int, java.util.function.UnaryOperator<E>);
     method public final boolean weakCompareAndSet(int, E, E);
   }
 
   public abstract class AtomicReferenceFieldUpdater {
     ctor protected AtomicReferenceFieldUpdater();
+    method public final V accumulateAndGet(T, V, java.util.function.BinaryOperator<V>);
     method public abstract boolean compareAndSet(T, V, V);
     method public abstract V get(T);
+    method public final V getAndAccumulate(T, V, java.util.function.BinaryOperator<V>);
     method public V getAndSet(T, V);
+    method public final V getAndUpdate(T, java.util.function.UnaryOperator<V>);
     method public abstract void lazySet(T, V);
     method public static java.util.concurrent.atomic.AtomicReferenceFieldUpdater<U, W> newUpdater(java.lang.Class<U>, java.lang.Class<W>, java.lang.String);
     method public abstract void set(T, V);
+    method public final V updateAndGet(T, java.util.function.UnaryOperator<V>);
     method public abstract boolean weakCompareAndSet(T, V, V);
   }
 
@@ -60036,6 +60367,59 @@
     method public boolean weakCompareAndSet(V, V, int, int);
   }
 
+  public class DoubleAccumulator extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public DoubleAccumulator(java.util.function.DoubleBinaryOperator, double);
+    method public void accumulate(double);
+    method public double doubleValue();
+    method public float floatValue();
+    method public double get();
+    method public double getThenReset();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+  }
+
+  public class DoubleAdder extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public DoubleAdder();
+    method public void add(double);
+    method public double doubleValue();
+    method public float floatValue();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+    method public double sum();
+    method public double sumThenReset();
+  }
+
+  public class LongAccumulator extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public LongAccumulator(java.util.function.LongBinaryOperator, long);
+    method public void accumulate(long);
+    method public double doubleValue();
+    method public float floatValue();
+    method public long get();
+    method public long getThenReset();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+  }
+
+  public class LongAdder extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public LongAdder();
+    method public void add(long);
+    method public void decrement();
+    method public double doubleValue();
+    method public float floatValue();
+    method public void increment();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+    method public long sum();
+    method public long sumThenReset();
+  }
+
+   abstract class Striped64 extends java.lang.Number {
+  }
+
 }
 
 package java.util.concurrent.locks {
@@ -60243,6 +60627,34 @@
     method public void unlock();
   }
 
+  public class StampedLock implements java.io.Serializable {
+    ctor public StampedLock();
+    method public java.util.concurrent.locks.Lock asReadLock();
+    method public java.util.concurrent.locks.ReadWriteLock asReadWriteLock();
+    method public java.util.concurrent.locks.Lock asWriteLock();
+    method public int getReadLockCount();
+    method public boolean isReadLocked();
+    method public boolean isWriteLocked();
+    method public long readLock();
+    method public long readLockInterruptibly() throws java.lang.InterruptedException;
+    method public long tryConvertToOptimisticRead(long);
+    method public long tryConvertToReadLock(long);
+    method public long tryConvertToWriteLock(long);
+    method public long tryOptimisticRead();
+    method public long tryReadLock();
+    method public long tryReadLock(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public boolean tryUnlockRead();
+    method public boolean tryUnlockWrite();
+    method public long tryWriteLock();
+    method public long tryWriteLock(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public void unlock(long);
+    method public void unlockRead(long);
+    method public void unlockWrite(long);
+    method public boolean validate(long);
+    method public long writeLock();
+    method public long writeLockInterruptibly() throws java.lang.InterruptedException;
+  }
+
 }
 
 package java.util.function {
diff --git a/api/system-current.txt b/api/system-current.txt
index 708286c..6433194 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3557,7 +3557,7 @@
     method public android.view.View getCurrentFocus();
     method public android.app.FragmentManager getFragmentManager();
     method public android.content.Intent getIntent();
-    method public deprecated java.lang.Object getLastNonConfigurationInstance();
+    method public java.lang.Object getLastNonConfigurationInstance();
     method public android.view.LayoutInflater getLayoutInflater();
     method public android.app.LoaderManager getLoaderManager();
     method public java.lang.String getLocalClassName();
@@ -3660,7 +3660,7 @@
     method protected void onRestoreInstanceState(android.os.Bundle);
     method public void onRestoreInstanceState(android.os.Bundle, android.os.PersistableBundle);
     method protected void onResume();
-    method public deprecated java.lang.Object onRetainNonConfigurationInstance();
+    method public java.lang.Object onRetainNonConfigurationInstance();
     method protected void onSaveInstanceState(android.os.Bundle);
     method public void onSaveInstanceState(android.os.Bundle, android.os.PersistableBundle);
     method public boolean onSearchRequested(android.view.SearchEvent);
@@ -9788,6 +9788,7 @@
     method public int getShortcutIconResId(android.content.pm.ShortcutInfo, android.os.UserHandle);
     method public java.util.List<android.content.pm.ShortcutInfo> getShortcutInfo(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
     method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle);
+    method public boolean hasShortcutHostPermission();
     method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
     method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle);
     method public void pinShortcuts(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
@@ -9928,11 +9929,11 @@
   public static class PackageInstaller.SessionParams implements android.os.Parcelable {
     ctor public PackageInstaller.SessionParams(int);
     method public int describeContents();
+    method public void setAllowDowngrade(boolean);
     method public void setAppIcon(android.graphics.Bitmap);
     method public void setAppLabel(java.lang.CharSequence);
     method public void setAppPackageName(java.lang.String);
     method public void setGrantedRuntimePermissions(java.lang.String[]);
-    method public void setInstallFlagsDowngrade();
     method public void setInstallLocation(int);
     method public void setOriginatingUid(int);
     method public void setOriginatingUri(android.net.Uri);
@@ -10511,7 +10512,6 @@
     method public static deprecated android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public int describeContents();
-    method public int getChangingConfigurations();
     method public int getColorForState(int[], int);
     method public int getDefaultColor();
     method public boolean isOpaque();
@@ -10523,6 +10523,7 @@
 
   public abstract class ComplexColor {
     ctor public ComplexColor();
+    method public int getChangingConfigurations();
     method public abstract int getDefaultColor();
     method public boolean isStateful();
   }
@@ -13430,9 +13431,9 @@
     method public void setPaddingMode(int);
     method public void setPaddingRelative(int, int, int, int);
     method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+    field public static final int INSET_UNDEFINED = -2147483648; // 0x80000000
     field public static final int PADDING_MODE_NEST = 0; // 0x0
     field public static final int PADDING_MODE_STACK = 1; // 0x1
-    field public static final int UNDEFINED_INSET = -2147483648; // 0x80000000
   }
 
   public class LevelListDrawable extends android.graphics.drawable.DrawableContainer {
@@ -33114,6 +33115,7 @@
   public static class CallLog.Calls implements android.provider.BaseColumns {
     ctor public CallLog.Calls();
     method public static java.lang.String getLastOutgoingCall(android.content.Context);
+    field public static final int ANSWERED_EXTERNALLY_TYPE = 7; // 0x7
     field public static final int BLOCKED_TYPE = 6; // 0x6
     field public static final java.lang.String CACHED_FORMATTED_NUMBER = "formatted_number";
     field public static final java.lang.String CACHED_LOOKUP_URI = "lookup_uri";
@@ -33136,6 +33138,7 @@
     field public static final java.lang.String DURATION = "duration";
     field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.CALL_TYPE_FILTER";
     field public static final java.lang.String FEATURES = "features";
+    field public static final int FEATURES_PULLED_EXTERNALLY = 2; // 0x2
     field public static final int FEATURES_VIDEO = 1; // 0x1
     field public static final java.lang.String GEOCODED_LOCATION = "geocoded_location";
     field public static final int INCOMING_TYPE = 1; // 0x1
@@ -38658,10 +38661,12 @@
     method public void phoneAccountSelected(android.telecom.PhoneAccountHandle, boolean);
     method public void playDtmfTone(char);
     method public void postDialContinue(boolean);
+    method public void pullExternalCall();
     method public void registerCallback(android.telecom.Call.Callback);
     method public void registerCallback(android.telecom.Call.Callback, android.os.Handler);
     method public void reject(boolean, java.lang.String);
     method public deprecated void removeListener(android.telecom.Call.Listener);
+    method public void sendCallEvent(java.lang.String, android.os.Bundle);
     method public void splitFromConference();
     method public void stopDtmfTone();
     method public void swapConference();
@@ -38676,6 +38681,7 @@
     field public static final int STATE_HOLDING = 3; // 0x3
     field public static final int STATE_NEW = 0; // 0x0
     field public static final deprecated int STATE_PRE_DIAL_WAIT = 8; // 0x8
+    field public static final int STATE_PULLING_CALL = 11; // 0xb
     field public static final int STATE_RINGING = 2; // 0x2
     field public static final int STATE_SELECT_PHONE_ACCOUNT = 8; // 0x8
   }
@@ -38686,6 +38692,7 @@
     method public void onCannedTextResponsesLoaded(android.telecom.Call, java.util.List<java.lang.String>);
     method public void onChildrenChanged(android.telecom.Call, java.util.List<android.telecom.Call>);
     method public void onConferenceableCallsChanged(android.telecom.Call, java.util.List<android.telecom.Call>);
+    method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle);
     method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details);
     method public void onParentChanged(android.telecom.Call, android.telecom.Call);
     method public void onPostDialWait(android.telecom.Call, java.lang.String);
@@ -38716,6 +38723,7 @@
     method public static java.lang.String propertiesToString(int);
     field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 4194304; // 0x400000
     field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
+    field public static final int CAPABILITY_CAN_PULL_CALL = 8388608; // 0x800000
     field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
     field public static final int CAPABILITY_HOLD = 1; // 0x1
     field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
@@ -38735,6 +38743,7 @@
     field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 4; // 0x4
     field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2
     field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10
+    field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40
     field public static final int PROPERTY_WIFI = 8; // 0x8
     field public static final int PROPERTY_WORK_CALL = 32; // 0x20
   }
@@ -38860,15 +38869,19 @@
     method public void onAnswer();
     method public deprecated void onAudioStateChanged(android.telecom.AudioState);
     method public void onCallAudioStateChanged(android.telecom.CallAudioState);
+    method public void onCallEvent(java.lang.String, android.os.Bundle);
     method public void onDisconnect();
     method public void onHold();
     method public void onPlayDtmfTone(char);
     method public void onPostDialContinue(boolean);
+    method public void onPullExternalCall();
     method public void onReject();
+    method public void onReject(java.lang.String);
     method public void onSeparate();
     method public void onStateChanged(int);
     method public void onStopDtmfTone();
     method public void onUnhold();
+    method public void sendConnectionEvent(java.lang.String, android.os.Bundle);
     method public final void setActive();
     method public final void setAddress(android.net.Uri, int);
     method public final void setAudioModeIsVoip(boolean);
@@ -38892,9 +38905,12 @@
     method public static java.lang.String stateToString(int);
     field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 8388608; // 0x800000
     field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
+    field public static final int CAPABILITY_CAN_PULL_CALL = 33554432; // 0x2000000
+    field public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 4194304; // 0x400000
     field public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 524288; // 0x80000
     field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
     field public static final int CAPABILITY_HOLD = 1; // 0x1
+    field public static final int CAPABILITY_IS_EXTERNAL_CALL = 16777216; // 0x1000000
     field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
     field public static final int CAPABILITY_MERGE_CONFERENCE = 4; // 0x4
     field public static final int CAPABILITY_MUTE = 64; // 0x40
@@ -38908,6 +38924,7 @@
     field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 2048; // 0x800
     field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2
     field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8
+    field public static final java.lang.String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED";
     field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
     field public static final java.lang.String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS";
     field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER";
@@ -38917,6 +38934,7 @@
     field public static final int STATE_HOLDING = 5; // 0x5
     field public static final int STATE_INITIALIZING = 0; // 0x0
     field public static final int STATE_NEW = 1; // 0x1
+    field public static final int STATE_PULLING_CALL = 7; // 0x7
     field public static final int STATE_RINGING = 2; // 0x2
   }
 
@@ -38994,7 +39012,9 @@
     method public java.lang.String getReason();
     method public int getTone();
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final int ANSWERED_ELSEWHERE = 11; // 0xb
     field public static final int BUSY = 7; // 0x7
+    field public static final int CALL_PULLED = 12; // 0xc
     field public static final int CANCELED = 4; // 0x4
     field public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10; // 0xa
     field public static final android.os.Parcelable.Creator<android.telecom.DisconnectCause> CREATOR;
@@ -39031,6 +39051,7 @@
     method public void onCallAudioStateChanged(android.telecom.CallAudioState);
     method public void onCallRemoved(android.telecom.Call);
     method public void onCanAddCallChanged(boolean);
+    method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle);
     method public deprecated void onPhoneCreated(android.telecom.Phone);
     method public deprecated void onPhoneDestroyed(android.telecom.Phone);
     method public void onSilenceRinger();
@@ -39236,6 +39257,7 @@
     method public boolean isVoipAudioMode();
     method public void playDtmfTone(char);
     method public void postDialContinue(boolean);
+    method public void pullExternalCall();
     method public void registerCallback(android.telecom.RemoteConnection.Callback);
     method public void registerCallback(android.telecom.RemoteConnection.Callback, android.os.Handler);
     method public void reject();
@@ -39253,6 +39275,7 @@
     method public void onConferenceChanged(android.telecom.RemoteConnection, android.telecom.RemoteConference);
     method public void onConferenceableConnectionsChanged(android.telecom.RemoteConnection, java.util.List<android.telecom.RemoteConnection>);
     method public void onConnectionCapabilitiesChanged(android.telecom.RemoteConnection, int);
+    method public void onConnectionEvent(android.telecom.RemoteConnection, java.lang.String, android.os.Bundle);
     method public void onDestroyed(android.telecom.RemoteConnection);
     method public void onDisconnected(android.telecom.RemoteConnection, android.telecom.DisconnectCause);
     method public void onExtrasChanged(android.telecom.RemoteConnection, android.os.Bundle);
@@ -39377,6 +39400,7 @@
     field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
     field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
     field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
+    field public static final java.lang.String METADATA_INCLUDE_EXTERNAL_CALLS = "android.telecom.INCLUDE_EXTERNAL_CALLS";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI";
     field public static final int PRESENTATION_ALLOWED = 1; // 0x1
@@ -60444,6 +60468,7 @@
     method public void ensureCapacity(int);
     method public void forEach(java.util.function.Consumer<? super E>);
     method public E get(int);
+    method public boolean removeIf(java.util.function.Predicate<? super E>);
     method public int size();
     method public java.util.Spliterator<E> spliterator();
     method public void trimToSize();
@@ -60528,6 +60553,24 @@
     method public static int hashCode(float[]);
     method public static int hashCode(double[]);
     method public static int hashCode(java.lang.Object[]);
+    method public static void parallelSort(byte[]);
+    method public static void parallelSort(byte[], int, int);
+    method public static void parallelSort(char[]);
+    method public static void parallelSort(char[], int, int);
+    method public static void parallelSort(short[]);
+    method public static void parallelSort(short[], int, int);
+    method public static void parallelSort(int[]);
+    method public static void parallelSort(int[], int, int);
+    method public static void parallelSort(long[]);
+    method public static void parallelSort(long[], int, int);
+    method public static void parallelSort(float[]);
+    method public static void parallelSort(float[], int, int);
+    method public static void parallelSort(double[]);
+    method public static void parallelSort(double[], int, int);
+    method public static void parallelSort(T[]);
+    method public static void parallelSort(T[], int, int);
+    method public static void parallelSort(T[], java.util.Comparator<? super T>);
+    method public static void parallelSort(T[], int, int, java.util.Comparator<? super T>);
     method public static void sort(int[]);
     method public static void sort(int[], int, int);
     method public static void sort(long[]);
@@ -60715,6 +60758,7 @@
     method public abstract java.util.Iterator<E> iterator();
     method public abstract boolean remove(java.lang.Object);
     method public abstract boolean removeAll(java.util.Collection<?>);
+    method public default boolean removeIf(java.util.function.Predicate<? super E>);
     method public abstract boolean retainAll(java.util.Collection<?>);
     method public abstract int size();
     method public abstract java.lang.Object[] toArray();
@@ -61348,18 +61392,28 @@
 
   public abstract interface Map {
     method public abstract void clear();
+    method public default V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public default V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
+    method public default V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public abstract boolean containsKey(java.lang.Object);
     method public abstract boolean containsValue(java.lang.Object);
     method public abstract java.util.Set<java.util.Map.Entry<K, V>> entrySet();
     method public abstract boolean equals(java.lang.Object);
     method public default void forEach(java.util.function.BiConsumer<? super K, ? super V>);
     method public abstract V get(java.lang.Object);
+    method public default V getOrDefault(java.lang.Object, V);
     method public abstract int hashCode();
     method public abstract boolean isEmpty();
     method public abstract java.util.Set<K> keySet();
+    method public default V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
     method public abstract V put(K, V);
     method public abstract void putAll(java.util.Map<? extends K, ? extends V>);
+    method public default V putIfAbsent(K, V);
     method public abstract V remove(java.lang.Object);
+    method public default boolean remove(java.lang.Object, java.lang.Object);
+    method public default boolean replace(K, V, V);
+    method public default V replace(K, V);
+    method public default void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public abstract int size();
     method public abstract java.util.Collection<V> values();
   }
@@ -61367,6 +61421,8 @@
   public static abstract interface Map.Entry {
     method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey();
     method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey(java.util.Comparator<? super K>);
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue();
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue(java.util.Comparator<? super V>);
     method public abstract boolean equals(java.lang.Object);
     method public abstract K getKey();
     method public abstract V getValue();
@@ -62097,6 +62153,7 @@
     method public synchronized void removeAllElements();
     method public synchronized boolean removeElement(java.lang.Object);
     method public synchronized void removeElementAt(int);
+    method public synchronized boolean removeIf(java.util.function.Predicate<? super E>);
     method public synchronized void setElementAt(E, int);
     method public synchronized void setSize(int);
     method public synchronized int size();
@@ -62148,6 +62205,7 @@
     method public void put(E) throws java.lang.InterruptedException;
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -62211,6 +62269,78 @@
     ctor public CancellationException(java.lang.String);
   }
 
+  public class CompletableFuture implements java.util.concurrent.CompletionStage java.util.concurrent.Future {
+    ctor public CompletableFuture();
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Void> allOf(java.util.concurrent.CompletableFuture<?>...);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Object> anyOf(java.util.concurrent.CompletableFuture<?>...);
+    method public java.util.concurrent.CompletableFuture<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
+    method public boolean cancel(boolean);
+    method public boolean complete(T);
+    method public boolean completeExceptionally(java.lang.Throwable);
+    method public static java.util.concurrent.CompletableFuture<U> completedFuture(U);
+    method public java.util.concurrent.CompletableFuture<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>);
+    method public T get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
+    method public T get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
+    method public T getNow(T);
+    method public int getNumberOfDependents();
+    method public java.util.concurrent.CompletableFuture<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
+    method public boolean isCancelled();
+    method public boolean isCompletedExceptionally();
+    method public boolean isDone();
+    method public T join();
+    method public void obtrudeException(java.lang.Throwable);
+    method public void obtrudeValue(T);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBoth(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEither(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable, java.util.concurrent.Executor);
+    method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>);
+    method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<U> thenApply(java.util.function.Function<? super T, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRun(java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<T> toCompletableFuture();
+    method public java.util.concurrent.CompletableFuture<T> whenComplete(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public java.util.concurrent.CompletableFuture<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public java.util.concurrent.CompletableFuture<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>, java.util.concurrent.Executor);
+  }
+
+  public static abstract interface CompletableFuture.AsynchronousCompletionTask {
+  }
+
+  public class CompletionException extends java.lang.RuntimeException {
+    ctor protected CompletionException();
+    ctor protected CompletionException(java.lang.String);
+    ctor public CompletionException(java.lang.String, java.lang.Throwable);
+    ctor public CompletionException(java.lang.Throwable);
+  }
+
   public abstract interface CompletionService {
     method public abstract java.util.concurrent.Future<V> poll();
     method public abstract java.util.concurrent.Future<V> poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
@@ -62219,20 +62349,130 @@
     method public abstract java.util.concurrent.Future<V> take() throws java.lang.InterruptedException;
   }
 
+  public abstract interface CompletionStage {
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>);
+    method public abstract java.util.concurrent.CompletionStage<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBoth(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEither(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<U> thenApply(java.util.function.Function<? super T, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRun(java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletableFuture<T> toCompletableFuture();
+    method public abstract java.util.concurrent.CompletionStage<T> whenComplete(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public abstract java.util.concurrent.CompletionStage<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public abstract java.util.concurrent.CompletionStage<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>, java.util.concurrent.Executor);
+  }
+
   public class ConcurrentHashMap extends java.util.AbstractMap implements java.util.concurrent.ConcurrentMap java.io.Serializable {
     ctor public ConcurrentHashMap();
     ctor public ConcurrentHashMap(int);
     ctor public ConcurrentHashMap(java.util.Map<? extends K, ? extends V>);
     ctor public ConcurrentHashMap(int, float);
     ctor public ConcurrentHashMap(int, float, int);
+    method public V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
+    method public V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public boolean contains(java.lang.Object);
     method public java.util.Enumeration<V> elements();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
+    method public void forEach(long, java.util.function.BiConsumer<? super K, ? super V>);
+    method public void forEach(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.Consumer<? super U>);
+    method public void forEachEntry(long, java.util.function.Consumer<? super java.util.Map.Entry<K, V>>);
+    method public void forEachEntry(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.Consumer<? super U>);
+    method public void forEachKey(long, java.util.function.Consumer<? super K>);
+    method public void forEachKey(long, java.util.function.Function<? super K, ? extends U>, java.util.function.Consumer<? super U>);
+    method public void forEachValue(long, java.util.function.Consumer<? super V>);
+    method public void forEachValue(long, java.util.function.Function<? super V, ? extends U>, java.util.function.Consumer<? super U>);
+    method public V getOrDefault(java.lang.Object, V);
+    method public java.util.concurrent.ConcurrentHashMap.KeySetView<K, V> keySet(V);
     method public java.util.Enumeration<K> keys();
+    method public long mappingCount();
+    method public V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
+    method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet();
+    method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet(int);
     method public V putIfAbsent(K, V);
+    method public U reduce(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public java.util.Map.Entry<K, V> reduceEntries(long, java.util.function.BiFunction<java.util.Map.Entry<K, V>, java.util.Map.Entry<K, V>, ? extends java.util.Map.Entry<K, V>>);
+    method public U reduceEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public double reduceEntriesToDouble(long, java.util.function.ToDoubleFunction<java.util.Map.Entry<K, V>>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceEntriesToInt(long, java.util.function.ToIntFunction<java.util.Map.Entry<K, V>>, int, java.util.function.IntBinaryOperator);
+    method public long reduceEntriesToLong(long, java.util.function.ToLongFunction<java.util.Map.Entry<K, V>>, long, java.util.function.LongBinaryOperator);
+    method public K reduceKeys(long, java.util.function.BiFunction<? super K, ? super K, ? extends K>);
+    method public U reduceKeys(long, java.util.function.Function<? super K, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public double reduceKeysToDouble(long, java.util.function.ToDoubleFunction<? super K>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceKeysToInt(long, java.util.function.ToIntFunction<? super K>, int, java.util.function.IntBinaryOperator);
+    method public long reduceKeysToLong(long, java.util.function.ToLongFunction<? super K>, long, java.util.function.LongBinaryOperator);
+    method public double reduceToDouble(long, java.util.function.ToDoubleBiFunction<? super K, ? super V>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceToInt(long, java.util.function.ToIntBiFunction<? super K, ? super V>, int, java.util.function.IntBinaryOperator);
+    method public long reduceToLong(long, java.util.function.ToLongBiFunction<? super K, ? super V>, long, java.util.function.LongBinaryOperator);
+    method public V reduceValues(long, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
+    method public U reduceValues(long, java.util.function.Function<? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public double reduceValuesToDouble(long, java.util.function.ToDoubleFunction<? super V>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceValuesToInt(long, java.util.function.ToIntFunction<? super V>, int, java.util.function.IntBinaryOperator);
+    method public long reduceValuesToLong(long, java.util.function.ToLongFunction<? super V>, long, java.util.function.LongBinaryOperator);
     method public boolean remove(java.lang.Object, java.lang.Object);
     method public boolean replace(K, V, V);
     method public V replace(K, V);
+    method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public U search(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>);
+    method public U searchEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>);
+    method public U searchKeys(long, java.util.function.Function<? super K, ? extends U>);
+    method public U searchValues(long, java.util.function.Function<? super V, ? extends U>);
+  }
+
+   static abstract class ConcurrentHashMap.CollectionView implements java.util.Collection java.io.Serializable {
+    method public final void clear();
+    method public abstract boolean contains(java.lang.Object);
+    method public final boolean containsAll(java.util.Collection<?>);
+    method public java.util.concurrent.ConcurrentHashMap<K, V> getMap();
+    method public final boolean isEmpty();
+    method public abstract java.util.Iterator<E> iterator();
+    method public abstract boolean remove(java.lang.Object);
+    method public final boolean removeAll(java.util.Collection<?>);
+    method public final boolean retainAll(java.util.Collection<?>);
+    method public final int size();
+    method public final java.lang.Object[] toArray();
+    method public final T[] toArray(T[]);
+    method public final java.lang.String toString();
+  }
+
+  public static class ConcurrentHashMap.KeySetView extends java.util.concurrent.ConcurrentHashMap.CollectionView implements java.io.Serializable java.util.Set {
+    method public boolean add(K);
+    method public boolean addAll(java.util.Collection<? extends K>);
+    method public boolean contains(java.lang.Object);
+    method public void forEach(java.util.function.Consumer<? super K>);
+    method public V getMappedValue();
+    method public java.util.Iterator<K> iterator();
+    method public boolean remove(java.lang.Object);
+    method public java.util.Spliterator<K> spliterator();
   }
 
   public class ConcurrentLinkedDeque extends java.util.AbstractCollection implements java.util.Deque java.io.Serializable {
@@ -62262,6 +62502,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class ConcurrentLinkedQueue extends java.util.AbstractQueue implements java.util.Queue java.io.Serializable {
@@ -62272,6 +62513,7 @@
     method public E peek();
     method public E poll();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public abstract interface ConcurrentMap implements java.util.Map {
@@ -62303,6 +62545,9 @@
     method public K ceilingKey(K);
     method public java.util.concurrent.ConcurrentSkipListMap<K, V> clone();
     method public java.util.Comparator<? super K> comparator();
+    method public V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
+    method public V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public java.util.NavigableSet<K> descendingKeySet();
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> descendingMap();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
@@ -62310,6 +62555,8 @@
     method public K firstKey();
     method public java.util.Map.Entry<K, V> floorEntry(K);
     method public K floorKey(K);
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
+    method public V getOrDefault(java.lang.Object, V);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K, boolean);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K);
     method public java.util.Map.Entry<K, V> higherEntry(K);
@@ -62318,6 +62565,7 @@
     method public K lastKey();
     method public java.util.Map.Entry<K, V> lowerEntry(K);
     method public K lowerKey(K);
+    method public V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
     method public java.util.NavigableSet<K> navigableKeySet();
     method public java.util.Map.Entry<K, V> pollFirstEntry();
     method public java.util.Map.Entry<K, V> pollLastEntry();
@@ -62325,6 +62573,7 @@
     method public boolean remove(java.lang.Object, java.lang.Object);
     method public boolean replace(K, V, V);
     method public V replace(K, V);
+    method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> subMap(K, boolean, K, boolean);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> subMap(K, K);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> tailMap(K, boolean);
@@ -62352,6 +62601,7 @@
     method public E pollFirst();
     method public E pollLast();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public java.util.NavigableSet<E> subSet(E, boolean, E, boolean);
     method public java.util.NavigableSet<E> subSet(E, E);
     method public java.util.NavigableSet<E> tailSet(E, boolean);
@@ -62362,31 +62612,34 @@
     ctor public CopyOnWriteArrayList();
     ctor public CopyOnWriteArrayList(java.util.Collection<? extends E>);
     ctor public CopyOnWriteArrayList(E[]);
-    method public synchronized boolean add(E);
-    method public synchronized void add(int, E);
-    method public synchronized boolean addAll(java.util.Collection<? extends E>);
-    method public synchronized boolean addAll(int, java.util.Collection<? extends E>);
-    method public synchronized int addAllAbsent(java.util.Collection<? extends E>);
-    method public synchronized boolean addIfAbsent(E);
-    method public synchronized void clear();
+    method public boolean add(E);
+    method public void add(int, E);
+    method public boolean addAll(java.util.Collection<? extends E>);
+    method public boolean addAll(int, java.util.Collection<? extends E>);
+    method public int addAllAbsent(java.util.Collection<? extends E>);
+    method public boolean addIfAbsent(E);
+    method public void clear();
     method public java.lang.Object clone();
     method public boolean contains(java.lang.Object);
     method public boolean containsAll(java.util.Collection<?>);
+    method public void forEach(java.util.function.Consumer<? super E>);
     method public E get(int);
-    method public int indexOf(E, int);
     method public int indexOf(java.lang.Object);
+    method public int indexOf(E, int);
     method public boolean isEmpty();
     method public java.util.Iterator<E> iterator();
-    method public int lastIndexOf(E, int);
     method public int lastIndexOf(java.lang.Object);
-    method public java.util.ListIterator<E> listIterator(int);
+    method public int lastIndexOf(E, int);
     method public java.util.ListIterator<E> listIterator();
-    method public synchronized E remove(int);
-    method public synchronized boolean remove(java.lang.Object);
-    method public synchronized boolean removeAll(java.util.Collection<?>);
-    method public synchronized boolean retainAll(java.util.Collection<?>);
-    method public synchronized E set(int, E);
+    method public java.util.ListIterator<E> listIterator(int);
+    method public E remove(int);
+    method public boolean remove(java.lang.Object);
+    method public boolean removeAll(java.util.Collection<?>);
+    method public void replaceAll(java.util.function.UnaryOperator<E>);
+    method public boolean retainAll(java.util.Collection<?>);
+    method public E set(int, E);
     method public int size();
+    method public void sort(java.util.Comparator<? super E>);
     method public java.util.List<E> subList(int, int);
     method public java.lang.Object[] toArray();
     method public T[] toArray(T[]);
@@ -62395,8 +62648,11 @@
   public class CopyOnWriteArraySet extends java.util.AbstractSet implements java.io.Serializable {
     ctor public CopyOnWriteArraySet();
     ctor public CopyOnWriteArraySet(java.util.Collection<? extends E>);
+    method public void forEach(java.util.function.Consumer<? super E>);
     method public java.util.Iterator<E> iterator();
+    method public boolean removeIf(java.util.function.Predicate<? super E>);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class CountDownLatch {
@@ -62407,6 +62663,32 @@
     method public long getCount();
   }
 
+  public abstract class CountedCompleter extends java.util.concurrent.ForkJoinTask {
+    ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>, int);
+    ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>);
+    ctor protected CountedCompleter();
+    method public final void addToPendingCount(int);
+    method public final boolean compareAndSetPendingCount(int, int);
+    method public void complete(T);
+    method public abstract void compute();
+    method public final int decrementPendingCountUnlessZero();
+    method protected final boolean exec();
+    method public final java.util.concurrent.CountedCompleter<?> firstComplete();
+    method public final java.util.concurrent.CountedCompleter<?> getCompleter();
+    method public final int getPendingCount();
+    method public T getRawResult();
+    method public final java.util.concurrent.CountedCompleter<?> getRoot();
+    method public final void helpComplete(int);
+    method public final java.util.concurrent.CountedCompleter<?> nextComplete();
+    method public void onCompletion(java.util.concurrent.CountedCompleter<?>);
+    method public boolean onExceptionalCompletion(java.lang.Throwable, java.util.concurrent.CountedCompleter<?>);
+    method public final void propagateCompletion();
+    method public final void quietlyCompleteRoot();
+    method public final void setPendingCount(int);
+    method protected void setRawResult(T);
+    method public final void tryComplete();
+  }
+
   public class CyclicBarrier {
     ctor public CyclicBarrier(int, java.lang.Runnable);
     ctor public CyclicBarrier(int);
@@ -62497,6 +62779,8 @@
     method public static java.util.concurrent.ExecutorService newSingleThreadExecutor(java.util.concurrent.ThreadFactory);
     method public static java.util.concurrent.ScheduledExecutorService newSingleThreadScheduledExecutor();
     method public static java.util.concurrent.ScheduledExecutorService newSingleThreadScheduledExecutor(java.util.concurrent.ThreadFactory);
+    method public static java.util.concurrent.ExecutorService newWorkStealingPool(int);
+    method public static java.util.concurrent.ExecutorService newWorkStealingPool();
     method public static java.util.concurrent.Callable<T> privilegedCallable(java.util.concurrent.Callable<T>);
     method public static java.util.concurrent.Callable<T> privilegedCallableUsingCurrentClassLoader(java.util.concurrent.Callable<T>);
     method public static java.util.concurrent.ThreadFactory privilegedThreadFactory();
@@ -62510,11 +62794,13 @@
     ctor public ForkJoinPool(int, java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory, java.lang.Thread.UncaughtExceptionHandler, boolean);
     method public boolean awaitQuiescence(long, java.util.concurrent.TimeUnit);
     method public boolean awaitTermination(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public static java.util.concurrent.ForkJoinPool commonPool();
     method protected int drainTasksTo(java.util.Collection<? super java.util.concurrent.ForkJoinTask<?>>);
     method public void execute(java.util.concurrent.ForkJoinTask<?>);
     method public void execute(java.lang.Runnable);
     method public int getActiveThreadCount();
     method public boolean getAsyncMode();
+    method public static int getCommonPoolParallelism();
     method public java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory getFactory();
     method public int getParallelism();
     method public int getPoolSize();
@@ -62552,6 +62838,7 @@
     method public static java.util.concurrent.ForkJoinTask<T> adapt(java.lang.Runnable, T);
     method public static java.util.concurrent.ForkJoinTask<T> adapt(java.util.concurrent.Callable<? extends T>);
     method public boolean cancel(boolean);
+    method public final boolean compareAndSetForkJoinTaskTag(short, short);
     method public void complete(V);
     method public void completeExceptionally(java.lang.Throwable);
     method protected abstract boolean exec();
@@ -62559,6 +62846,7 @@
     method public final V get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
     method public final V get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
     method public final java.lang.Throwable getException();
+    method public final short getForkJoinTaskTag();
     method public static java.util.concurrent.ForkJoinPool getPool();
     method public static int getQueuedTaskCount();
     method public abstract V getRawResult();
@@ -62577,9 +62865,11 @@
     method protected static java.util.concurrent.ForkJoinTask<?> peekNextLocalTask();
     method protected static java.util.concurrent.ForkJoinTask<?> pollNextLocalTask();
     method protected static java.util.concurrent.ForkJoinTask<?> pollTask();
+    method public final void quietlyComplete();
     method public final void quietlyInvoke();
     method public final void quietlyJoin();
     method public void reinitialize();
+    method public final short setForkJoinTaskTag(short);
     method protected abstract void setRawResult(V);
     method public boolean tryUnfork();
   }
@@ -62653,6 +62943,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
     method public E takeFirst() throws java.lang.InterruptedException;
     method public E takeLast() throws java.lang.InterruptedException;
@@ -62673,6 +62964,7 @@
     method public void put(E) throws java.lang.InterruptedException;
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -62692,6 +62984,7 @@
     method public void put(E);
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
     method public void transfer(E) throws java.lang.InterruptedException;
     method public boolean tryTransfer(E);
@@ -62739,6 +63032,7 @@
     method public void put(E);
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -62842,6 +63136,7 @@
     method public void put(E) throws java.lang.InterruptedException;
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -62971,112 +63266,136 @@
   public class AtomicInteger extends java.lang.Number implements java.io.Serializable {
     ctor public AtomicInteger(int);
     ctor public AtomicInteger();
+    method public final int accumulateAndGet(int, java.util.function.IntBinaryOperator);
     method public final int addAndGet(int);
     method public final boolean compareAndSet(int, int);
     method public final int decrementAndGet();
     method public double doubleValue();
     method public float floatValue();
     method public final int get();
+    method public final int getAndAccumulate(int, java.util.function.IntBinaryOperator);
     method public final int getAndAdd(int);
     method public final int getAndDecrement();
     method public final int getAndIncrement();
     method public final int getAndSet(int);
+    method public final int getAndUpdate(java.util.function.IntUnaryOperator);
     method public final int incrementAndGet();
     method public int intValue();
     method public final void lazySet(int);
     method public long longValue();
     method public final void set(int);
+    method public final int updateAndGet(java.util.function.IntUnaryOperator);
     method public final boolean weakCompareAndSet(int, int);
   }
 
   public class AtomicIntegerArray implements java.io.Serializable {
     ctor public AtomicIntegerArray(int);
     ctor public AtomicIntegerArray(int[]);
+    method public final int accumulateAndGet(int, int, java.util.function.IntBinaryOperator);
     method public final int addAndGet(int, int);
     method public final boolean compareAndSet(int, int, int);
     method public final int decrementAndGet(int);
     method public final int get(int);
+    method public final int getAndAccumulate(int, int, java.util.function.IntBinaryOperator);
     method public final int getAndAdd(int, int);
     method public final int getAndDecrement(int);
     method public final int getAndIncrement(int);
     method public final int getAndSet(int, int);
+    method public final int getAndUpdate(int, java.util.function.IntUnaryOperator);
     method public final int incrementAndGet(int);
     method public final void lazySet(int, int);
     method public final int length();
     method public final void set(int, int);
+    method public final int updateAndGet(int, java.util.function.IntUnaryOperator);
     method public final boolean weakCompareAndSet(int, int, int);
   }
 
   public abstract class AtomicIntegerFieldUpdater {
     ctor protected AtomicIntegerFieldUpdater();
+    method public final int accumulateAndGet(T, int, java.util.function.IntBinaryOperator);
     method public int addAndGet(T, int);
     method public abstract boolean compareAndSet(T, int, int);
     method public int decrementAndGet(T);
     method public abstract int get(T);
+    method public final int getAndAccumulate(T, int, java.util.function.IntBinaryOperator);
     method public int getAndAdd(T, int);
     method public int getAndDecrement(T);
     method public int getAndIncrement(T);
     method public int getAndSet(T, int);
+    method public final int getAndUpdate(T, java.util.function.IntUnaryOperator);
     method public int incrementAndGet(T);
     method public abstract void lazySet(T, int);
     method public static java.util.concurrent.atomic.AtomicIntegerFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
     method public abstract void set(T, int);
+    method public final int updateAndGet(T, java.util.function.IntUnaryOperator);
     method public abstract boolean weakCompareAndSet(T, int, int);
   }
 
   public class AtomicLong extends java.lang.Number implements java.io.Serializable {
     ctor public AtomicLong(long);
     ctor public AtomicLong();
+    method public final long accumulateAndGet(long, java.util.function.LongBinaryOperator);
     method public final long addAndGet(long);
     method public final boolean compareAndSet(long, long);
     method public final long decrementAndGet();
     method public double doubleValue();
     method public float floatValue();
     method public final long get();
+    method public final long getAndAccumulate(long, java.util.function.LongBinaryOperator);
     method public final long getAndAdd(long);
     method public final long getAndDecrement();
     method public final long getAndIncrement();
     method public final long getAndSet(long);
+    method public final long getAndUpdate(java.util.function.LongUnaryOperator);
     method public final long incrementAndGet();
     method public int intValue();
     method public final void lazySet(long);
     method public long longValue();
     method public final void set(long);
+    method public final long updateAndGet(java.util.function.LongUnaryOperator);
     method public final boolean weakCompareAndSet(long, long);
   }
 
   public class AtomicLongArray implements java.io.Serializable {
     ctor public AtomicLongArray(int);
     ctor public AtomicLongArray(long[]);
+    method public final long accumulateAndGet(int, long, java.util.function.LongBinaryOperator);
     method public long addAndGet(int, long);
     method public final boolean compareAndSet(int, long, long);
     method public final long decrementAndGet(int);
     method public final long get(int);
+    method public final long getAndAccumulate(int, long, java.util.function.LongBinaryOperator);
     method public final long getAndAdd(int, long);
     method public final long getAndDecrement(int);
     method public final long getAndIncrement(int);
     method public final long getAndSet(int, long);
+    method public final long getAndUpdate(int, java.util.function.LongUnaryOperator);
     method public final long incrementAndGet(int);
     method public final void lazySet(int, long);
     method public final int length();
     method public final void set(int, long);
+    method public final long updateAndGet(int, java.util.function.LongUnaryOperator);
     method public final boolean weakCompareAndSet(int, long, long);
   }
 
   public abstract class AtomicLongFieldUpdater {
     ctor protected AtomicLongFieldUpdater();
+    method public final long accumulateAndGet(T, long, java.util.function.LongBinaryOperator);
     method public long addAndGet(T, long);
     method public abstract boolean compareAndSet(T, long, long);
     method public long decrementAndGet(T);
     method public abstract long get(T);
+    method public final long getAndAccumulate(T, long, java.util.function.LongBinaryOperator);
     method public long getAndAdd(T, long);
     method public long getAndDecrement(T);
     method public long getAndIncrement(T);
     method public long getAndSet(T, long);
+    method public final long getAndUpdate(T, java.util.function.LongUnaryOperator);
     method public long incrementAndGet(T);
     method public abstract void lazySet(T, long);
     method public static java.util.concurrent.atomic.AtomicLongFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
     method public abstract void set(T, long);
+    method public final long updateAndGet(T, java.util.function.LongUnaryOperator);
     method public abstract boolean weakCompareAndSet(T, long, long);
   }
 
@@ -63094,34 +63413,46 @@
   public class AtomicReference implements java.io.Serializable {
     ctor public AtomicReference(V);
     ctor public AtomicReference();
+    method public final V accumulateAndGet(V, java.util.function.BinaryOperator<V>);
     method public final boolean compareAndSet(V, V);
     method public final V get();
+    method public final V getAndAccumulate(V, java.util.function.BinaryOperator<V>);
     method public final V getAndSet(V);
+    method public final V getAndUpdate(java.util.function.UnaryOperator<V>);
     method public final void lazySet(V);
     method public final void set(V);
+    method public final V updateAndGet(java.util.function.UnaryOperator<V>);
     method public final boolean weakCompareAndSet(V, V);
   }
 
   public class AtomicReferenceArray implements java.io.Serializable {
     ctor public AtomicReferenceArray(int);
     ctor public AtomicReferenceArray(E[]);
+    method public final E accumulateAndGet(int, E, java.util.function.BinaryOperator<E>);
     method public final boolean compareAndSet(int, E, E);
     method public final E get(int);
+    method public final E getAndAccumulate(int, E, java.util.function.BinaryOperator<E>);
     method public final E getAndSet(int, E);
+    method public final E getAndUpdate(int, java.util.function.UnaryOperator<E>);
     method public final void lazySet(int, E);
     method public final int length();
     method public final void set(int, E);
+    method public final E updateAndGet(int, java.util.function.UnaryOperator<E>);
     method public final boolean weakCompareAndSet(int, E, E);
   }
 
   public abstract class AtomicReferenceFieldUpdater {
     ctor protected AtomicReferenceFieldUpdater();
+    method public final V accumulateAndGet(T, V, java.util.function.BinaryOperator<V>);
     method public abstract boolean compareAndSet(T, V, V);
     method public abstract V get(T);
+    method public final V getAndAccumulate(T, V, java.util.function.BinaryOperator<V>);
     method public V getAndSet(T, V);
+    method public final V getAndUpdate(T, java.util.function.UnaryOperator<V>);
     method public abstract void lazySet(T, V);
     method public static java.util.concurrent.atomic.AtomicReferenceFieldUpdater<U, W> newUpdater(java.lang.Class<U>, java.lang.Class<W>, java.lang.String);
     method public abstract void set(T, V);
+    method public final V updateAndGet(T, java.util.function.UnaryOperator<V>);
     method public abstract boolean weakCompareAndSet(T, V, V);
   }
 
@@ -63136,6 +63467,59 @@
     method public boolean weakCompareAndSet(V, V, int, int);
   }
 
+  public class DoubleAccumulator extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public DoubleAccumulator(java.util.function.DoubleBinaryOperator, double);
+    method public void accumulate(double);
+    method public double doubleValue();
+    method public float floatValue();
+    method public double get();
+    method public double getThenReset();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+  }
+
+  public class DoubleAdder extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public DoubleAdder();
+    method public void add(double);
+    method public double doubleValue();
+    method public float floatValue();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+    method public double sum();
+    method public double sumThenReset();
+  }
+
+  public class LongAccumulator extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public LongAccumulator(java.util.function.LongBinaryOperator, long);
+    method public void accumulate(long);
+    method public double doubleValue();
+    method public float floatValue();
+    method public long get();
+    method public long getThenReset();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+  }
+
+  public class LongAdder extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public LongAdder();
+    method public void add(long);
+    method public void decrement();
+    method public double doubleValue();
+    method public float floatValue();
+    method public void increment();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+    method public long sum();
+    method public long sumThenReset();
+  }
+
+   abstract class Striped64 extends java.lang.Number {
+  }
+
 }
 
 package java.util.concurrent.locks {
@@ -63343,6 +63727,34 @@
     method public void unlock();
   }
 
+  public class StampedLock implements java.io.Serializable {
+    ctor public StampedLock();
+    method public java.util.concurrent.locks.Lock asReadLock();
+    method public java.util.concurrent.locks.ReadWriteLock asReadWriteLock();
+    method public java.util.concurrent.locks.Lock asWriteLock();
+    method public int getReadLockCount();
+    method public boolean isReadLocked();
+    method public boolean isWriteLocked();
+    method public long readLock();
+    method public long readLockInterruptibly() throws java.lang.InterruptedException;
+    method public long tryConvertToOptimisticRead(long);
+    method public long tryConvertToReadLock(long);
+    method public long tryConvertToWriteLock(long);
+    method public long tryOptimisticRead();
+    method public long tryReadLock();
+    method public long tryReadLock(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public boolean tryUnlockRead();
+    method public boolean tryUnlockWrite();
+    method public long tryWriteLock();
+    method public long tryWriteLock(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public void unlock(long);
+    method public void unlockRead(long);
+    method public void unlockWrite(long);
+    method public boolean validate(long);
+    method public long writeLock();
+    method public long writeLockInterruptibly() throws java.lang.InterruptedException;
+  }
+
 }
 
 package java.util.function {
diff --git a/api/test-current.txt b/api/test-current.txt
index 9aed5e9..6a54f319 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -3442,7 +3442,7 @@
     method public android.view.View getCurrentFocus();
     method public android.app.FragmentManager getFragmentManager();
     method public android.content.Intent getIntent();
-    method public deprecated java.lang.Object getLastNonConfigurationInstance();
+    method public java.lang.Object getLastNonConfigurationInstance();
     method public android.view.LayoutInflater getLayoutInflater();
     method public android.app.LoaderManager getLoaderManager();
     method public java.lang.String getLocalClassName();
@@ -3543,7 +3543,7 @@
     method protected void onRestoreInstanceState(android.os.Bundle);
     method public void onRestoreInstanceState(android.os.Bundle, android.os.PersistableBundle);
     method protected void onResume();
-    method public deprecated java.lang.Object onRetainNonConfigurationInstance();
+    method public java.lang.Object onRetainNonConfigurationInstance();
     method protected void onSaveInstanceState(android.os.Bundle);
     method public void onSaveInstanceState(android.os.Bundle, android.os.PersistableBundle);
     method public boolean onSearchRequested(android.view.SearchEvent);
@@ -9463,6 +9463,7 @@
     method public int getShortcutIconResId(android.content.pm.ShortcutInfo, android.os.UserHandle);
     method public java.util.List<android.content.pm.ShortcutInfo> getShortcutInfo(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
     method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle);
+    method public boolean hasShortcutHostPermission();
     method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
     method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle);
     method public void pinShortcuts(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
@@ -10126,7 +10127,6 @@
     method public static deprecated android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public int describeContents();
-    method public int getChangingConfigurations();
     method public int getColorForState(int[], int);
     method public int getDefaultColor();
     method public boolean isOpaque();
@@ -10138,6 +10138,7 @@
 
   public abstract class ComplexColor {
     ctor public ComplexColor();
+    method public int getChangingConfigurations();
     method public abstract int getDefaultColor();
     method public boolean isStateful();
   }
@@ -13045,9 +13046,9 @@
     method public void setPaddingMode(int);
     method public void setPaddingRelative(int, int, int, int);
     method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+    field public static final int INSET_UNDEFINED = -2147483648; // 0x80000000
     field public static final int PADDING_MODE_NEST = 0; // 0x0
     field public static final int PADDING_MODE_STACK = 1; // 0x1
-    field public static final int UNDEFINED_INSET = -2147483648; // 0x80000000
   }
 
   public class LevelListDrawable extends android.graphics.drawable.DrawableContainer {
@@ -30832,6 +30833,7 @@
   public static class CallLog.Calls implements android.provider.BaseColumns {
     ctor public CallLog.Calls();
     method public static java.lang.String getLastOutgoingCall(android.content.Context);
+    field public static final int ANSWERED_EXTERNALLY_TYPE = 7; // 0x7
     field public static final int BLOCKED_TYPE = 6; // 0x6
     field public static final java.lang.String CACHED_FORMATTED_NUMBER = "formatted_number";
     field public static final java.lang.String CACHED_LOOKUP_URI = "lookup_uri";
@@ -30854,6 +30856,7 @@
     field public static final java.lang.String DURATION = "duration";
     field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.CALL_TYPE_FILTER";
     field public static final java.lang.String FEATURES = "features";
+    field public static final int FEATURES_PULLED_EXTERNALLY = 2; // 0x2
     field public static final int FEATURES_VIDEO = 1; // 0x1
     field public static final java.lang.String GEOCODED_LOCATION = "geocoded_location";
     field public static final int INCOMING_TYPE = 1; // 0x1
@@ -36130,9 +36133,11 @@
     method public void phoneAccountSelected(android.telecom.PhoneAccountHandle, boolean);
     method public void playDtmfTone(char);
     method public void postDialContinue(boolean);
+    method public void pullExternalCall();
     method public void registerCallback(android.telecom.Call.Callback);
     method public void registerCallback(android.telecom.Call.Callback, android.os.Handler);
     method public void reject(boolean, java.lang.String);
+    method public void sendCallEvent(java.lang.String, android.os.Bundle);
     method public void splitFromConference();
     method public void stopDtmfTone();
     method public void swapConference();
@@ -36146,6 +36151,7 @@
     field public static final int STATE_DISCONNECTING = 10; // 0xa
     field public static final int STATE_HOLDING = 3; // 0x3
     field public static final int STATE_NEW = 0; // 0x0
+    field public static final int STATE_PULLING_CALL = 11; // 0xb
     field public static final int STATE_RINGING = 2; // 0x2
     field public static final int STATE_SELECT_PHONE_ACCOUNT = 8; // 0x8
   }
@@ -36156,6 +36162,7 @@
     method public void onCannedTextResponsesLoaded(android.telecom.Call, java.util.List<java.lang.String>);
     method public void onChildrenChanged(android.telecom.Call, java.util.List<android.telecom.Call>);
     method public void onConferenceableCallsChanged(android.telecom.Call, java.util.List<android.telecom.Call>);
+    method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle);
     method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details);
     method public void onParentChanged(android.telecom.Call, android.telecom.Call);
     method public void onPostDialWait(android.telecom.Call, java.lang.String);
@@ -36186,6 +36193,7 @@
     method public static java.lang.String propertiesToString(int);
     field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 4194304; // 0x400000
     field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
+    field public static final int CAPABILITY_CAN_PULL_CALL = 8388608; // 0x800000
     field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
     field public static final int CAPABILITY_HOLD = 1; // 0x1
     field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
@@ -36205,6 +36213,7 @@
     field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 4; // 0x4
     field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2
     field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10
+    field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40
     field public static final int PROPERTY_WIFI = 8; // 0x8
     field public static final int PROPERTY_WORK_CALL = 32; // 0x20
   }
@@ -36319,15 +36328,19 @@
     method public void onAnswer(int);
     method public void onAnswer();
     method public void onCallAudioStateChanged(android.telecom.CallAudioState);
+    method public void onCallEvent(java.lang.String, android.os.Bundle);
     method public void onDisconnect();
     method public void onHold();
     method public void onPlayDtmfTone(char);
     method public void onPostDialContinue(boolean);
+    method public void onPullExternalCall();
     method public void onReject();
+    method public void onReject(java.lang.String);
     method public void onSeparate();
     method public void onStateChanged(int);
     method public void onStopDtmfTone();
     method public void onUnhold();
+    method public void sendConnectionEvent(java.lang.String, android.os.Bundle);
     method public final void setActive();
     method public final void setAddress(android.net.Uri, int);
     method public final void setAudioModeIsVoip(boolean);
@@ -36351,9 +36364,12 @@
     method public static java.lang.String stateToString(int);
     field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 8388608; // 0x800000
     field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
+    field public static final int CAPABILITY_CAN_PULL_CALL = 33554432; // 0x2000000
+    field public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 4194304; // 0x400000
     field public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 524288; // 0x80000
     field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
     field public static final int CAPABILITY_HOLD = 1; // 0x1
+    field public static final int CAPABILITY_IS_EXTERNAL_CALL = 16777216; // 0x1000000
     field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
     field public static final int CAPABILITY_MERGE_CONFERENCE = 4; // 0x4
     field public static final int CAPABILITY_MUTE = 64; // 0x40
@@ -36367,6 +36383,7 @@
     field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 2048; // 0x800
     field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2
     field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8
+    field public static final java.lang.String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED";
     field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
     field public static final java.lang.String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS";
     field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER";
@@ -36376,6 +36393,7 @@
     field public static final int STATE_HOLDING = 5; // 0x5
     field public static final int STATE_INITIALIZING = 0; // 0x0
     field public static final int STATE_NEW = 1; // 0x1
+    field public static final int STATE_PULLING_CALL = 7; // 0x7
     field public static final int STATE_RINGING = 2; // 0x2
   }
 
@@ -36453,7 +36471,9 @@
     method public java.lang.String getReason();
     method public int getTone();
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final int ANSWERED_ELSEWHERE = 11; // 0xb
     field public static final int BUSY = 7; // 0x7
+    field public static final int CALL_PULLED = 12; // 0xc
     field public static final int CANCELED = 4; // 0x4
     field public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10; // 0xa
     field public static final android.os.Parcelable.Creator<android.telecom.DisconnectCause> CREATOR;
@@ -36489,6 +36509,7 @@
     method public void onCallAudioStateChanged(android.telecom.CallAudioState);
     method public void onCallRemoved(android.telecom.Call);
     method public void onCanAddCallChanged(boolean);
+    method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle);
     method public void onSilenceRinger();
     method public final void setAudioRoute(int);
     method public final void setMuted(boolean);
@@ -36639,6 +36660,7 @@
     method public boolean isVoipAudioMode();
     method public void playDtmfTone(char);
     method public void postDialContinue(boolean);
+    method public void pullExternalCall();
     method public void registerCallback(android.telecom.RemoteConnection.Callback);
     method public void registerCallback(android.telecom.RemoteConnection.Callback, android.os.Handler);
     method public void reject();
@@ -36655,6 +36677,7 @@
     method public void onConferenceChanged(android.telecom.RemoteConnection, android.telecom.RemoteConference);
     method public void onConferenceableConnectionsChanged(android.telecom.RemoteConnection, java.util.List<android.telecom.RemoteConnection>);
     method public void onConnectionCapabilitiesChanged(android.telecom.RemoteConnection, int);
+    method public void onConnectionEvent(android.telecom.RemoteConnection, java.lang.String, android.os.Bundle);
     method public void onDestroyed(android.telecom.RemoteConnection);
     method public void onDisconnected(android.telecom.RemoteConnection, android.telecom.DisconnectCause);
     method public void onExtrasChanged(android.telecom.RemoteConnection, android.os.Bundle);
@@ -36752,6 +36775,7 @@
     field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
     field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
     field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
+    field public static final java.lang.String METADATA_INCLUDE_EXTERNAL_CALLS = "android.telecom.INCLUDE_EXTERNAL_CALLS";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI";
     field public static final int PRESENTATION_ALLOWED = 1; // 0x1
@@ -57418,6 +57442,7 @@
     method public void ensureCapacity(int);
     method public void forEach(java.util.function.Consumer<? super E>);
     method public E get(int);
+    method public boolean removeIf(java.util.function.Predicate<? super E>);
     method public int size();
     method public java.util.Spliterator<E> spliterator();
     method public void trimToSize();
@@ -57502,6 +57527,24 @@
     method public static int hashCode(float[]);
     method public static int hashCode(double[]);
     method public static int hashCode(java.lang.Object[]);
+    method public static void parallelSort(byte[]);
+    method public static void parallelSort(byte[], int, int);
+    method public static void parallelSort(char[]);
+    method public static void parallelSort(char[], int, int);
+    method public static void parallelSort(short[]);
+    method public static void parallelSort(short[], int, int);
+    method public static void parallelSort(int[]);
+    method public static void parallelSort(int[], int, int);
+    method public static void parallelSort(long[]);
+    method public static void parallelSort(long[], int, int);
+    method public static void parallelSort(float[]);
+    method public static void parallelSort(float[], int, int);
+    method public static void parallelSort(double[]);
+    method public static void parallelSort(double[], int, int);
+    method public static void parallelSort(T[]);
+    method public static void parallelSort(T[], int, int);
+    method public static void parallelSort(T[], java.util.Comparator<? super T>);
+    method public static void parallelSort(T[], int, int, java.util.Comparator<? super T>);
     method public static void sort(int[]);
     method public static void sort(int[], int, int);
     method public static void sort(long[]);
@@ -57689,6 +57732,7 @@
     method public abstract java.util.Iterator<E> iterator();
     method public abstract boolean remove(java.lang.Object);
     method public abstract boolean removeAll(java.util.Collection<?>);
+    method public default boolean removeIf(java.util.function.Predicate<? super E>);
     method public abstract boolean retainAll(java.util.Collection<?>);
     method public abstract int size();
     method public abstract java.lang.Object[] toArray();
@@ -58322,18 +58366,28 @@
 
   public abstract interface Map {
     method public abstract void clear();
+    method public default V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public default V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
+    method public default V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public abstract boolean containsKey(java.lang.Object);
     method public abstract boolean containsValue(java.lang.Object);
     method public abstract java.util.Set<java.util.Map.Entry<K, V>> entrySet();
     method public abstract boolean equals(java.lang.Object);
     method public default void forEach(java.util.function.BiConsumer<? super K, ? super V>);
     method public abstract V get(java.lang.Object);
+    method public default V getOrDefault(java.lang.Object, V);
     method public abstract int hashCode();
     method public abstract boolean isEmpty();
     method public abstract java.util.Set<K> keySet();
+    method public default V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
     method public abstract V put(K, V);
     method public abstract void putAll(java.util.Map<? extends K, ? extends V>);
+    method public default V putIfAbsent(K, V);
     method public abstract V remove(java.lang.Object);
+    method public default boolean remove(java.lang.Object, java.lang.Object);
+    method public default boolean replace(K, V, V);
+    method public default V replace(K, V);
+    method public default void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public abstract int size();
     method public abstract java.util.Collection<V> values();
   }
@@ -58341,6 +58395,8 @@
   public static abstract interface Map.Entry {
     method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey();
     method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey(java.util.Comparator<? super K>);
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue();
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue(java.util.Comparator<? super V>);
     method public abstract boolean equals(java.lang.Object);
     method public abstract K getKey();
     method public abstract V getValue();
@@ -59071,6 +59127,7 @@
     method public synchronized void removeAllElements();
     method public synchronized boolean removeElement(java.lang.Object);
     method public synchronized void removeElementAt(int);
+    method public synchronized boolean removeIf(java.util.function.Predicate<? super E>);
     method public synchronized void setElementAt(E, int);
     method public synchronized void setSize(int);
     method public synchronized int size();
@@ -59122,6 +59179,7 @@
     method public void put(E) throws java.lang.InterruptedException;
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -59185,6 +59243,78 @@
     ctor public CancellationException(java.lang.String);
   }
 
+  public class CompletableFuture implements java.util.concurrent.CompletionStage java.util.concurrent.Future {
+    ctor public CompletableFuture();
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Void> allOf(java.util.concurrent.CompletableFuture<?>...);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Object> anyOf(java.util.concurrent.CompletableFuture<?>...);
+    method public java.util.concurrent.CompletableFuture<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
+    method public boolean cancel(boolean);
+    method public boolean complete(T);
+    method public boolean completeExceptionally(java.lang.Throwable);
+    method public static java.util.concurrent.CompletableFuture<U> completedFuture(U);
+    method public java.util.concurrent.CompletableFuture<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>);
+    method public T get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
+    method public T get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
+    method public T getNow(T);
+    method public int getNumberOfDependents();
+    method public java.util.concurrent.CompletableFuture<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
+    method public boolean isCancelled();
+    method public boolean isCompletedExceptionally();
+    method public boolean isDone();
+    method public T join();
+    method public void obtrudeException(java.lang.Throwable);
+    method public void obtrudeValue(T);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBoth(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEither(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable, java.util.concurrent.Executor);
+    method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>);
+    method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<U> thenApply(java.util.function.Function<? super T, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRun(java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<T> toCompletableFuture();
+    method public java.util.concurrent.CompletableFuture<T> whenComplete(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public java.util.concurrent.CompletableFuture<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public java.util.concurrent.CompletableFuture<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>, java.util.concurrent.Executor);
+  }
+
+  public static abstract interface CompletableFuture.AsynchronousCompletionTask {
+  }
+
+  public class CompletionException extends java.lang.RuntimeException {
+    ctor protected CompletionException();
+    ctor protected CompletionException(java.lang.String);
+    ctor public CompletionException(java.lang.String, java.lang.Throwable);
+    ctor public CompletionException(java.lang.Throwable);
+  }
+
   public abstract interface CompletionService {
     method public abstract java.util.concurrent.Future<V> poll();
     method public abstract java.util.concurrent.Future<V> poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
@@ -59193,20 +59323,130 @@
     method public abstract java.util.concurrent.Future<V> take() throws java.lang.InterruptedException;
   }
 
+  public abstract interface CompletionStage {
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>);
+    method public abstract java.util.concurrent.CompletionStage<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBoth(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEither(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<U> thenApply(java.util.function.Function<? super T, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRun(java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletableFuture<T> toCompletableFuture();
+    method public abstract java.util.concurrent.CompletionStage<T> whenComplete(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public abstract java.util.concurrent.CompletionStage<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public abstract java.util.concurrent.CompletionStage<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>, java.util.concurrent.Executor);
+  }
+
   public class ConcurrentHashMap extends java.util.AbstractMap implements java.util.concurrent.ConcurrentMap java.io.Serializable {
     ctor public ConcurrentHashMap();
     ctor public ConcurrentHashMap(int);
     ctor public ConcurrentHashMap(java.util.Map<? extends K, ? extends V>);
     ctor public ConcurrentHashMap(int, float);
     ctor public ConcurrentHashMap(int, float, int);
+    method public V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
+    method public V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public boolean contains(java.lang.Object);
     method public java.util.Enumeration<V> elements();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
+    method public void forEach(long, java.util.function.BiConsumer<? super K, ? super V>);
+    method public void forEach(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.Consumer<? super U>);
+    method public void forEachEntry(long, java.util.function.Consumer<? super java.util.Map.Entry<K, V>>);
+    method public void forEachEntry(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.Consumer<? super U>);
+    method public void forEachKey(long, java.util.function.Consumer<? super K>);
+    method public void forEachKey(long, java.util.function.Function<? super K, ? extends U>, java.util.function.Consumer<? super U>);
+    method public void forEachValue(long, java.util.function.Consumer<? super V>);
+    method public void forEachValue(long, java.util.function.Function<? super V, ? extends U>, java.util.function.Consumer<? super U>);
+    method public V getOrDefault(java.lang.Object, V);
+    method public java.util.concurrent.ConcurrentHashMap.KeySetView<K, V> keySet(V);
     method public java.util.Enumeration<K> keys();
+    method public long mappingCount();
+    method public V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
+    method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet();
+    method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet(int);
     method public V putIfAbsent(K, V);
+    method public U reduce(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public java.util.Map.Entry<K, V> reduceEntries(long, java.util.function.BiFunction<java.util.Map.Entry<K, V>, java.util.Map.Entry<K, V>, ? extends java.util.Map.Entry<K, V>>);
+    method public U reduceEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public double reduceEntriesToDouble(long, java.util.function.ToDoubleFunction<java.util.Map.Entry<K, V>>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceEntriesToInt(long, java.util.function.ToIntFunction<java.util.Map.Entry<K, V>>, int, java.util.function.IntBinaryOperator);
+    method public long reduceEntriesToLong(long, java.util.function.ToLongFunction<java.util.Map.Entry<K, V>>, long, java.util.function.LongBinaryOperator);
+    method public K reduceKeys(long, java.util.function.BiFunction<? super K, ? super K, ? extends K>);
+    method public U reduceKeys(long, java.util.function.Function<? super K, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public double reduceKeysToDouble(long, java.util.function.ToDoubleFunction<? super K>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceKeysToInt(long, java.util.function.ToIntFunction<? super K>, int, java.util.function.IntBinaryOperator);
+    method public long reduceKeysToLong(long, java.util.function.ToLongFunction<? super K>, long, java.util.function.LongBinaryOperator);
+    method public double reduceToDouble(long, java.util.function.ToDoubleBiFunction<? super K, ? super V>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceToInt(long, java.util.function.ToIntBiFunction<? super K, ? super V>, int, java.util.function.IntBinaryOperator);
+    method public long reduceToLong(long, java.util.function.ToLongBiFunction<? super K, ? super V>, long, java.util.function.LongBinaryOperator);
+    method public V reduceValues(long, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
+    method public U reduceValues(long, java.util.function.Function<? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public double reduceValuesToDouble(long, java.util.function.ToDoubleFunction<? super V>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceValuesToInt(long, java.util.function.ToIntFunction<? super V>, int, java.util.function.IntBinaryOperator);
+    method public long reduceValuesToLong(long, java.util.function.ToLongFunction<? super V>, long, java.util.function.LongBinaryOperator);
     method public boolean remove(java.lang.Object, java.lang.Object);
     method public boolean replace(K, V, V);
     method public V replace(K, V);
+    method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public U search(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>);
+    method public U searchEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>);
+    method public U searchKeys(long, java.util.function.Function<? super K, ? extends U>);
+    method public U searchValues(long, java.util.function.Function<? super V, ? extends U>);
+  }
+
+   static abstract class ConcurrentHashMap.CollectionView implements java.util.Collection java.io.Serializable {
+    method public final void clear();
+    method public abstract boolean contains(java.lang.Object);
+    method public final boolean containsAll(java.util.Collection<?>);
+    method public java.util.concurrent.ConcurrentHashMap<K, V> getMap();
+    method public final boolean isEmpty();
+    method public abstract java.util.Iterator<E> iterator();
+    method public abstract boolean remove(java.lang.Object);
+    method public final boolean removeAll(java.util.Collection<?>);
+    method public final boolean retainAll(java.util.Collection<?>);
+    method public final int size();
+    method public final java.lang.Object[] toArray();
+    method public final T[] toArray(T[]);
+    method public final java.lang.String toString();
+  }
+
+  public static class ConcurrentHashMap.KeySetView extends java.util.concurrent.ConcurrentHashMap.CollectionView implements java.io.Serializable java.util.Set {
+    method public boolean add(K);
+    method public boolean addAll(java.util.Collection<? extends K>);
+    method public boolean contains(java.lang.Object);
+    method public void forEach(java.util.function.Consumer<? super K>);
+    method public V getMappedValue();
+    method public java.util.Iterator<K> iterator();
+    method public boolean remove(java.lang.Object);
+    method public java.util.Spliterator<K> spliterator();
   }
 
   public class ConcurrentLinkedDeque extends java.util.AbstractCollection implements java.util.Deque java.io.Serializable {
@@ -59236,6 +59476,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class ConcurrentLinkedQueue extends java.util.AbstractQueue implements java.util.Queue java.io.Serializable {
@@ -59246,6 +59487,7 @@
     method public E peek();
     method public E poll();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public abstract interface ConcurrentMap implements java.util.Map {
@@ -59277,6 +59519,9 @@
     method public K ceilingKey(K);
     method public java.util.concurrent.ConcurrentSkipListMap<K, V> clone();
     method public java.util.Comparator<? super K> comparator();
+    method public V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
+    method public V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public java.util.NavigableSet<K> descendingKeySet();
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> descendingMap();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
@@ -59284,6 +59529,8 @@
     method public K firstKey();
     method public java.util.Map.Entry<K, V> floorEntry(K);
     method public K floorKey(K);
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
+    method public V getOrDefault(java.lang.Object, V);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K, boolean);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K);
     method public java.util.Map.Entry<K, V> higherEntry(K);
@@ -59292,6 +59539,7 @@
     method public K lastKey();
     method public java.util.Map.Entry<K, V> lowerEntry(K);
     method public K lowerKey(K);
+    method public V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
     method public java.util.NavigableSet<K> navigableKeySet();
     method public java.util.Map.Entry<K, V> pollFirstEntry();
     method public java.util.Map.Entry<K, V> pollLastEntry();
@@ -59299,6 +59547,7 @@
     method public boolean remove(java.lang.Object, java.lang.Object);
     method public boolean replace(K, V, V);
     method public V replace(K, V);
+    method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> subMap(K, boolean, K, boolean);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> subMap(K, K);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> tailMap(K, boolean);
@@ -59326,6 +59575,7 @@
     method public E pollFirst();
     method public E pollLast();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public java.util.NavigableSet<E> subSet(E, boolean, E, boolean);
     method public java.util.NavigableSet<E> subSet(E, E);
     method public java.util.NavigableSet<E> tailSet(E, boolean);
@@ -59336,31 +59586,34 @@
     ctor public CopyOnWriteArrayList();
     ctor public CopyOnWriteArrayList(java.util.Collection<? extends E>);
     ctor public CopyOnWriteArrayList(E[]);
-    method public synchronized boolean add(E);
-    method public synchronized void add(int, E);
-    method public synchronized boolean addAll(java.util.Collection<? extends E>);
-    method public synchronized boolean addAll(int, java.util.Collection<? extends E>);
-    method public synchronized int addAllAbsent(java.util.Collection<? extends E>);
-    method public synchronized boolean addIfAbsent(E);
-    method public synchronized void clear();
+    method public boolean add(E);
+    method public void add(int, E);
+    method public boolean addAll(java.util.Collection<? extends E>);
+    method public boolean addAll(int, java.util.Collection<? extends E>);
+    method public int addAllAbsent(java.util.Collection<? extends E>);
+    method public boolean addIfAbsent(E);
+    method public void clear();
     method public java.lang.Object clone();
     method public boolean contains(java.lang.Object);
     method public boolean containsAll(java.util.Collection<?>);
+    method public void forEach(java.util.function.Consumer<? super E>);
     method public E get(int);
-    method public int indexOf(E, int);
     method public int indexOf(java.lang.Object);
+    method public int indexOf(E, int);
     method public boolean isEmpty();
     method public java.util.Iterator<E> iterator();
-    method public int lastIndexOf(E, int);
     method public int lastIndexOf(java.lang.Object);
-    method public java.util.ListIterator<E> listIterator(int);
+    method public int lastIndexOf(E, int);
     method public java.util.ListIterator<E> listIterator();
-    method public synchronized E remove(int);
-    method public synchronized boolean remove(java.lang.Object);
-    method public synchronized boolean removeAll(java.util.Collection<?>);
-    method public synchronized boolean retainAll(java.util.Collection<?>);
-    method public synchronized E set(int, E);
+    method public java.util.ListIterator<E> listIterator(int);
+    method public E remove(int);
+    method public boolean remove(java.lang.Object);
+    method public boolean removeAll(java.util.Collection<?>);
+    method public void replaceAll(java.util.function.UnaryOperator<E>);
+    method public boolean retainAll(java.util.Collection<?>);
+    method public E set(int, E);
     method public int size();
+    method public void sort(java.util.Comparator<? super E>);
     method public java.util.List<E> subList(int, int);
     method public java.lang.Object[] toArray();
     method public T[] toArray(T[]);
@@ -59369,8 +59622,11 @@
   public class CopyOnWriteArraySet extends java.util.AbstractSet implements java.io.Serializable {
     ctor public CopyOnWriteArraySet();
     ctor public CopyOnWriteArraySet(java.util.Collection<? extends E>);
+    method public void forEach(java.util.function.Consumer<? super E>);
     method public java.util.Iterator<E> iterator();
+    method public boolean removeIf(java.util.function.Predicate<? super E>);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class CountDownLatch {
@@ -59381,6 +59637,32 @@
     method public long getCount();
   }
 
+  public abstract class CountedCompleter extends java.util.concurrent.ForkJoinTask {
+    ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>, int);
+    ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>);
+    ctor protected CountedCompleter();
+    method public final void addToPendingCount(int);
+    method public final boolean compareAndSetPendingCount(int, int);
+    method public void complete(T);
+    method public abstract void compute();
+    method public final int decrementPendingCountUnlessZero();
+    method protected final boolean exec();
+    method public final java.util.concurrent.CountedCompleter<?> firstComplete();
+    method public final java.util.concurrent.CountedCompleter<?> getCompleter();
+    method public final int getPendingCount();
+    method public T getRawResult();
+    method public final java.util.concurrent.CountedCompleter<?> getRoot();
+    method public final void helpComplete(int);
+    method public final java.util.concurrent.CountedCompleter<?> nextComplete();
+    method public void onCompletion(java.util.concurrent.CountedCompleter<?>);
+    method public boolean onExceptionalCompletion(java.lang.Throwable, java.util.concurrent.CountedCompleter<?>);
+    method public final void propagateCompletion();
+    method public final void quietlyCompleteRoot();
+    method public final void setPendingCount(int);
+    method protected void setRawResult(T);
+    method public final void tryComplete();
+  }
+
   public class CyclicBarrier {
     ctor public CyclicBarrier(int, java.lang.Runnable);
     ctor public CyclicBarrier(int);
@@ -59471,6 +59753,8 @@
     method public static java.util.concurrent.ExecutorService newSingleThreadExecutor(java.util.concurrent.ThreadFactory);
     method public static java.util.concurrent.ScheduledExecutorService newSingleThreadScheduledExecutor();
     method public static java.util.concurrent.ScheduledExecutorService newSingleThreadScheduledExecutor(java.util.concurrent.ThreadFactory);
+    method public static java.util.concurrent.ExecutorService newWorkStealingPool(int);
+    method public static java.util.concurrent.ExecutorService newWorkStealingPool();
     method public static java.util.concurrent.Callable<T> privilegedCallable(java.util.concurrent.Callable<T>);
     method public static java.util.concurrent.Callable<T> privilegedCallableUsingCurrentClassLoader(java.util.concurrent.Callable<T>);
     method public static java.util.concurrent.ThreadFactory privilegedThreadFactory();
@@ -59484,11 +59768,13 @@
     ctor public ForkJoinPool(int, java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory, java.lang.Thread.UncaughtExceptionHandler, boolean);
     method public boolean awaitQuiescence(long, java.util.concurrent.TimeUnit);
     method public boolean awaitTermination(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public static java.util.concurrent.ForkJoinPool commonPool();
     method protected int drainTasksTo(java.util.Collection<? super java.util.concurrent.ForkJoinTask<?>>);
     method public void execute(java.util.concurrent.ForkJoinTask<?>);
     method public void execute(java.lang.Runnable);
     method public int getActiveThreadCount();
     method public boolean getAsyncMode();
+    method public static int getCommonPoolParallelism();
     method public java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory getFactory();
     method public int getParallelism();
     method public int getPoolSize();
@@ -59526,6 +59812,7 @@
     method public static java.util.concurrent.ForkJoinTask<T> adapt(java.lang.Runnable, T);
     method public static java.util.concurrent.ForkJoinTask<T> adapt(java.util.concurrent.Callable<? extends T>);
     method public boolean cancel(boolean);
+    method public final boolean compareAndSetForkJoinTaskTag(short, short);
     method public void complete(V);
     method public void completeExceptionally(java.lang.Throwable);
     method protected abstract boolean exec();
@@ -59533,6 +59820,7 @@
     method public final V get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
     method public final V get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
     method public final java.lang.Throwable getException();
+    method public final short getForkJoinTaskTag();
     method public static java.util.concurrent.ForkJoinPool getPool();
     method public static int getQueuedTaskCount();
     method public abstract V getRawResult();
@@ -59551,9 +59839,11 @@
     method protected static java.util.concurrent.ForkJoinTask<?> peekNextLocalTask();
     method protected static java.util.concurrent.ForkJoinTask<?> pollNextLocalTask();
     method protected static java.util.concurrent.ForkJoinTask<?> pollTask();
+    method public final void quietlyComplete();
     method public final void quietlyInvoke();
     method public final void quietlyJoin();
     method public void reinitialize();
+    method public final short setForkJoinTaskTag(short);
     method protected abstract void setRawResult(V);
     method public boolean tryUnfork();
   }
@@ -59627,6 +59917,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
     method public E takeFirst() throws java.lang.InterruptedException;
     method public E takeLast() throws java.lang.InterruptedException;
@@ -59647,6 +59938,7 @@
     method public void put(E) throws java.lang.InterruptedException;
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -59666,6 +59958,7 @@
     method public void put(E);
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
     method public void transfer(E) throws java.lang.InterruptedException;
     method public boolean tryTransfer(E);
@@ -59713,6 +60006,7 @@
     method public void put(E);
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -59816,6 +60110,7 @@
     method public void put(E) throws java.lang.InterruptedException;
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -59945,112 +60240,136 @@
   public class AtomicInteger extends java.lang.Number implements java.io.Serializable {
     ctor public AtomicInteger(int);
     ctor public AtomicInteger();
+    method public final int accumulateAndGet(int, java.util.function.IntBinaryOperator);
     method public final int addAndGet(int);
     method public final boolean compareAndSet(int, int);
     method public final int decrementAndGet();
     method public double doubleValue();
     method public float floatValue();
     method public final int get();
+    method public final int getAndAccumulate(int, java.util.function.IntBinaryOperator);
     method public final int getAndAdd(int);
     method public final int getAndDecrement();
     method public final int getAndIncrement();
     method public final int getAndSet(int);
+    method public final int getAndUpdate(java.util.function.IntUnaryOperator);
     method public final int incrementAndGet();
     method public int intValue();
     method public final void lazySet(int);
     method public long longValue();
     method public final void set(int);
+    method public final int updateAndGet(java.util.function.IntUnaryOperator);
     method public final boolean weakCompareAndSet(int, int);
   }
 
   public class AtomicIntegerArray implements java.io.Serializable {
     ctor public AtomicIntegerArray(int);
     ctor public AtomicIntegerArray(int[]);
+    method public final int accumulateAndGet(int, int, java.util.function.IntBinaryOperator);
     method public final int addAndGet(int, int);
     method public final boolean compareAndSet(int, int, int);
     method public final int decrementAndGet(int);
     method public final int get(int);
+    method public final int getAndAccumulate(int, int, java.util.function.IntBinaryOperator);
     method public final int getAndAdd(int, int);
     method public final int getAndDecrement(int);
     method public final int getAndIncrement(int);
     method public final int getAndSet(int, int);
+    method public final int getAndUpdate(int, java.util.function.IntUnaryOperator);
     method public final int incrementAndGet(int);
     method public final void lazySet(int, int);
     method public final int length();
     method public final void set(int, int);
+    method public final int updateAndGet(int, java.util.function.IntUnaryOperator);
     method public final boolean weakCompareAndSet(int, int, int);
   }
 
   public abstract class AtomicIntegerFieldUpdater {
     ctor protected AtomicIntegerFieldUpdater();
+    method public final int accumulateAndGet(T, int, java.util.function.IntBinaryOperator);
     method public int addAndGet(T, int);
     method public abstract boolean compareAndSet(T, int, int);
     method public int decrementAndGet(T);
     method public abstract int get(T);
+    method public final int getAndAccumulate(T, int, java.util.function.IntBinaryOperator);
     method public int getAndAdd(T, int);
     method public int getAndDecrement(T);
     method public int getAndIncrement(T);
     method public int getAndSet(T, int);
+    method public final int getAndUpdate(T, java.util.function.IntUnaryOperator);
     method public int incrementAndGet(T);
     method public abstract void lazySet(T, int);
     method public static java.util.concurrent.atomic.AtomicIntegerFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
     method public abstract void set(T, int);
+    method public final int updateAndGet(T, java.util.function.IntUnaryOperator);
     method public abstract boolean weakCompareAndSet(T, int, int);
   }
 
   public class AtomicLong extends java.lang.Number implements java.io.Serializable {
     ctor public AtomicLong(long);
     ctor public AtomicLong();
+    method public final long accumulateAndGet(long, java.util.function.LongBinaryOperator);
     method public final long addAndGet(long);
     method public final boolean compareAndSet(long, long);
     method public final long decrementAndGet();
     method public double doubleValue();
     method public float floatValue();
     method public final long get();
+    method public final long getAndAccumulate(long, java.util.function.LongBinaryOperator);
     method public final long getAndAdd(long);
     method public final long getAndDecrement();
     method public final long getAndIncrement();
     method public final long getAndSet(long);
+    method public final long getAndUpdate(java.util.function.LongUnaryOperator);
     method public final long incrementAndGet();
     method public int intValue();
     method public final void lazySet(long);
     method public long longValue();
     method public final void set(long);
+    method public final long updateAndGet(java.util.function.LongUnaryOperator);
     method public final boolean weakCompareAndSet(long, long);
   }
 
   public class AtomicLongArray implements java.io.Serializable {
     ctor public AtomicLongArray(int);
     ctor public AtomicLongArray(long[]);
+    method public final long accumulateAndGet(int, long, java.util.function.LongBinaryOperator);
     method public long addAndGet(int, long);
     method public final boolean compareAndSet(int, long, long);
     method public final long decrementAndGet(int);
     method public final long get(int);
+    method public final long getAndAccumulate(int, long, java.util.function.LongBinaryOperator);
     method public final long getAndAdd(int, long);
     method public final long getAndDecrement(int);
     method public final long getAndIncrement(int);
     method public final long getAndSet(int, long);
+    method public final long getAndUpdate(int, java.util.function.LongUnaryOperator);
     method public final long incrementAndGet(int);
     method public final void lazySet(int, long);
     method public final int length();
     method public final void set(int, long);
+    method public final long updateAndGet(int, java.util.function.LongUnaryOperator);
     method public final boolean weakCompareAndSet(int, long, long);
   }
 
   public abstract class AtomicLongFieldUpdater {
     ctor protected AtomicLongFieldUpdater();
+    method public final long accumulateAndGet(T, long, java.util.function.LongBinaryOperator);
     method public long addAndGet(T, long);
     method public abstract boolean compareAndSet(T, long, long);
     method public long decrementAndGet(T);
     method public abstract long get(T);
+    method public final long getAndAccumulate(T, long, java.util.function.LongBinaryOperator);
     method public long getAndAdd(T, long);
     method public long getAndDecrement(T);
     method public long getAndIncrement(T);
     method public long getAndSet(T, long);
+    method public final long getAndUpdate(T, java.util.function.LongUnaryOperator);
     method public long incrementAndGet(T);
     method public abstract void lazySet(T, long);
     method public static java.util.concurrent.atomic.AtomicLongFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
     method public abstract void set(T, long);
+    method public final long updateAndGet(T, java.util.function.LongUnaryOperator);
     method public abstract boolean weakCompareAndSet(T, long, long);
   }
 
@@ -60068,34 +60387,46 @@
   public class AtomicReference implements java.io.Serializable {
     ctor public AtomicReference(V);
     ctor public AtomicReference();
+    method public final V accumulateAndGet(V, java.util.function.BinaryOperator<V>);
     method public final boolean compareAndSet(V, V);
     method public final V get();
+    method public final V getAndAccumulate(V, java.util.function.BinaryOperator<V>);
     method public final V getAndSet(V);
+    method public final V getAndUpdate(java.util.function.UnaryOperator<V>);
     method public final void lazySet(V);
     method public final void set(V);
+    method public final V updateAndGet(java.util.function.UnaryOperator<V>);
     method public final boolean weakCompareAndSet(V, V);
   }
 
   public class AtomicReferenceArray implements java.io.Serializable {
     ctor public AtomicReferenceArray(int);
     ctor public AtomicReferenceArray(E[]);
+    method public final E accumulateAndGet(int, E, java.util.function.BinaryOperator<E>);
     method public final boolean compareAndSet(int, E, E);
     method public final E get(int);
+    method public final E getAndAccumulate(int, E, java.util.function.BinaryOperator<E>);
     method public final E getAndSet(int, E);
+    method public final E getAndUpdate(int, java.util.function.UnaryOperator<E>);
     method public final void lazySet(int, E);
     method public final int length();
     method public final void set(int, E);
+    method public final E updateAndGet(int, java.util.function.UnaryOperator<E>);
     method public final boolean weakCompareAndSet(int, E, E);
   }
 
   public abstract class AtomicReferenceFieldUpdater {
     ctor protected AtomicReferenceFieldUpdater();
+    method public final V accumulateAndGet(T, V, java.util.function.BinaryOperator<V>);
     method public abstract boolean compareAndSet(T, V, V);
     method public abstract V get(T);
+    method public final V getAndAccumulate(T, V, java.util.function.BinaryOperator<V>);
     method public V getAndSet(T, V);
+    method public final V getAndUpdate(T, java.util.function.UnaryOperator<V>);
     method public abstract void lazySet(T, V);
     method public static java.util.concurrent.atomic.AtomicReferenceFieldUpdater<U, W> newUpdater(java.lang.Class<U>, java.lang.Class<W>, java.lang.String);
     method public abstract void set(T, V);
+    method public final V updateAndGet(T, java.util.function.UnaryOperator<V>);
     method public abstract boolean weakCompareAndSet(T, V, V);
   }
 
@@ -60110,6 +60441,59 @@
     method public boolean weakCompareAndSet(V, V, int, int);
   }
 
+  public class DoubleAccumulator extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public DoubleAccumulator(java.util.function.DoubleBinaryOperator, double);
+    method public void accumulate(double);
+    method public double doubleValue();
+    method public float floatValue();
+    method public double get();
+    method public double getThenReset();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+  }
+
+  public class DoubleAdder extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public DoubleAdder();
+    method public void add(double);
+    method public double doubleValue();
+    method public float floatValue();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+    method public double sum();
+    method public double sumThenReset();
+  }
+
+  public class LongAccumulator extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public LongAccumulator(java.util.function.LongBinaryOperator, long);
+    method public void accumulate(long);
+    method public double doubleValue();
+    method public float floatValue();
+    method public long get();
+    method public long getThenReset();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+  }
+
+  public class LongAdder extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public LongAdder();
+    method public void add(long);
+    method public void decrement();
+    method public double doubleValue();
+    method public float floatValue();
+    method public void increment();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+    method public long sum();
+    method public long sumThenReset();
+  }
+
+   abstract class Striped64 extends java.lang.Number {
+  }
+
 }
 
 package java.util.concurrent.locks {
@@ -60317,6 +60701,34 @@
     method public void unlock();
   }
 
+  public class StampedLock implements java.io.Serializable {
+    ctor public StampedLock();
+    method public java.util.concurrent.locks.Lock asReadLock();
+    method public java.util.concurrent.locks.ReadWriteLock asReadWriteLock();
+    method public java.util.concurrent.locks.Lock asWriteLock();
+    method public int getReadLockCount();
+    method public boolean isReadLocked();
+    method public boolean isWriteLocked();
+    method public long readLock();
+    method public long readLockInterruptibly() throws java.lang.InterruptedException;
+    method public long tryConvertToOptimisticRead(long);
+    method public long tryConvertToReadLock(long);
+    method public long tryConvertToWriteLock(long);
+    method public long tryOptimisticRead();
+    method public long tryReadLock();
+    method public long tryReadLock(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public boolean tryUnlockRead();
+    method public boolean tryUnlockWrite();
+    method public long tryWriteLock();
+    method public long tryWriteLock(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public void unlock(long);
+    method public void unlockRead(long);
+    method public void unlockWrite(long);
+    method public boolean validate(long);
+    method public long writeLock();
+    method public long writeLockInterruptibly() throws java.lang.InterruptedException;
+  }
+
 }
 
 package java.util.function {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 6b67b95..a0a599e 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1976,15 +1976,13 @@
      * normal {@link #onSaveInstanceState(Bundle)} mechanism) even if this
      * function returns null.
      *
-     * @return Returns the object previously returned by
-     * {@link #onRetainNonConfigurationInstance()}.
-     *
-     * @deprecated Use the new {@link Fragment} API
+     * <p><strong>Note:</strong> For most cases you should use the {@link Fragment} API
      * {@link Fragment#setRetainInstance(boolean)} instead; this is also
-     * available on older platforms through the Android compatibility package.
+     * available on older platforms through the Android support libraries.
+     *
+     * @return the object previously returned by {@link #onRetainNonConfigurationInstance()}
      */
     @Nullable
-    @Deprecated
     public Object getLastNonConfigurationInstance() {
         return mLastNonConfigurationInstances != null
                 ? mLastNonConfigurationInstances.activity : null;
@@ -2035,12 +2033,12 @@
      * guarantee for {@link android.os.AsyncTask#doInBackground} since that is
      * running in a separate thread.)
      *
-     * @return Return any Object holding the desired state to propagate to the
-     * next activity instance.
-     *
-     * @deprecated Use the new {@link Fragment} API
+     * <p><strong>Note:</strong> For most cases you should use the {@link Fragment} API
      * {@link Fragment#setRetainInstance(boolean)} instead; this is also
-     * available on older platforms through the Android compatibility package.
+     * available on older platforms through the Android support libraries.
+     *
+     * @return any Object holding the desired state to propagate to the
+     *         next activity instance
      */
     public Object onRetainNonConfigurationInstance() {
         return null;
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 8b62ef9..811a05b 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2307,7 +2307,7 @@
 
         case KEYGUARD_GOING_AWAY_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
-            keyguardGoingAway(data.readInt() != 0, data.readInt() != 0);
+            keyguardGoingAway(data.readInt());
             reply.writeNoException();
             return true;
         }
@@ -5924,13 +5924,12 @@
         reply.recycle();
     }
 
-    public void keyguardGoingAway(boolean disableWindowAnimations,
-            boolean keyguardGoingToNotificationShade) throws RemoteException {
+    public void keyguardGoingAway(int flags)
+            throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(disableWindowAnimations ? 1 : 0);
-        data.writeInt(keyguardGoingToNotificationShade ? 1 : 0);
+        data.writeInt(flags);
         mRemote.transact(KEYGUARD_GOING_AWAY_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 094950b..f178455 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -777,15 +777,16 @@
 
     /**
      * Sets the bounds (window size) that the activity should be launched in.
+     * Rect position should be provided in pixels and in screen coordinates.
      * Set to null explicitly for fullscreen.
      * <p>
      * <strong>NOTE:<strong/> This value is ignored on devices that don't have
      * {@link android.content.pm.PackageManager#FEATURE_FREEFORM_WINDOW_MANAGEMENT} or
      * {@link android.content.pm.PackageManager#FEATURE_PICTURE_IN_PICTURE} enabled.
-     * @param launchBounds Launch bounds to use for the activity or null for fullscreen.
+     * @param screenSpacePixelRect Launch bounds to use for the activity or null for fullscreen.
      */
-    public ActivityOptions setLaunchBounds(@Nullable Rect launchBounds) {
-        mLaunchBounds = launchBounds != null ? new Rect(launchBounds) : null;
+    public ActivityOptions setLaunchBounds(@Nullable Rect screenSpacePixelRect) {
+        mLaunchBounds = screenSpacePixelRect != null ? new Rect(screenSpacePixelRect) : null;
         return this;
     }
 
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index cdbf598..8e87e26 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -475,8 +475,13 @@
 
     public void keyguardWaitingForActivityDrawn() throws RemoteException;
 
-    public void keyguardGoingAway(boolean disableWindowAnimations,
-            boolean keyguardGoingToNotificationShade) throws RemoteException;
+    /**
+     * Notify the system that the keyguard is going away.
+     *
+     * @param flags See {@link android.view.WindowManagerPolicy#KEYGUARD_GOING_AWAY_FLAG_TO_SHADE}
+     *              etc.
+     */
+    public void keyguardGoingAway(int flags) throws RemoteException;
 
     public boolean shouldUpRecreateTask(IBinder token, String destAffinity)
             throws RemoteException;
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index b8fc323..a03fd72 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -281,7 +281,7 @@
             addedPaths.addAll(newPaths);
         }
         synchronized (this) {
-            mClassLoader = createOrUpdateClassLoaderLocked(addedPaths);
+            createOrUpdateClassLoaderLocked(addedPaths);
             if (mResources != null) {
                 mResources = mActivityThread.getTopLevelResources(mResDir, mSplitResDirs,
                         mOverlayDirs, mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY,
@@ -402,101 +402,99 @@
                 }
             }
         }
-
-        final String zip = TextUtils.join(File.pathSeparator, outZipPaths);
     }
 
-    private ClassLoader createOrUpdateClassLoaderLocked(List<String> addedPaths) {
-        final ClassLoader classLoader;
-        if (mIncludeCode && !mPackageName.equals("android")) {
-            // Avoid the binder call when the package is the current application package.
-            // The activity manager will perform ensure that dexopt is performed before
-            // spinning up the process.
-            if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) {
-                VMRuntime.getRuntime().vmInstructionSet();
-                try {
-                    ActivityThread.getPackageManager().notifyPackageUse(mPackageName);
-                } catch (RemoteException re) {
-                    throw re.rethrowFromSystemServer();
-                }
+    private void createOrUpdateClassLoaderLocked(List<String> addedPaths) {
+        if (mPackageName.equals("android")) {
+            if (mClassLoader != null) {
+                // nothing to update
+                return;
             }
 
-            final List<String> zipPaths = new ArrayList<>();
-            final List<String> libPaths = new ArrayList<>();
-
-            if (mRegisterPackage) {
-                try {
-                    ActivityManagerNative.getDefault().addPackageDependency(mPackageName);
-                } catch (RemoteException e) {
-                    throw e.rethrowFromSystemServer();
-                }
-            }
-
-            makePaths(mActivityThread, mApplicationInfo, zipPaths, libPaths);
-            final String zip = TextUtils.join(File.pathSeparator, zipPaths);
-            final boolean isBundledApp = mApplicationInfo.isSystemApp()
-                    && !mApplicationInfo.isUpdatedSystemApp();
-            String libraryPermittedPath = mDataDir;
-            if (isBundledApp) {
-                // This is necessary to grant bundled apps access to
-                // libraries located in subdirectories of /system/lib
-                libraryPermittedPath += File.pathSeparator +
-                                        System.getProperty("java.library.path");
-            }
-            // DO NOT SHIP: this is a workaround for apps loading native libraries
-            // provided by 3rd party apps using absolute path instead of corresponding
-            // classloader; see http://b/26954419 for example.
-            if (mApplicationInfo.targetSdkVersion <= 23) {
-                libraryPermittedPath += File.pathSeparator + "/data/app";
-            }
-            // -----------------------------------------------------------------------------
-
-            final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
-
-            /*
-             * With all the combination done (if necessary, actually
-             * create the class loader.
-             */
-
-            if (ActivityThread.localLOGV)
-                Slog.v(ActivityThread.TAG, "Class path: " + zip +
-                        ", JNI path: " + librarySearchPath);
-
-            if (mClassLoader == null) {
-                // Temporarily disable logging of disk reads on the Looper thread
-                // as this is early and necessary.
-                StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
-
-                classLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
-                        mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
-                        libraryPermittedPath, mBaseClassLoader);
-
-                StrictMode.setThreadPolicy(oldPolicy);
-            } else if (addedPaths != null && addedPaths.size() > 0) {
-                final String add = TextUtils.join(File.pathSeparator, addedPaths);
-                ApplicationLoaders.getDefault().addPath(mClassLoader, add);
-                classLoader = mClassLoader;
+            if (mBaseClassLoader != null) {
+                mClassLoader = mBaseClassLoader;
             } else {
-                classLoader = mClassLoader;
+                mClassLoader = ClassLoader.getSystemClassLoader();
             }
-        } else {
-            if (mClassLoader == null) {
-                if (mBaseClassLoader == null) {
-                    classLoader = ClassLoader.getSystemClassLoader();
-                } else {
-                    classLoader = mBaseClassLoader;
-                }
-            } else {
-                classLoader = mClassLoader;
+
+            return;
+        }
+
+        // Avoid the binder call when the package is the current application package.
+        // The activity manager will perform ensure that dexopt is performed before
+        // spinning up the process.
+        if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) {
+            VMRuntime.getRuntime().vmInstructionSet();
+            try {
+                ActivityThread.getPackageManager().notifyPackageUse(mPackageName);
+            } catch (RemoteException re) {
+                throw re.rethrowFromSystemServer();
             }
         }
-        return classLoader;
+
+        final List<String> zipPaths = new ArrayList<>();
+        final List<String> libPaths = new ArrayList<>();
+
+        if (mRegisterPackage) {
+            try {
+                ActivityManagerNative.getDefault().addPackageDependency(mPackageName);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        makePaths(mActivityThread, mApplicationInfo, zipPaths, libPaths);
+        final String zip = mIncludeCode ? TextUtils.join(File.pathSeparator, zipPaths) : "";
+        final boolean isBundledApp = mApplicationInfo.isSystemApp()
+                && !mApplicationInfo.isUpdatedSystemApp();
+        String libraryPermittedPath = mDataDir;
+        if (isBundledApp) {
+            // This is necessary to grant bundled apps access to
+            // libraries located in subdirectories of /system/lib
+            libraryPermittedPath += File.pathSeparator +
+                                    System.getProperty("java.library.path");
+        }
+        // DO NOT SHIP: this is a workaround for apps loading native libraries
+        // provided by 3rd party apps using absolute path instead of corresponding
+        // classloader; see http://b/26954419 for example.
+        if (mApplicationInfo.targetSdkVersion <= 23) {
+            libraryPermittedPath += File.pathSeparator + "/data/app";
+        }
+        // -----------------------------------------------------------------------------
+
+        final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
+
+        /*
+         * With all the combination done (if necessary, actually
+         * create the class loader.
+         */
+
+        if (ActivityThread.localLOGV)
+            Slog.v(ActivityThread.TAG, "Class path: " + zip +
+                    ", JNI path: " + librarySearchPath);
+
+        if (mClassLoader == null) {
+            // Temporarily disable logging of disk reads on the Looper thread
+            // as this is early and necessary.
+            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
+
+            mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
+                    mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
+                    libraryPermittedPath, mBaseClassLoader);
+
+            StrictMode.setThreadPolicy(oldPolicy);
+        }
+
+        if (addedPaths != null && addedPaths.size() > 0) {
+            final String add = TextUtils.join(File.pathSeparator, addedPaths);
+            ApplicationLoaders.getDefault().addPath(mClassLoader, add);
+        }
     }
 
     public ClassLoader getClassLoader() {
         synchronized (this) {
             if (mClassLoader == null) {
-                mClassLoader = createOrUpdateClassLoaderLocked(null /*addedPaths*/);
+                createOrUpdateClassLoaderLocked(null /*addedPaths*/);
             }
             return mClassLoader;
         }
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index a34e8551e..3be2cdc 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -284,10 +284,11 @@
     public static final String EXTRA_BUGREPORT_HASH = "android.app.extra.BUGREPORT_HASH";
 
     /**
-     * An {@code int} failure code representing the reason of the bugreport failure.
+     * An {@code int} failure code representing the reason of the bugreport failure. One of
+     * {@link #BUGREPORT_FAILURE_FAILED_COMPLETING}
+     * or {@link #BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE}
      *
      * @see #ACTION_BUGREPORT_FAILED
-     * @see #BUGREPORT_FAILURE_FAILED_COMPLETING, #BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE
      * @hide
      */
     public static final String EXTRA_BUGREPORT_FAILURE_REASON =
@@ -305,9 +306,24 @@
         BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE
     })
     public @interface BugreportFailureCode {}
-    /** Bugreport completion process failed. */
+
+    /**
+     * Bugreport completion process failed.
+     *
+     * <p>If this error code is received, the requesting of bugreport can be retried.
+     * @see DevicePolicyManager#requestBugreport
+     */
     public static final int BUGREPORT_FAILURE_FAILED_COMPLETING = 0;
-    /** Bugreport is no longer available for collection. */
+
+    /**
+     * Bugreport has been created, but is no longer available for collection.
+     *
+     * <p>This error likely occurs because the user of the device hasn't consented to share
+     * the bugreport for a long period after its creation.
+     *
+     * <p>If this error code is received, the requesting of bugreport can be retried.
+     * @see DevicePolicyManager#requestBugreport
+     */
     public static final int BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE = 1;
 
     /** @hide */
@@ -598,7 +614,8 @@
      * @param context The running context as per {@link #onReceive}.
      * @param intent The received intent as per {@link #onReceive}.
      * @param failureCode int containing failure code. One of
-     * #BUGREPORT_FAILURE_FAILED_COMPLETING or #BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE
+     * {@link #BUGREPORT_FAILURE_FAILED_COMPLETING}
+     * or {@link #BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE}
      * @see DevicePolicyManager#requestBugreport
      */
     public void onBugreportFailed(Context context, Intent intent,
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index 61b40d4..c934ca8 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -16,6 +16,7 @@
 
 package android.app.admin;
 
+import android.content.Intent;
 import android.os.UserHandle;
 
 import java.util.List;
@@ -80,4 +81,15 @@
      * @return true if package has a device or profile owner, false otherwise.
      */
     public abstract boolean hasDeviceOwnerOrProfileOwner(String packageName, int userId);
+
+    /**
+     * Creates an intent to show the admin support dialog to let the user know that the package is
+     * suspended by the admin. This assumes that {@param packageName} is suspended by the
+     * device/profile owner. The caller should check if the package is suspended or not.
+     *
+     * @param packageName The package that is suspended
+     * @param userId The user having the suspended package.
+     * @return The intent to trigger the admin support dialog.
+     */
+    public abstract Intent createPackageSuspendedDialogIntent(String packageName, int userId);
 }
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index b1d3f20..7b57872 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -58,4 +58,6 @@
     int getShortcutIconResId(String callingPackage, in ShortcutInfo shortcut, in UserHandle user);
     ParcelFileDescriptor getShortcutIconFd(String callingPackage, in ShortcutInfo shortcut,
             in UserHandle user);
+
+    boolean hasShortcutHostPermission(String callingPackage);
 }
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index a6a732e..8d43c44 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -16,11 +16,9 @@
 
 package android.content.pm;
 
-import android.Manifest.permission;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -30,7 +28,6 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -159,6 +156,9 @@
          * Indicates that one or more shortcuts (which may be dynamic and/or pinned)
          * have been added, updated or removed.
          *
+         * <p>Only the applications that are allowed to access the shortcut information,
+         * as defined in {@link #hasShortcutHostPermission()}, will receive it.
+         *
          * @param packageName The name of the package that has the shortcuts.
          * @param shortcuts all shortcuts from the package (dynamic and/or pinned).
          * @param user The UserHandle of the profile that generated the change.
@@ -395,16 +395,34 @@
     }
 
     /**
+     * Returns whether the caller can access the shortcut information.
+     *
+     * <p>Only the default launcher can access the shortcut information.
+     *
+     * <p>Note when this method returns {@code false}, that may be a temporary situation because
+     * the user is trying a new launcher application.  The user may decide to change the default
+     * launcher to the calling application again, so even if a launcher application loses
+     * this permission, it does <b>not</b> have to purge pinned shortcut information.
+     */
+    public boolean hasShortcutHostPermission() {
+        try {
+            return mService.hasShortcutHostPermission(mContext.getPackageName());
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Returns the IDs of {@link ShortcutInfo}s that match {@code query}.
      *
-     * <p>Callers mut have the {@link permission#BIND_APPWIDGET} permission.
+     * <p>Callers must be allowed to access the shortcut information, as defined in {@link
+     * #hasShortcutHostPermission()}.
      *
      * @param query result includes shortcuts matching this query.
      * @param user The UserHandle of the profile.
      *
      * @return the IDs of {@link ShortcutInfo}s that match the query.
      */
-    @RequiresPermission(permission.BIND_APPWIDGET)
     @Nullable
     public List<ShortcutInfo> getShortcuts(@NonNull ShortcutQuery query,
             @NonNull UserHandle user) {
@@ -420,7 +438,8 @@
     /**
      * Returns {@link ShortcutInfo}s with the given IDs from a package.
      *
-     * <p>Callers mut have the {@link permission#BIND_APPWIDGET} permission.
+     * <p>Callers must be allowed to access the shortcut information, as defined in {@link
+     * #hasShortcutHostPermission()}.
      *
      * @param packageName The target package.
      * @param ids IDs of the shortcuts to retrieve.
@@ -428,7 +447,6 @@
      *
      * @return list of {@link ShortcutInfo} associated with the package.
      */
-    @RequiresPermission(permission.BIND_APPWIDGET)
     @Nullable
     public List<ShortcutInfo> getShortcutInfo(@NonNull String packageName,
             @NonNull List<String> ids, @NonNull UserHandle user) {
@@ -447,13 +465,13 @@
      * <p>This API is <b>NOT</b> cumulative; this will replace all pinned shortcuts for the package.
      * However, different launchers may have different set of pinned shortcuts.
      *
-     * <p>Callers must have the {@link permission#BIND_APPWIDGET} permission.
+     * <p>Callers must be allowed to access the shortcut information, as defined in {@link
+     * #hasShortcutHostPermission()}.
      *
      * @param packageName The target package name.
      * @param shortcutIds The IDs of the shortcut to be pinned.
      * @param user The UserHandle of the profile.
      */
-    @RequiresPermission(permission.BIND_APPWIDGET)
     public void pinShortcuts(@NonNull String packageName, @NonNull List<String> shortcutIds,
             @NonNull UserHandle user) {
         try {
@@ -467,12 +485,12 @@
      * Return the icon resource ID, if {@code shortcut} has one
      * (i.e. when {@link ShortcutInfo#hasIconResource()} returns {@code true}).
      *
-     * <p>Callers mut have the {@link permission#BIND_APPWIDGET} permission.
+     * <p>Callers must be allowed to access the shortcut information, as defined in {@link
+     * #hasShortcutHostPermission()}.
      *
      * @param shortcut The target shortcut.
      * @param user The UserHandle of the profile.
      */
-    @RequiresPermission(permission.BIND_APPWIDGET)
     public int getShortcutIconResId(@NonNull ShortcutInfo shortcut, @NonNull UserHandle user) {
         try {
             return mService.getShortcutIconResId(mContext.getPackageName(), shortcut, user);
@@ -485,12 +503,12 @@
      * Return the icon as {@link ParcelFileDescriptor}, when it's stored as a file
      * (i.e. when {@link ShortcutInfo#hasIconFile()} returns {@code true}).
      *
-     * <p>Callers mut have the {@link permission#BIND_APPWIDGET} permission.
+     * <p>Callers must be allowed to access the shortcut information, as defined in {@link
+     * #hasShortcutHostPermission()}.
      *
      * @param shortcut The target shortcut.
      * @param user The UserHandle of the profile.
      */
-    @RequiresPermission(permission.BIND_APPWIDGET)
     public ParcelFileDescriptor getShortcutIconFd(
             @NonNull ShortcutInfo shortcut, @NonNull UserHandle user) {
         try {
@@ -503,7 +521,8 @@
     /**
      * Launches a shortcut.
      *
-     * <p>Callers mut have the {@link permission#BIND_APPWIDGET} permission.
+     * <p>Callers must be allowed to access the shortcut information, as defined in {@link
+     * #hasShortcutHostPermission()}.
      *
      * @param packageName The target shortcut package name.
      * @param shortcutId The target shortcut ID.
@@ -513,7 +532,6 @@
      * @return {@code false} when the shortcut is no longer valid (e.g. the creator application
      *   has been uninstalled). {@code true} when the shortcut is still valid.
      */
-    @RequiresPermission(permission.BIND_APPWIDGET)
     public boolean startShortcut(@NonNull String packageName, @NonNull String shortcutId,
             @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions,
             @NonNull UserHandle user) {
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 0f5ec91..6f2786a 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1054,8 +1054,12 @@
 
         /** {@hide} */
         @SystemApi
-        public void setInstallFlagsDowngrade() {
-            installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
+        public void setAllowDowngrade(boolean allowDowngrade) {
+            if (allowDowngrade) {
+                installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
+            } else {
+                installFlags &= ~PackageManager.INSTALL_ALLOW_DOWNGRADE;
+            }
         }
 
         /** {@hide} */
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 89f2fc4..13ebb82 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -16,6 +16,7 @@
 
 package android.content.pm;
 
+import android.content.ComponentName;
 import android.content.pm.PackageManager.NameNotFoundException;
 
 import java.util.List;
@@ -140,4 +141,10 @@
      *             found on the system.
      */
     public abstract ApplicationInfo getApplicationInfo(String packageName, int userId);
+
+    /**
+     * Interface to {@link com.android.server.pm.PackageManagerService#getHomeActivitiesAsUser}.
+     */
+    public abstract ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates,
+            int userId);
 }
diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java
index 918c763..7c764aa 100644
--- a/core/java/android/content/pm/ShortcutServiceInternal.java
+++ b/core/java/android/content/pm/ShortcutServiceInternal.java
@@ -63,4 +63,6 @@
 
     public abstract ParcelFileDescriptor getShortcutIconFd(@NonNull String callingPackage,
             @NonNull ShortcutInfo shortcut, int userId);
+
+    public abstract boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId);
 }
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 5bf2e3e..fb5bfd3 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -442,7 +442,7 @@
      * @see android.content.pm.ActivityInfo
      */
     public @Config int getChangingConfigurations() {
-        return mChangingConfigurations;
+        return super.getChangingConfigurations() | mChangingConfigurations;
     }
 
     private int modulateColorAlpha(int baseColor, float alphaMod) {
diff --git a/core/java/android/content/res/ComplexColor.java b/core/java/android/content/res/ComplexColor.java
index d96ec62..b297764 100644
--- a/core/java/android/content/res/ComplexColor.java
+++ b/core/java/android/content/res/ComplexColor.java
@@ -25,6 +25,8 @@
  * {@link android.content.res.ColorStateList} or {@link android.content.res.GradientColor}
  */
 public abstract class ComplexColor {
+    private int mChangingConfigurations;
+
     /**
      * @return {@code true}  if this ComplexColor changes color based on state, {@code false}
      * otherwise.
@@ -52,4 +54,24 @@
      * @hide only for resource preloading
      */
     public abstract ComplexColor obtainForTheme(Theme t);
+
+    /**
+     * @hide only for resource preloading
+     */
+    final void setBaseChangingConfigurations(int changingConfigurations) {
+        mChangingConfigurations = changingConfigurations;
+    }
+
+    /**
+     * Returns a mask of the configuration parameters for which this color
+     * may change, requiring that it be re-created.
+     *
+     * @return a mask of the changing configuration parameters, as defined by
+     *         {@link android.content.pm.ActivityInfo}
+     *
+     * @see android.content.pm.ActivityInfo
+     */
+    public int getChangingConfigurations() {
+        return mChangingConfigurations;
+    }
 }
diff --git a/core/java/android/content/res/GradientColor.java b/core/java/android/content/res/GradientColor.java
index 3291340..f29656a 100644
--- a/core/java/android/content/res/GradientColor.java
+++ b/core/java/android/content/res/GradientColor.java
@@ -542,6 +542,19 @@
         return clone;
     }
 
+    /**
+     * Returns a mask of the configuration parameters for which this gradient
+     * may change, requiring that it be re-created.
+     *
+     * @return a mask of the changing configuration parameters, as defined by
+     *         {@link android.content.pm.ActivityInfo}
+     *
+     * @see android.content.pm.ActivityInfo
+     */
+    public int getChangingConfigurations() {
+        return super.getChangingConfigurations() | mChangingConfigurations;
+    }
+
     private void applyTheme(Theme t) {
         if (mThemeAttrs != null) {
             applyRootAttrsTheme(t);
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 90037f7..a364010 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -713,9 +713,11 @@
         }
 
         if (complexColor != null) {
+            complexColor.setBaseChangingConfigurations(value.changingConfigurations);
+
             if (mPreloading) {
-                if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
-                        "color")) {
+                if (verifyPreloadConfig(complexColor.getChangingConfigurations(),
+                        0, value.resourceId, "color")) {
                     sPreloadedComplexColors.put(key, complexColor.getConstantState());
                 }
             } else {
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 2826882..6b79a8a 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -2269,8 +2269,9 @@
     public void onExtractedDeleteText(int start, int end) {
         InputConnection conn = getCurrentInputConnection();
         if (conn != null) {
+            conn.finishComposingText();
             conn.setSelection(start, start);
-            conn.deleteSurroundingText(0, end-start);
+            conn.deleteSurroundingText(0, end - start);
         }
     }
 
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index e7c4a07..e2ae133 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -179,6 +179,7 @@
          * <li>{@link #VOICEMAIL_TYPE}</li>
          * <li>{@link #REJECTED_TYPE}</li>
          * <li>{@link #BLOCKED_TYPE}</li>
+         * <li>{@link #ANSWERED_EXTERNALLY_TYPE}</li>
          * </ul>
          * </p>
          */
@@ -196,6 +197,12 @@
         public static final int REJECTED_TYPE = 5;
         /** Call log type for calls blocked automatically. */
         public static final int BLOCKED_TYPE = 6;
+        /**
+         * Call log type for a call which was answered on another device.  Used in situations where
+         * a call rings on multiple devices simultaneously and it ended up being answered on a
+         * device other than the current one.
+         */
+        public static final int ANSWERED_EXTERNALLY_TYPE = 7;
 
         /**
          * Bit-mask describing features of the call (e.g. video).
@@ -207,6 +214,9 @@
         /** Call had video. */
         public static final int FEATURES_VIDEO = 0x1;
 
+        /** Call was pulled externally. */
+        public static final int FEATURES_PULLED_EXTERNALLY = 0x2;
+
         /**
          * The phone number as the user entered it.
          * <P>Type: TEXT</P>
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index fb6a9d5..22d5ed8 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.IntDef;
 import android.annotation.RequiresPermission;
 import android.content.Context;
 import android.content.res.CompatibilityInfo;
@@ -31,6 +32,8 @@
 import android.util.DisplayMetrics;
 import android.util.Log;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
 
 import static android.Manifest.permission.CONFIGURE_DISPLAY_COLOR_TRANSFORM;
@@ -715,6 +718,14 @@
     }
 
     /**
+     * Returns the display's HDR capabilities.
+     * @hide
+     */
+    public HdrCapabilities getHdrCapabilities() {
+        return new HdrCapabilities();
+    }
+
+    /**
      * Gets the supported color transforms of this device.
      * @hide
      */
@@ -1112,6 +1123,117 @@
     }
 
     /**
+     * Encapsulates the HDR capabilities of a given display.
+     * For example, what HDR types it supports and details about the desired luminance data.
+     * <p>You can get an instance for a given {@link Display} object with
+     * {@link Display#getHdrCapabilities getHdrCapabilities()}.
+     * @hide
+     */
+    public static final class HdrCapabilities implements Parcelable {
+        /**
+         * Invalid luminance value.
+         */
+        public static final float INVALID_LUMINANCE = -1;
+        /**
+         * Dolby Vision high dynamic range (HDR) display.
+         */
+        public static final int HDR_TYPE_DOLBY_VISION = 1;
+        /**
+         * HDR10 display.
+         */
+        public static final int HDR_TYPE_HDR10 = 2;
+        /**
+         * Hybrid Log-Gamma HDR display.
+         */
+        public static final int HDR_TYPE_HLG = 3;
+
+        @IntDef({
+            HDR_TYPE_DOLBY_VISION,
+            HDR_TYPE_HDR10,
+            HDR_TYPE_HLG,
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface HdrType {}
+
+        private @HdrType int[] mSupportedHdrTypes = new int[0];
+        private float mMaxLuminance = INVALID_LUMINANCE;
+        private float mMaxAverageLuminance = INVALID_LUMINANCE;
+        private float mMinLuminance = INVALID_LUMINANCE;
+
+        public HdrCapabilities() {
+        }
+
+        /**
+         * Gets the supported HDR types of this display.
+         * Returns empty array if HDR is not supported by the display.
+         */
+        public @HdrType int[] getSupportedHdrTypes() {
+            return mSupportedHdrTypes;
+        }
+        /**
+         * Returns the desired content max luminance data in cd/m2 for this display.
+         */
+        public float getDesiredMaxLuminance() {
+            return mMaxLuminance;
+        }
+        /**
+         * Returns the desired content max frame-average luminance data in cd/m2 for this display.
+         */
+        public float getDesiredMaxAverageLuminance() {
+            return mMaxAverageLuminance;
+        }
+        /**
+         * Returns the desired content min luminance data in cd/m2 for this display.
+         */
+        public float getDesiredMinLuminance() {
+            return mMinLuminance;
+        }
+
+        public static final Creator<HdrCapabilities> CREATOR = new Creator<HdrCapabilities>() {
+            @Override
+            public HdrCapabilities createFromParcel(Parcel source) {
+                return new HdrCapabilities(source);
+            }
+
+            @Override
+            public HdrCapabilities[] newArray(int size) {
+                return new HdrCapabilities[size];
+            }
+        };
+
+        private HdrCapabilities(Parcel source) {
+            readFromParcel(source);
+        }
+
+        public void readFromParcel(Parcel source) {
+            int types = source.readInt();
+            mSupportedHdrTypes = new int[types];
+            for (int i = 0; i < types; ++i) {
+                mSupportedHdrTypes[i] = source.readInt();
+            }
+            mMaxLuminance = source.readFloat();
+            mMaxAverageLuminance = source.readFloat();
+            mMinLuminance = source.readFloat();
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeInt(mSupportedHdrTypes.length);
+            for (int i = 0; i < mSupportedHdrTypes.length; ++i) {
+                dest.writeInt(mSupportedHdrTypes[i]);
+            }
+            dest.writeFloat(mMaxLuminance);
+            dest.writeFloat(mMaxAverageLuminance);
+            dest.writeFloat(mMinLuminance);
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+    }
+
+    /**
      * A color transform supported by a given display.
      *
      * @see Display#getSupportedColorTransforms()
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index f912e51..d8b7421 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -193,8 +193,7 @@
     boolean isKeyguardSecure();
     boolean inKeyguardRestrictedInputMode();
     void dismissKeyguard();
-    void keyguardGoingAway(boolean disableWindowAnimations,
-            boolean keyguardGoingToNotificationShade);
+    void keyguardGoingAway(int flags);
 
     void closeSystemDialogs(String reason);
 
diff --git a/core/java/android/view/ViewOverlay.java b/core/java/android/view/ViewOverlay.java
index 69c30ba..b770bd5 100644
--- a/core/java/android/view/ViewOverlay.java
+++ b/core/java/android/view/ViewOverlay.java
@@ -216,6 +216,9 @@
         public void clear() {
             removeAllViews();
             if (mDrawables != null) {
+                for (Drawable drawable : mDrawables) {
+                    drawable.setCallback(null);
+                }
                 mDrawables.clear();
             }
         }
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 34e81fc..c1392fe 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -91,6 +91,11 @@
     public final static int FLAG_INTERACTIVE = 0x20000000;
     public final static int FLAG_PASS_TO_USER = 0x40000000;
 
+    // Flags for IActivityManager.keyguardGoingAway()
+    public final static int KEYGUARD_GOING_AWAY_FLAG_TO_SHADE = 1 << 0;
+    public final static int KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS = 1 << 1;
+    public final static int KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER = 1 << 2;
+
     // Flags used for indicating whether the internal and/or external input devices
     // of some type are available.
     public final static int PRESENCE_INTERNAL = 1 << 0;
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 3b6ba3a..4bcb406 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -18,6 +18,7 @@
 
 import android.R;
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.PendingIntent;
 import android.app.PendingIntent.CanceledException;
@@ -216,6 +217,7 @@
     boolean mInBatchEditControllers;
     boolean mShowSoftInputOnFocus = true;
     private boolean mPreserveSelection;
+    private boolean mRestartActionModeOnNextRefresh;
     boolean mTemporaryDetach;
 
     boolean mIsBeingLongClicked;
@@ -380,9 +382,8 @@
         updateSpellCheckSpans(0, mTextView.getText().length(),
                 true /* create the spell checker if needed */);
 
-        if (mTextView.getSelectionStart() != mTextView.getSelectionEnd()) {
-            // We had an active selection from before, start the selection mode.
-            startSelectionActionMode();
+        if (mTextView.hasSelection()) {
+            refreshTextActionMode();
         }
 
         getPositionListener().addSubscriber(mCursorAnchorInfoNotifier, true);
@@ -1081,6 +1082,10 @@
     }
 
     private void startDragAndDrop() {
+        // TODO: Fix drag and drop in full screen extracted mode.
+        if (mTextView.isInExtractedMode()) {
+            return;
+        }
         final int start = mTextView.getSelectionStart();
         final int end = mTextView.getSelectionEnd();
         CharSequence selectedText = mTextView.getTransformedText(start, end);
@@ -1283,7 +1288,7 @@
             }
             final InputMethodManager imm = InputMethodManager.peekInstance();
             if (mTextView.hasSelection() && !extractedTextModeWillBeStarted()) {
-                startSelectionActionMode();
+                refreshTextActionMode();
             }
         } else {
             if (mBlink != null) {
@@ -1846,6 +1851,7 @@
 
     void refreshTextActionMode() {
         if (extractedTextModeWillBeStarted()) {
+            mRestartActionModeOnNextRefresh = false;
             return;
         }
         final boolean hasSelection = mTextView.hasSelection();
@@ -1854,12 +1860,19 @@
         if ((selectionController != null && selectionController.isCursorBeingModified())
                 || (insertionController != null && insertionController.isCursorBeingModified())) {
             // ActionMode should be managed by the currently active cursor controller.
+            mRestartActionModeOnNextRefresh = false;
             return;
         }
         if (hasSelection) {
-            if (mTextActionMode == null || selectionController == null
-                    || !selectionController.isActive()) {
-                // Avoid dismissing the selection if it exists.
+            hideInsertionPointCursorController();
+            if (mTextActionMode == null) {
+                if (mRestartActionModeOnNextRefresh || mTextView.isInExtractedMode()) {
+                    // To avoid distraction, newly start action mode only when selection action
+                    // mode is being restarted or in full screen extracted mode.
+                    startSelectionActionMode();
+                }
+            } else if (selectionController == null || !selectionController.isActive()) {
+                // Insertion action mode is active. Avoid dismissing the selection.
                 stopTextActionModeWithPreservingSelection();
                 startSelectionActionMode();
             } else {
@@ -1874,6 +1887,7 @@
                 mTextActionMode.invalidateContentRect();
             }
         }
+        mRestartActionModeOnNextRefresh = false;
     }
 
     /**
@@ -1904,11 +1918,12 @@
      *
      * @return true if the selection mode was actually started.
      */
-    private boolean startSelectionActionMode() {
+    boolean startSelectionActionMode() {
         boolean selectionStarted = startSelectionActionModeInternal();
         if (selectionStarted) {
             getSelectionController().show();
         }
+        mRestartActionModeOnNextRefresh = false;
         return selectionStarted;
     }
 
@@ -2112,6 +2127,9 @@
     }
 
     private void stopTextActionModeWithPreservingSelection() {
+        if (mTextActionMode != null) {
+            mRestartActionModeOnNextRefresh = true;
+        }
         mPreserveSelection = true;
         stopTextActionMode();
         mPreserveSelection = false;
@@ -2460,7 +2478,7 @@
             }
             final SubMenu subMenu = menu.addSubMenu(Menu.NONE, Menu.NONE, MENU_ITEM_ORDER_REPLACE,
                     com.android.internal.R.string.replace);
-            final int numItems = mSuggestionHelper.getSuggestionInfo(suggestionInfoArray);
+            final int numItems = mSuggestionHelper.getSuggestionInfo(suggestionInfoArray, null);
             for (int i = 0; i < numItems; i++) {
                 final SuggestionInfo info = suggestionInfoArray[i];
                 subMenu.add(Menu.NONE, Menu.NONE, i, info.mText)
@@ -2516,32 +2534,44 @@
         mPreserveSelection = true;
     }
 
-    private void replaceWithSuggestion(final SuggestionInfo suggestionInfo) {
+    @Nullable
+    private SuggestionSpan findEquivalentSuggestionSpan(
+            @NonNull SuggestionSpanInfo suggestionSpanInfo) {
         final Editable editable = (Editable) mTextView.getText();
-        if (editable.getSpanStart(suggestionInfo.mSuggestionSpan) < 0) {
-            // Suggestion span coundn't be found. Try to find a suggestion span that has the same
-            // contents.
-            final SuggestionSpan[] suggestionSpans = editable.getSpans(
-                    suggestionInfo.mSuggestionSpanStart, suggestionInfo.mSuggestionSpanEnd,
-                    SuggestionSpan.class);
-            for (final SuggestionSpan suggestionSpan : suggestionSpans) {
-                final int spanStart = editable.getSpanStart(suggestionSpan);
-                if (spanStart != suggestionInfo.mSuggestionSpanStart) {
-                    continue;
-                }
-                int spanEnd = editable.getSpanEnd(suggestionSpan);
-                if (spanEnd != suggestionInfo.mSuggestionSpanEnd) {
-                    continue;
-                }
-                if (suggestionSpan.equals(suggestionInfo.mSuggestionSpan)) {
-                    // Found.
-                    suggestionInfo.mSuggestionSpan = suggestionSpan;
-                    break;
-                }
+        if (editable.getSpanStart(suggestionSpanInfo.mSuggestionSpan) >= 0) {
+            // Exactly same span is found.
+            return suggestionSpanInfo.mSuggestionSpan;
+        }
+        // Suggestion span couldn't be found. Try to find a suggestion span that has the same
+        // contents.
+        final SuggestionSpan[] suggestionSpans = editable.getSpans(suggestionSpanInfo.mSpanStart,
+                suggestionSpanInfo.mSpanEnd, SuggestionSpan.class);
+        for (final SuggestionSpan suggestionSpan : suggestionSpans) {
+            final int start = editable.getSpanStart(suggestionSpan);
+            if (start != suggestionSpanInfo.mSpanStart) {
+                continue;
+            }
+            final int end = editable.getSpanEnd(suggestionSpan);
+            if (end != suggestionSpanInfo.mSpanEnd) {
+                continue;
+            }
+            if (suggestionSpan.equals(suggestionSpanInfo.mSuggestionSpan)) {
+                return suggestionSpan;
             }
         }
-        final int spanStart = editable.getSpanStart(suggestionInfo.mSuggestionSpan);
-        final int spanEnd = editable.getSpanEnd(suggestionInfo.mSuggestionSpan);
+        return null;
+    }
+
+    private void replaceWithSuggestion(@NonNull final SuggestionInfo suggestionInfo) {
+        final SuggestionSpan targetSuggestionSpan = findEquivalentSuggestionSpan(
+                suggestionInfo.mSuggestionSpanInfo);
+        if (targetSuggestionSpan == null) {
+            // Span has been removed
+            return;
+        }
+        final Editable editable = (Editable) mTextView.getText();
+        final int spanStart = editable.getSpanStart(targetSuggestionSpan);
+        final int spanEnd = editable.getSpanEnd(targetSuggestionSpan);
         if (spanStart < 0 || spanEnd <= spanStart) {
             // Span has been removed
             return;
@@ -2571,7 +2601,7 @@
         }
 
         // Notify source IME of the suggestion pick. Do this before swapping texts.
-        suggestionInfo.mSuggestionSpan.notifySelection(
+        targetSuggestionSpan.notifySelection(
                 mTextView.getContext(), originalText, suggestionInfo.mSuggestionIndex);
 
         // Swap text content between actual text and Suggestion span
@@ -2581,7 +2611,7 @@
                 suggestionStart, suggestionEnd).toString();
         mTextView.replaceText_internal(spanStart, spanEnd, suggestion);
 
-        String[] suggestions = suggestionInfo.mSuggestionSpan.getSuggestions();
+        String[] suggestions = targetSuggestionSpan.getSuggestions();
         suggestions[suggestionInfo.mSuggestionIndex] = originalText;
 
         // Restore previous SuggestionSpans
@@ -3029,19 +3059,12 @@
         }
     }
 
-    private static class SuggestionInfo {
+    private static final class SuggestionInfo {
         // Range of actual suggestion within mText
         int mSuggestionStart, mSuggestionEnd;
 
         // The SuggestionSpan that this TextView represents
-        @Nullable
-        SuggestionSpan mSuggestionSpan;
-
-        // The SuggestionSpan start position
-        int mSuggestionSpanStart;
-
-        // The SuggestionSpan end position
-        int mSuggestionSpanEnd;
+        final SuggestionSpanInfo mSuggestionSpanInfo = new SuggestionSpanInfo();
 
         // The index of this suggestion inside suggestionSpan
         int mSuggestionIndex;
@@ -3049,9 +3072,32 @@
         final SpannableStringBuilder mText = new SpannableStringBuilder();
 
         void clear() {
-            mSuggestionSpan = null;
+            mSuggestionSpanInfo.clear();
             mText.clear();
         }
+
+        // Utility method to set attributes about a SuggestionSpan.
+        void setSpanInfo(SuggestionSpan span, int spanStart, int spanEnd) {
+            mSuggestionSpanInfo.mSuggestionSpan = span;
+            mSuggestionSpanInfo.mSpanStart = spanStart;
+            mSuggestionSpanInfo.mSpanEnd = spanEnd;
+        }
+    }
+
+    private static final class SuggestionSpanInfo {
+        // The SuggestionSpan;
+        @Nullable
+        SuggestionSpan mSuggestionSpan;
+
+        // The SuggestionSpan start position
+        int mSpanStart;
+
+        // The SuggestionSpan end position
+        int mSpanEnd;
+
+        void clear() {
+            mSuggestionSpan = null;
+        }
     }
 
     private class SuggestionHelper {
@@ -3109,48 +3155,51 @@
          * position.
          *
          * @param suggestionInfos SuggestionInfo array the results will be set.
+         * @param misspelledSpanInfo a struct the misspelled SuggestionSpan info will be set.
          * @return the number of suggestions actually fetched.
          */
-        public int getSuggestionInfo(SuggestionInfo[] suggestionInfos) {
+        public int getSuggestionInfo(SuggestionInfo[] suggestionInfos,
+                @Nullable SuggestionSpanInfo misspelledSpanInfo) {
             final Spannable spannable = (Spannable) mTextView.getText();
             final SuggestionSpan[] suggestionSpans = getSortedSuggestionSpans();
             final int nbSpans = suggestionSpans.length;
             if (nbSpans == 0) return 0;
 
             int numberOfSuggestions = 0;
-            for (int spanIndex = 0; spanIndex < nbSpans; spanIndex++) {
-                final SuggestionSpan suggestionSpan = suggestionSpans[spanIndex];
+            for (final SuggestionSpan suggestionSpan : suggestionSpans) {
                 final int spanStart = spannable.getSpanStart(suggestionSpan);
                 final int spanEnd = spannable.getSpanEnd(suggestionSpan);
 
+                if (misspelledSpanInfo != null
+                        && (suggestionSpan.getFlags() & SuggestionSpan.FLAG_MISSPELLED) != 0) {
+                    misspelledSpanInfo.mSuggestionSpan = suggestionSpan;
+                    misspelledSpanInfo.mSpanStart = spanStart;
+                    misspelledSpanInfo.mSpanEnd = spanEnd;
+                }
+
                 final String[] suggestions = suggestionSpan.getSuggestions();
                 final int nbSuggestions = suggestions.length;
+                suggestionLoop:
                 for (int suggestionIndex = 0; suggestionIndex < nbSuggestions; suggestionIndex++) {
                     final String suggestion = suggestions[suggestionIndex];
-                    boolean suggestionIsDuplicate = false;
                     for (int i = 0; i < numberOfSuggestions; i++) {
-                        if (suggestionInfos[i].mText.toString().equals(suggestion)) {
-                            final SuggestionSpan otherSuggestionSpan =
-                                    suggestionInfos[i].mSuggestionSpan;
-                            final int otherSpanStart = spannable.getSpanStart(otherSuggestionSpan);
-                            final int otherSpanEnd = spannable.getSpanEnd(otherSuggestionSpan);
+                        final SuggestionInfo otherSuggestionInfo = suggestionInfos[i];
+                        if (otherSuggestionInfo.mText.toString().equals(suggestion)) {
+                            final int otherSpanStart =
+                                    otherSuggestionInfo.mSuggestionSpanInfo.mSpanStart;
+                            final int otherSpanEnd =
+                                    otherSuggestionInfo.mSuggestionSpanInfo.mSpanEnd;
                             if (spanStart == otherSpanStart && spanEnd == otherSpanEnd) {
-                                suggestionIsDuplicate = true;
-                                break;
+                                continue suggestionLoop;
                             }
                         }
                     }
 
-                    if (suggestionIsDuplicate) {
-                        continue;
-                    }
                     SuggestionInfo suggestionInfo = suggestionInfos[numberOfSuggestions];
-                    suggestionInfo.mSuggestionSpan = suggestionSpan;
+                    suggestionInfo.setSpanInfo(suggestionSpan, spanStart, spanEnd);
                     suggestionInfo.mSuggestionIndex = suggestionIndex;
                     suggestionInfo.mSuggestionStart = 0;
                     suggestionInfo.mSuggestionEnd = suggestion.length();
-                    suggestionInfo.mSuggestionSpanStart = spanStart;
-                    suggestionInfo.mSuggestionSpanEnd = spanEnd;
                     suggestionInfo.mText.replace(0, suggestionInfo.mText.length(), suggestion);
                     numberOfSuggestions++;
                     if (numberOfSuggestions >= suggestionInfos.length) {
@@ -3180,7 +3229,7 @@
         private TextView mAddToDictionaryButton;
         private TextView mDeleteButton;
         private ListView mSuggestionListView;
-        private SuggestionSpan mMisspelledSpan;
+        private final SuggestionSpanInfo mMisspelledSpanInfo = new SuggestionSpanInfo();
         private int mContainerMarginWidth;
         private int mContainerMarginTop;
 
@@ -3252,9 +3301,18 @@
                     com.android.internal.R.id.addToDictionaryButton);
             mAddToDictionaryButton.setOnClickListener(new View.OnClickListener() {
                 public void onClick(View v) {
+                    final SuggestionSpan misspelledSpan =
+                            findEquivalentSuggestionSpan(mMisspelledSpanInfo);
+                    if (misspelledSpan == null) {
+                        // Span has been removed.
+                        return;
+                    }
                     final Editable editable = (Editable) mTextView.getText();
-                    final int spanStart = editable.getSpanStart(mMisspelledSpan);
-                    final int spanEnd = editable.getSpanEnd(mMisspelledSpan);
+                    final int spanStart = editable.getSpanStart(misspelledSpan);
+                    final int spanEnd = editable.getSpanEnd(misspelledSpan);
+                    if (spanStart < 0 || spanEnd <= spanStart) {
+                        return;
+                    }
                     final String originalText = TextUtils.substring(editable, spanStart, spanEnd);
 
                     final Intent intent = new Intent(Settings.ACTION_USER_DICTIONARY_INSERT);
@@ -3265,7 +3323,7 @@
                     mTextView.getContext().startActivity(intent);
                     // There is no way to know if the word was indeed added. Re-check.
                     // TODO The ExtractEditText should remove the span in the original text instead
-                    editable.removeSpan(mMisspelledSpan);
+                    editable.removeSpan(mMisspelledSpanInfo.mSuggestionSpan);
                     Selection.setSelection(editable, spanEnd);
                     updateSpellCheckSpans(spanStart, spanEnd, false);
                     hideWithCleanUp();
@@ -3422,30 +3480,29 @@
             for (final SuggestionInfo info : mSuggestionInfos) {
                 info.clear();
             }
-            mMisspelledSpan = null;
+            mMisspelledSpanInfo.clear();
             hide();
         }
 
         private boolean updateSuggestions() {
             Spannable spannable = (Spannable) mTextView.getText();
             mNumberOfSuggestions =
-                    mSuggestionHelper.getSuggestionInfo(mSuggestionInfos);
-            if (mNumberOfSuggestions == 0) {
+                    mSuggestionHelper.getSuggestionInfo(mSuggestionInfos, mMisspelledSpanInfo);
+            if (mNumberOfSuggestions == 0 && mMisspelledSpanInfo.mSuggestionSpan == null) {
                 return false;
             }
 
             int spanUnionStart = mTextView.getText().length();
             int spanUnionEnd = 0;
 
-            mMisspelledSpan = null;
             for (int i = 0; i < mNumberOfSuggestions; i++) {
-                final SuggestionInfo suggestionInfo = mSuggestionInfos[i];
-                final SuggestionSpan suggestionSpan = suggestionInfo.mSuggestionSpan;
-                if ((suggestionSpan.getFlags() & SuggestionSpan.FLAG_MISSPELLED) != 0) {
-                    mMisspelledSpan = suggestionSpan;
-                }
-                spanUnionStart = Math.min(spanUnionStart, suggestionInfo.mSuggestionSpanStart);
-                spanUnionEnd = Math.max(spanUnionEnd, suggestionInfo.mSuggestionSpanEnd);
+                final SuggestionSpanInfo spanInfo = mSuggestionInfos[i].mSuggestionSpanInfo;
+                spanUnionStart = Math.min(spanUnionStart, spanInfo.mSpanStart);
+                spanUnionEnd = Math.max(spanUnionEnd, spanInfo.mSpanEnd);
+            }
+            if (mMisspelledSpanInfo.mSuggestionSpan != null) {
+                spanUnionStart = Math.min(spanUnionStart, mMisspelledSpanInfo.mSpanStart);
+                spanUnionEnd = Math.max(spanUnionEnd, mMisspelledSpanInfo.mSpanEnd);
             }
 
             for (int i = 0; i < mNumberOfSuggestions; i++) {
@@ -3454,17 +3511,23 @@
 
             // Make "Add to dictionary" item visible if there is a span with the misspelled flag
             int addToDictionaryButtonVisibility = View.GONE;
-            if (mMisspelledSpan != null) {
-                final int misspelledStart = spannable.getSpanStart(mMisspelledSpan);
-                final int misspelledEnd = spannable.getSpanEnd(mMisspelledSpan);
-                if (misspelledStart >= 0 && misspelledEnd > misspelledStart) {
+            if (mMisspelledSpanInfo.mSuggestionSpan != null) {
+                if (mMisspelledSpanInfo.mSpanStart >= 0
+                        && mMisspelledSpanInfo.mSpanEnd > mMisspelledSpanInfo.mSpanStart) {
                     addToDictionaryButtonVisibility = View.VISIBLE;
                 }
             }
             mAddToDictionaryButton.setVisibility(addToDictionaryButtonVisibility);
 
             if (mSuggestionRangeSpan == null) mSuggestionRangeSpan = new SuggestionRangeSpan();
-            final int underlineColor = mSuggestionInfos[0].mSuggestionSpan.getUnderlineColor();
+            final int underlineColor;
+            if (mNumberOfSuggestions != 0) {
+                underlineColor =
+                        mSuggestionInfos[0].mSuggestionSpanInfo.mSuggestionSpan.getUnderlineColor();
+            } else {
+                underlineColor = mMisspelledSpanInfo.mSuggestionSpan.getUnderlineColor();
+            }
+
             if (underlineColor == 0) {
                 // Fallback on the default highlight color when the first span does not provide one
                 mSuggestionRangeSpan.setBackgroundColor(mTextView.mHighlightColor);
@@ -3484,8 +3547,8 @@
         private void highlightTextDifferences(SuggestionInfo suggestionInfo, int unionStart,
                 int unionEnd) {
             final Spannable text = (Spannable) mTextView.getText();
-            final int spanStart = suggestionInfo.mSuggestionSpanStart;
-            final int spanEnd = suggestionInfo.mSuggestionSpanEnd;
+            final int spanStart = suggestionInfo.mSuggestionSpanInfo.mSpanStart;
+            final int spanEnd = suggestionInfo.mSuggestionSpanInfo.mSpanEnd;
 
             // Adjust the start/end of the suggestion span
             suggestionInfo.mSuggestionStart = spanStart - unionStart;
@@ -3661,6 +3724,8 @@
 
         @Override
         public void onDestroyActionMode(ActionMode mode) {
+            // Clear mTextActionMode not to recursively destroy action mode by clearing selection.
+            mTextActionMode = null;
             Callback customCallback = getCustomCallback();
             if (customCallback != null) {
                 customCallback.onDestroyActionMode(mode);
@@ -3679,8 +3744,6 @@
             if (mSelectionModifierCursorController != null) {
                 mSelectionModifierCursorController.hide();
             }
-
-            mTextActionMode = null;
         }
 
         @Override
@@ -5083,27 +5146,12 @@
                     // No longer dragging to select text, let the parent intercept events.
                     mTextView.getParent().requestDisallowInterceptTouchEvent(false);
 
-                    int startOffset = mTextView.getSelectionStart();
-                    int endOffset = mTextView.getSelectionEnd();
-
-                    // Since we don't let drag handles pass once they're visible, we need to
-                    // make sure the start / end locations are correct because the user *can*
-                    // switch directions during the initial drag.
-                    if (endOffset < startOffset) {
-                        int tmp = endOffset;
-                        endOffset = startOffset;
-                        startOffset = tmp;
-
-                        // Also update the selection with the right offsets in this case.
-                        Selection.setSelection((Spannable) mTextView.getText(),
-                                startOffset, endOffset);
-                    }
-                    if (startOffset != endOffset) {
-                        startSelectionActionMode();
-                    }
-
                     // No longer the first dragging motion, reset.
                     resetDragAcceleratorState();
+
+                    if (mTextView.hasSelection()) {
+                        startSelectionActionMode();
+                    }
                     break;
             }
         }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index e971f86..fbedbda 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -9212,6 +9212,10 @@
                     }
                     if (start >= 0 && start <= end && end <= text.length()) {
                         Selection.setSelection((Spannable) text, start, end);
+                        // Make sure selection mode is engaged.
+                        if (mEditor != null) {
+                            mEditor.startSelectionActionMode();
+                        }
                         return true;
                     }
                 }
diff --git a/core/java/com/android/internal/app/UnlaunchableAppActivity.java b/core/java/com/android/internal/app/UnlaunchableAppActivity.java
index 29190f9..f6fbaab 100644
--- a/core/java/com/android/internal/app/UnlaunchableAppActivity.java
+++ b/core/java/com/android/internal/app/UnlaunchableAppActivity.java
@@ -42,15 +42,13 @@
 
 /**
  * A dialog shown to the user when they try to launch an app from a quiet profile
- * ({@link UserManager#isQuietModeEnabled(UserHandle)}, or when the app is suspended by the
- * profile owner or device owner.
+ * ({@link UserManager#isQuietModeEnabled(UserHandle)}.
  */
 public class UnlaunchableAppActivity extends Activity
         implements DialogInterface.OnDismissListener, DialogInterface.OnClickListener {
     private static final String TAG = "UnlaunchableAppActivity";
 
     private static final int UNLAUNCHABLE_REASON_QUIET_MODE = 1;
-    private static final int UNLAUNCHABLE_REASON_SUSPENDED_PACKAGE = 2;
     private static final String EXTRA_UNLAUNCHABLE_REASON = "unlaunchable_reason";
 
     private int mUserId;
@@ -74,37 +72,6 @@
         if (mReason == UNLAUNCHABLE_REASON_QUIET_MODE) {
             dialogTitle = getResources().getString(R.string.work_mode_off_title);
             dialogMessage = getResources().getString(R.string.work_mode_off_message);
-        } else if (mReason == UNLAUNCHABLE_REASON_SUSPENDED_PACKAGE) {
-            DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(
-                    Context.DEVICE_POLICY_SERVICE);
-            String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
-            String packageLabel = packageName;
-            try {
-                Context userContext = createPackageContextAsUser(packageName, 0,
-                        UserHandle.of(mUserId));
-                ApplicationInfo appInfo = userContext.getApplicationInfo();
-                if (appInfo != null) {
-                    packageLabel = userContext.getPackageManager().getApplicationLabel(appInfo)
-                            .toString();
-                }
-            } catch (NameNotFoundException e) {
-            }
-            dialogTitle = String.format(getResources().getString(R.string.suspended_package_title),
-                    packageLabel);
-            ComponentName profileOwner = dpm.getProfileOwnerAsUser(mUserId);
-            String profileOwnerName = null;
-            if (profileOwner != null) {
-                dialogMessage = dpm.getShortSupportMessageForUser(profileOwner, mUserId);
-                profileOwnerName = dpm.getProfileOwnerNameAsUser(mUserId);
-            }
-            // Fall back to standard message if profile owner hasn't set something specific.
-            if (TextUtils.isEmpty(dialogMessage)) {
-                if (TextUtils.isEmpty(profileOwnerName)) {
-                    profileOwnerName = getResources().getString(R.string.unknownName);
-                }
-                dialogMessage = getResources().getString(R.string.suspended_package_message,
-                        profileOwnerName);
-            }
         } else {
             Log.wtf(TAG, "Invalid unlaunchable type: " + mReason);
             finish();
@@ -154,12 +121,4 @@
         intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
         return intent;
     }
-
-    public static Intent createPackageSuspendedDialogIntent(String packageName, int userId) {
-        Intent intent = createBaseIntent();
-        intent.putExtra(EXTRA_UNLAUNCHABLE_REASON, UNLAUNCHABLE_REASON_SUSPENDED_PACKAGE);
-        intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
-        intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
-        return intent;
-    }
 }
diff --git a/core/res/res/anim/lock_screen_behind_enter.xml b/core/res/res/anim/lock_screen_behind_enter.xml
index 6f3c4d42..c96e280 100644
--- a/core/res/res/anim/lock_screen_behind_enter.xml
+++ b/core/res/res/anim/lock_screen_behind_enter.xml
@@ -16,7 +16,6 @@
   -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:background="#ff000000"
         android:detachWallpaper="true"
         android:shareInterpolator="false"
         android:startOffset="100">
diff --git a/core/res/res/values-television/config.xml b/core/res/res/values-television/config.xml
index ae19150..3408c21 100644
--- a/core/res/res/values-television/config.xml
+++ b/core/res/res/values-television/config.xml
@@ -25,7 +25,7 @@
     <bool name="config_defaultWindowFeatureOptionsPanel">false</bool>
 
     <!-- Default bounds [left top right bottom] on screen for picture-in-picture windows. -->
-    <string translatable="false" name="config_defaultPictureInPictureBounds">"1420 100 1820 325"</string>
+    <string translatable="false" name="config_defaultPictureInPictureBounds">"1328 54 1808 324"</string>
 
     <!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows, when the PIP
          is located in center. -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 17afd92..5d083d7 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4188,10 +4188,6 @@
     <string name="work_mode_off_message">Allow work profile to function, including apps, background sync, and related features.</string>
     <!-- Title for button to turn on work profile. [CHAR LIMIT=NONE] -->
     <string name="work_mode_turn_on">Turn on</string>
-    <!-- Title for dialog displayed when a packge is suspended by device admin. [CHAR LIMIT=30] -->
-    <string name="suspended_package_title">%1$s disabled</string>
-    <!-- Message for dialog displayed when a packge is suspended by device admin. [CHAR LIMIT=NONE] -->
-    <string name="suspended_package_message">Disabled by %1$s administrator. Contact them to learn more.</string>
 
     <!-- Notification title shown when new SMS/MMS is received while the device is locked [CHAR LIMIT=NONE] -->
     <string name="new_sms_notification_title">You have new messages</string>
@@ -4229,7 +4225,7 @@
     <string name="negative_duration">\u2212<xliff:g id="time" example="1:14">%1$s</xliff:g></string>
 
     <!-- Title of notification shown when device has been forced to safe mode after a security compromise. -->
-    <string name="audit_safemode_notification">Factory reset to use this device normally</string>
+    <string name="audit_safemode_notification">Factory reset to use this device without restrictions</string>
     <!-- Description of notification shown when device has been forced to safe mode after a security compromise. -->
     <string name="audit_safemode_notification_details">Touch to learn more.</string>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 32a01318..f01cce3 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2508,8 +2508,6 @@
   <java-symbol type="string" name="work_mode_off_title" />
   <java-symbol type="string" name="work_mode_off_message" />
   <java-symbol type="string" name="work_mode_turn_on" />
-  <java-symbol type="string" name="suspended_package_title" />
-  <java-symbol type="string" name="suspended_package_message" />
 
   <!-- New SMS notification while phone is locked. -->
   <java-symbol type="string" name="new_sms_notification_title" />
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index cf7978c..c02a01a 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -102,7 +102,7 @@
     <!-- United Kingdom (Great Britain): 4-6 digits, common codes [5-8]xxxx, plus EU:
          http://www.short-codes.com/media/Co-regulatoryCodeofPracticeforcommonshortcodes170206.pdf,
          visual voicemail code for EE: 887 -->
-    <shortcode country="gb" pattern="\\d{4,6}" premium="[5-8]\\d{4}" free="116\\d{3}|887|83669|34664|40406" />
+    <shortcode country="gb" pattern="\\d{4,6}" premium="[5-8]\\d{4}" free="116\\d{3}|2020|35890|61002|61202|887|83669|34664|40406" />
 
     <!-- Georgia: 4 digits, known premium codes listed -->
     <shortcode country="ge" pattern="\\d{4}" premium="801[234]|888[239]" />
@@ -214,7 +214,7 @@
 
     <!-- USA: 5-6 digits (premium codes from https://www.premiumsmsrefunds.com/ShortCodes.htm),
          visual voicemail code for T-Mobile: 122 -->
-    <shortcode country="us" pattern="\\d{5,6}" premium="20433|21(?:344|472)|22715|23(?:333|847)|24(?:15|28)0|25209|27(?:449|606|663)|28498|305(?:00|83)|32(?:340|941)|33(?:166|786|849)|34746|35(?:182|564)|37975|38(?:135|146|254)|41(?:366|463)|42335|43(?:355|500)|44(?:567|578|711|811)|45814|46(?:157|173|327)|46666|47553|48(?:221|277|669)|50(?:844|920)|51(?:062|368)|52944|54(?:723|892)|55928|56483|57370|59(?:182|187|252|342)|60339|61(?:266|982)|62478|64(?:219|898)|65(?:108|500)|69(?:208|388)|70877|71851|72(?:078|087|465)|73(?:288|588|882|909|997)|74(?:034|332|815)|76426|79213|81946|83177|84(?:103|685)|85797|86(?:234|236|666)|89616|90(?:715|842|938)|91(?:362|958)|94719|95297|96(?:040|666|835|969)|97(?:142|294|688)|99(?:689|796|807)" free="122|87902" />
+    <shortcode country="us" pattern="\\d{5,6}" premium="20433|21(?:344|472)|22715|23(?:333|847)|24(?:15|28)0|25209|27(?:449|606|663)|28498|305(?:00|83)|32(?:340|941)|33(?:166|786|849)|34746|35(?:182|564)|37975|38(?:135|146|254)|41(?:366|463)|42335|43(?:355|500)|44(?:578|711|811)|45814|46(?:157|173|327)|46666|47553|48(?:221|277|669)|50(?:844|920)|51(?:062|368)|52944|54(?:723|892)|55928|56483|57370|59(?:182|187|252|342)|60339|61(?:266|982)|62478|64(?:219|898)|65(?:108|500)|69(?:208|388)|70877|71851|72(?:078|087|465)|73(?:288|588|882|909|997)|74(?:034|332|815)|76426|79213|81946|83177|84(?:103|685)|85797|86(?:234|236|666)|89616|90(?:715|842|938)|91(?:362|958)|94719|95297|96(?:040|666|835|969)|97(?:142|294|688)|99(?:689|796|807)" standard="44567" free="122|87902" />
 
     <!-- Vietnam -->
     <shortcode country="vn" free="5001" />
diff --git a/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
index 3d8fe69..a37abf1 100644
--- a/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
+++ b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
@@ -32,6 +32,8 @@
 
 /**
  * SuggestionsPopupWindowTest tests.
+ *
+ * TODO: Add tests for when there are no suggestions
  */
 public class SuggestionsPopupWindowTest extends ActivityInstrumentationTestCase2<TextViewActivity> {
 
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index 844eadb..4a4727f 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -47,6 +47,8 @@
 import android.support.test.espresso.action.EspressoKey;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.text.Selection;
+import android.text.Spannable;
 import android.view.KeyEvent;
 
 import static org.hamcrest.Matchers.anyOf;
@@ -534,4 +536,68 @@
                 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('i')));
         onView(withId(R.id.textview)).check(hasSelection("hijk"));
     }
+
+    @SmallTest
+    public void testSetSelectionAndActionMode() throws Exception {
+        final String text = "abc def";
+        onView(withId(R.id.textview)).perform(click());
+        onView(withId(R.id.textview)).perform(replaceText(text));
+
+        final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
+        assertFloatingToolbarIsNotDisplayed();
+        textView.post(() -> Selection.setSelection((Spannable) textView.getText(), 0, 3));
+        getInstrumentation().waitForIdleSync();
+        sleepForFloatingToolbarPopup();
+        // Don't automatically start action mode.
+        assertFloatingToolbarIsNotDisplayed();
+        // Make sure that "Select All" is included in the selection action mode when the entire text
+        // is not selected.
+        onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('e')));
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarIsDisplayed();
+        // Changing the selection range by API should not interrupt the selection action mode.
+        textView.post(() -> Selection.setSelection((Spannable) textView.getText(), 0, 3));
+        getInstrumentation().waitForIdleSync();
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarIsDisplayed();
+        assertFloatingToolbarContainsItem(
+                getActivity().getString(com.android.internal.R.string.selectAll));
+        // Make sure that "Select All" is no longer included when the entire text is selected by
+        // API.
+        textView.post(
+                () -> Selection.setSelection((Spannable) textView.getText(), 0, text.length()));
+        getInstrumentation().waitForIdleSync();
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarIsDisplayed();
+        assertFloatingToolbarDoesNotContainItem(
+                getActivity().getString(com.android.internal.R.string.selectAll));
+        // Make sure that shrinking the selection range to cursor (an empty range) by API
+        // terminates selection action mode and does not trigger the insertion action mode.
+        textView.post(() -> Selection.setSelection((Spannable) textView.getText(), 0));
+        getInstrumentation().waitForIdleSync();
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarIsNotDisplayed();
+        // Make sure that user click can trigger the insertion action mode.
+        onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.length()));
+        onHandleView(com.android.internal.R.id.insertion_handle).perform(click());
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarIsDisplayed();
+        // Make sure that an existing insertion action mode keeps alive after the insertion point is
+        // moved by API.
+        textView.post(() -> Selection.setSelection((Spannable) textView.getText(), 0));
+        getInstrumentation().waitForIdleSync();
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarIsDisplayed();
+        assertFloatingToolbarDoesNotContainItem(
+                getActivity().getString(com.android.internal.R.string.copy));
+        // Make sure that selection action mode is started after selection is created by API when
+        // insertion action mode is active.
+        textView.post(
+                () -> Selection.setSelection((Spannable) textView.getText(), 1, text.length()));
+        getInstrumentation().waitForIdleSync();
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarIsDisplayed();
+        assertFloatingToolbarContainsItem(
+                getActivity().getString(com.android.internal.R.string.copy));
+    }
 }
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index d312454..3e86e6f 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -32,7 +32,7 @@
  * @see Drawable#getOutline(Outline)
  */
 public final class Outline {
-    private static final float RADIUS_UNDEFINED = -1.0f;
+    private static final float RADIUS_UNDEFINED = Float.NEGATIVE_INFINITY;
 
     /** @hide */
     public Path mPath;
@@ -196,11 +196,11 @@
     }
 
     /**
-     * Returns the rounded rect radius, if set, or {@code -1} if a path has
+     * Returns the rounded rect radius, if set, or a value less than 0 if a path has
      * been set via {@link #setConvexPath(Path)}. A return value of {@code 0}
      * indicates a non-rounded rect.
      *
-     * @return the rounded rect radius or {@code -1}
+     * @return the rounded rect radius, or value < 0
      */
     public float getRadius() {
         return mRadius;
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 437ebaa..ae9ebc7 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -157,7 +157,7 @@
     private static final boolean DBG_ANIMATION_VECTOR_DRAWABLE = false;
 
     /** Local, mutable animator set. */
-    private VectorDrawableAnimator mAnimatorSet = new VectorDrawableAnimatorRT(this);
+    private VectorDrawableAnimator mAnimatorSet = new VectorDrawableAnimatorUI(this);
 
     /**
      * The resources against which this drawable was created. Used to attempt
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 8417a40..d9c3a02 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -89,7 +89,7 @@
      * @see #getLayerInsetStart(int)
      * @see #getLayerInsetEnd(int)
      */
-    public static final int UNDEFINED_INSET = Integer.MIN_VALUE;
+    public static final int INSET_UNDEFINED = Integer.MIN_VALUE;
 
     LayerState mLayerState;
 
@@ -759,7 +759,7 @@
      * @attr ref android.R.styleable#LayerDrawableItem_bottom
      */
     public void setLayerInset(int index, int l, int t, int r, int b) {
-        setLayerInsetInternal(index, l, t, r, b, UNDEFINED_INSET, UNDEFINED_INSET);
+        setLayerInsetInternal(index, l, t, r, b, INSET_UNDEFINED, INSET_UNDEFINED);
     }
 
     /**
@@ -874,7 +874,7 @@
     /**
      * @param index the index of the layer
      * @return the number of pixels to inset from the start bound, or
-     *         {@link #UNDEFINED_INSET} if not specified
+     *         {@link #INSET_UNDEFINED} if not specified
      * @attr ref android.R.styleable#LayerDrawableItem_start
      */
     public int getLayerInsetStart(int index) {
@@ -885,7 +885,7 @@
     /**
      * @param index the index of the layer to adjust
      * @param e number of pixels to inset from the end bound, or
-     *         {@link #UNDEFINED_INSET} if not specified
+     *         {@link #INSET_UNDEFINED} if not specified
      * @attr ref android.R.styleable#LayerDrawableItem_end
      */
     public void setLayerInsetEnd(int index, int e) {
@@ -1503,8 +1503,8 @@
             // insets.
             final int insetRtlL = isLayoutRtl ? r.mInsetE : r.mInsetS;
             final int insetRtlR = isLayoutRtl ? r.mInsetS : r.mInsetE;
-            final int insetL = insetRtlL == UNDEFINED_INSET ? r.mInsetL : insetRtlL;
-            final int insetR = insetRtlR == UNDEFINED_INSET ? r.mInsetR : insetRtlR;
+            final int insetL = insetRtlL == INSET_UNDEFINED ? r.mInsetL : insetRtlL;
+            final int insetR = insetRtlR == INSET_UNDEFINED ? r.mInsetR : insetRtlR;
 
             // Establish containing region based on aggregate padding and
             // requested insets for the current layer.
@@ -1602,8 +1602,8 @@
             // left / right ones.
             final int insetRtlL = isLayoutRtl ? r.mInsetE : r.mInsetS;
             final int insetRtlR = isLayoutRtl ? r.mInsetS : r.mInsetE;
-            final int insetL = insetRtlL == UNDEFINED_INSET ? r.mInsetL : insetRtlL;
-            final int insetR = insetRtlR == UNDEFINED_INSET ? r.mInsetR : insetRtlR;
+            final int insetL = insetRtlL == INSET_UNDEFINED ? r.mInsetL : insetRtlL;
+            final int insetR = insetRtlR == INSET_UNDEFINED ? r.mInsetR : insetRtlR;
 
             // Don't apply padding and insets for children that don't have
             // an intrinsic dimension.
@@ -1763,8 +1763,8 @@
         public int[] mThemeAttrs;
         public int mDensity = DisplayMetrics.DENSITY_DEFAULT;
         public int mInsetL, mInsetT, mInsetR, mInsetB;
-        public int mInsetS = UNDEFINED_INSET;
-        public int mInsetE = UNDEFINED_INSET;
+        public int mInsetS = INSET_UNDEFINED;
+        public int mInsetE = INSET_UNDEFINED;
         public int mWidth = -1;
         public int mHeight = -1;
         public int mGravity = Gravity.NO_GRAVITY;
@@ -1833,10 +1833,10 @@
             mInsetT = Drawable.scaleFromDensity(mInsetT, sourceDensity, targetDensity, false);
             mInsetR = Drawable.scaleFromDensity(mInsetR, sourceDensity, targetDensity, false);
             mInsetB = Drawable.scaleFromDensity(mInsetB, sourceDensity, targetDensity, false);
-            if (mInsetS != UNDEFINED_INSET) {
+            if (mInsetS != INSET_UNDEFINED) {
                 mInsetS = Drawable.scaleFromDensity(mInsetS, sourceDensity, targetDensity, false);
             }
-            if (mInsetE != UNDEFINED_INSET) {
+            if (mInsetE != INSET_UNDEFINED) {
                 mInsetE = Drawable.scaleFromDensity(mInsetE, sourceDensity, targetDensity, false);
             }
             if (mWidth > 0) {
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index f6e3b50..ca07738 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -255,6 +255,7 @@
 ifeq (true, $(HWUI_NEW_OPS))
     LOCAL_SRC_FILES += \
         tests/unit/BakedOpDispatcherTests.cpp \
+        tests/unit/BakedOpRendererTests.cpp \
         tests/unit/BakedOpStateTests.cpp \
         tests/unit/FrameBuilderTests.cpp \
         tests/unit/LeakCheckTests.cpp \
diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp
index da5ecca..bb3ea3f 100644
--- a/libs/hwui/BakedOpRenderer.cpp
+++ b/libs/hwui/BakedOpRenderer.cpp
@@ -40,6 +40,16 @@
 void BakedOpRenderer::startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) {
     LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer...");
 
+    // subtract repaintRect from region, since it will be regenerated
+    if (repaintRect.contains(0, 0,
+                offscreenBuffer->viewportWidth, offscreenBuffer->viewportHeight)) {
+        // repaint full layer, so throw away entire region
+        offscreenBuffer->region.clear();
+    } else {
+        offscreenBuffer->region.subtractSelf(android::Rect(repaintRect.left, repaintRect.top,
+                repaintRect.right, repaintRect.bottom));
+    }
+
     mRenderTarget.offscreenBuffer = offscreenBuffer;
 
     // create and bind framebuffer
diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp
index afe9807..f886dda 100644
--- a/libs/hwui/ClipArea.cpp
+++ b/libs/hwui/ClipArea.cpp
@@ -41,6 +41,10 @@
     return transformedBounds;
 }
 
+void ClipBase::dump() const {
+    ALOGD("mode %d" RECT_STRING, mode, RECT_ARGS(rect));
+}
+
 /*
  * TransformedRectangle
  */
diff --git a/libs/hwui/ClipArea.h b/libs/hwui/ClipArea.h
index 479796d..1654eb8 100644
--- a/libs/hwui/ClipArea.h
+++ b/libs/hwui/ClipArea.h
@@ -106,6 +106,8 @@
     // Bounds of the clipping area, used to define the scissor, and define which
     // portion of the stencil is updated/used
     Rect rect;
+
+    void dump() const;
 };
 
 struct ClipRect : ClipBase {
diff --git a/libs/hwui/LayerBuilder.cpp b/libs/hwui/LayerBuilder.cpp
index c5af279..e6a95ff 100644
--- a/libs/hwui/LayerBuilder.cpp
+++ b/libs/hwui/LayerBuilder.cpp
@@ -349,8 +349,9 @@
 }
 
 void LayerBuilder::dump() const {
-    ALOGD("LayerBuilder %p, %ux%u buffer %p, blo %p, rn %p",
-            this, width, height, offscreenBuffer, beginLayerOp, renderNode);
+    ALOGD("LayerBuilder %p, %ux%u buffer %p, blo %p, rn %p (%s)",
+            this, width, height, offscreenBuffer, beginLayerOp,
+            renderNode, renderNode ? renderNode->getName() : "-");
     for (const BatchBase* batch : mBatches) {
         batch->dump();
     }
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index f0c79d7..11eb825 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -356,11 +356,15 @@
 }
 void RecordingCanvas::drawRoundRect(float left, float top, float right, float bottom,
             float rx, float ry, const SkPaint& paint) {
-    addOp(alloc().create_trivial<RoundRectOp>(
-            Rect(left, top, right, bottom),
-            *(mState.currentSnapshot()->transform),
-            getRecordedClip(),
-            refPaint(&paint), rx, ry));
+    if (CC_LIKELY(MathUtils::isPositive(rx) || MathUtils::isPositive(ry))) {
+        addOp(alloc().create_trivial<RoundRectOp>(
+                Rect(left, top, right, bottom),
+                *(mState.currentSnapshot()->transform),
+                getRecordedClip(),
+                refPaint(&paint), rx, ry));
+    } else {
+        drawRect(left, top, right, bottom, paint);
+    }
 }
 
 void RecordingCanvas::drawRoundRect(
diff --git a/libs/hwui/debug/nullgles.cpp b/libs/hwui/debug/nullgles.cpp
index ffb0649..8689f98 100644
--- a/libs/hwui/debug/nullgles.cpp
+++ b/libs/hwui/debug/nullgles.cpp
@@ -133,6 +133,15 @@
     }
 }
 
+GLenum glCheckFramebufferStatus(GLenum target) {
+    switch (target) {
+    case GL_FRAMEBUFFER:
+        return GL_FRAMEBUFFER_COMPLETE;
+    default:
+        return 0; // error case
+    }
+}
+
 const char* getString(GLenum name) {
     switch (name) {
     case GL_VENDOR:
diff --git a/libs/hwui/renderstate/OffscreenBufferPool.cpp b/libs/hwui/renderstate/OffscreenBufferPool.cpp
index 5f984b5..bb1a044 100644
--- a/libs/hwui/renderstate/OffscreenBufferPool.cpp
+++ b/libs/hwui/renderstate/OffscreenBufferPool.cpp
@@ -164,6 +164,9 @@
         // resize in place
         layer->viewportWidth = width;
         layer->viewportHeight = height;
+
+        // entire area will be repainted (and may be smaller) so clear usage region
+        layer->region.clear();
         return layer;
     }
     putOrDelete(layer);
diff --git a/libs/hwui/tests/unit/BakedOpRendererTests.cpp b/libs/hwui/tests/unit/BakedOpRendererTests.cpp
new file mode 100644
index 0000000..59bd75e
--- /dev/null
+++ b/libs/hwui/tests/unit/BakedOpRendererTests.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <BakedOpRenderer.h>
+#include <tests/common/TestUtils.h>
+
+using namespace android::uirenderer;
+
+const BakedOpRenderer::LightInfo sLightInfo = { 128, 128 };
+
+RENDERTHREAD_TEST(BakedOpRenderer, startRepaintLayer_clear) {
+    BakedOpRenderer renderer(Caches::getInstance(), renderThread.renderState(), true, sLightInfo);
+    OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 200u, 200u);
+
+    layer.dirty(Rect(200, 200));
+    {
+        renderer.startRepaintLayer(&layer, Rect(200, 200));
+        EXPECT_TRUE(layer.region.isEmpty()) << "Repaint full layer should clear region";
+        renderer.endLayer();
+    }
+
+    layer.dirty(Rect(200, 200));
+    {
+        renderer.startRepaintLayer(&layer, Rect(100, 200)); // repainting left side
+        EXPECT_TRUE(layer.region.isRect());
+        //ALOGD("bounds %d %d %d %d", RECT_ARGS(layer.region.getBounds()));
+        EXPECT_EQ(android::Rect(100, 0, 200, 200), layer.region.getBounds())
+                << "Left side being repainted, so right side should be clear";
+        renderer.endLayer();
+    }
+
+    // right side is now only dirty portion
+    {
+        renderer.startRepaintLayer(&layer, Rect(100, 0, 200, 200)); // repainting right side
+        EXPECT_TRUE(layer.region.isEmpty())
+                << "Now right side being repainted, so region should be entirely clear";
+        renderer.endLayer();
+    }
+}
diff --git a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
index 0c6eb57..37a485e 100644
--- a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
+++ b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
@@ -103,9 +103,11 @@
         OffscreenBufferPool pool;
 
         auto layer = pool.get(thread.renderState(), 64u, 64u);
+        layer->dirty(Rect(64, 64));
 
         // resize in place
         ASSERT_EQ(layer, pool.resize(layer, 60u, 55u));
+        EXPECT_TRUE(layer->region.isEmpty()) << "In place resize should clear usage region";
         EXPECT_EQ(60u, layer->viewportWidth);
         EXPECT_EQ(55u, layer->viewportHeight);
         EXPECT_EQ(64u, layer->texture.width());
@@ -113,9 +115,13 @@
 
         // resized to use different object in pool
         auto layer2 = pool.get(thread.renderState(), 128u, 128u);
+        layer2->dirty(Rect(128, 128));
+        EXPECT_FALSE(layer2->region.isEmpty());
         pool.putOrDelete(layer2);
         ASSERT_EQ(1u, pool.getCount());
+
         ASSERT_EQ(layer2, pool.resize(layer, 120u, 125u));
+        EXPECT_TRUE(layer2->region.isEmpty()) << "Swap resize should clear usage region";
         EXPECT_EQ(120u, layer2->viewportWidth);
         EXPECT_EQ(125u, layer2->viewportHeight);
         EXPECT_EQ(128u, layer2->texture.width());
diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
index c3165bb..5e613fd 100644
--- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -114,6 +114,23 @@
     EXPECT_EQ(Rect(10, 20, 90, 180), op.unmappedBounds);
 }
 
+TEST(RecordingCanvas, drawRoundRect) {
+    // Round case - stays rounded
+    auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
+        canvas.drawRoundRect(0, 0, 100, 100, 10, 10, SkPaint());
+    });
+    ASSERT_EQ(1u, dl->getOps().size()) << "Must be exactly one op";
+    ASSERT_EQ(RecordedOpId::RoundRectOp, dl->getOps()[0]->opId);
+
+    // Non-rounded case - turned into drawRect
+    dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
+        canvas.drawRoundRect(0, 0, 100, 100, 0, -1, SkPaint());
+    });
+    ASSERT_EQ(1u, dl->getOps().size()) << "Must be exactly one op";
+    ASSERT_EQ(RecordedOpId::RectOp, dl->getOps()[0]->opId)
+        << "Non-rounded rects should be converted";
+}
+
 TEST(RecordingCanvas, drawText) {
     auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
         SkPaint paint;
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index ce12e76..e35fcf6 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -1197,8 +1197,9 @@
             }
             bytesRead += 2;
             int length = dataInputStream.readUnsignedShort() - 2;
-            if (length < 0)
+            if (length < 0) {
                 throw new IOException("Invalid length");
+            }
             bytesRead += length;
             switch (marker) {
                 case MARKER_APP1: {
@@ -1221,6 +1222,9 @@
                     if (length <= 0) {
                         throw new IOException("Invalid exif");
                     }
+                    if (DEBUG) {
+                        Log.d(TAG, "readExifSegment with a byte array (length: " + length + ")");
+                    }
                     byte[] bytes = new byte[length];
                     if (dataInputStream.read(bytes) != length) {
                         throw new IOException("Invalid exif");
@@ -1309,8 +1313,9 @@
                 case MARKER_APP1: {
                     // Rewrite EXIF segment
                     int length = dataInputStream.readUnsignedShort() - 2;
-                    if (length < 0)
+                    if (length < 0) {
                         throw new IOException("Invalid length");
+                    }
                     bytesRead += 2;
                     int read;
                     while ((read = dataInputStream.read(
@@ -1331,8 +1336,9 @@
                     // Copy JPEG segment
                     int length = dataInputStream.readUnsignedShort();
                     dataOutputStream.writeUnsignedShort(length);
-                    if (length < 0)
+                    if (length < 0) {
                         throw new IOException("Invalid length");
+                    }
                     length -= 2;
                     bytesRead += 2;
                     int read;
@@ -1385,8 +1391,9 @@
         }
         firstIfdOffset -= 8;
         if (firstIfdOffset > 0) {
-            if (dataInputStream.skip(firstIfdOffset) != firstIfdOffset)
+            if (dataInputStream.skip(firstIfdOffset) != firstIfdOffset) {
                 throw new IOException("Couldn't jump to first Ifd: " + firstIfdOffset);
+            }
         }
 
         // Read primary image TIFF image file directory.
@@ -1582,8 +1589,16 @@
     // Reads image file directory, which is a tag group in EXIF.
     private void readImageFileDirectory(ByteOrderAwarenessDataInputStream dataInputStream, int hint)
             throws IOException {
+        if (dataInputStream.peek() + 2 > dataInputStream.mLength) {
+            // Return if there is no data from the offset.
+            return;
+        }
         // See JEITA CP-3451 Figure 5. page 9.
         short numberOfDirectoryEntry = dataInputStream.readShort();
+        if (dataInputStream.peek() + 12 * numberOfDirectoryEntry > dataInputStream.mLength) {
+            // Return if the size of entries is too big.
+            return;
+        }
 
         if (DEBUG) {
             Log.d(TAG, "numberOfDirectoryEntry: " + numberOfDirectoryEntry);
@@ -1595,10 +1610,25 @@
             int numberOfComponents = dataInputStream.readInt();
             long nextEntryOffset = dataInputStream.peek() + 4;  // next four bytes is for data
                                                                 // offset or value.
+            // Look up a corresponding tag from tag number
+            String tagName = (String) sExifTagMapsForReading[hint].get(tagNumber);
 
             if (DEBUG) {
-                Log.d(TAG, String.format("tagNumber: %d, dataFormat: %d, numberOfComponents: %d",
-                        tagNumber, dataFormat, numberOfComponents));
+                Log.d(TAG, String.format("hint: %d, tagNumber: %d, tagName: %s, dataFormat: %d," +
+                        "numberOfComponents: %d", hint, tagNumber, tagName, dataFormat,
+                        numberOfComponents));
+            }
+
+            if (tagName == null || dataFormat <= 0 ||
+                    dataFormat >= IFD_FORMAT_BYTES_PER_FORMAT.length) {
+                // Skip if the parsed tag number is not defined or invalid data format.
+                if (tagName == null) {
+                    Log.w(TAG, "Skip the tag entry since tag number is not defined: " + tagNumber);
+                } else {
+                    Log.w(TAG, "Skip the tag entry since data format is invalid: " + dataFormat);
+                }
+                dataInputStream.seek(nextEntryOffset);
+                continue;
             }
 
             // Read a value from data field or seek to the value offset which is stored in data
@@ -1609,19 +1639,21 @@
                 if (DEBUG) {
                     Log.d(TAG, "seek to data offset: " + offset);
                 }
-                dataInputStream.seek(offset);
-            }
-
-            // Look up a corresponding tag from tag number
-            String tagName = (String) sExifTagMapsForReading[hint].get(tagNumber);
-            // Skip if the parsed tag number is not defined.
-            if (tagName == null) {
-                dataInputStream.seek(nextEntryOffset);
-                continue;
+                if (offset + byteCount <= dataInputStream.mLength) {
+                    dataInputStream.seek(offset);
+                } else {
+                     // Skip if invalid data offset.
+                    Log.w(TAG, "Skip the tag entry since data offset is invalid: " + offset);
+                    dataInputStream.seek(nextEntryOffset);
+                    continue;
+                }
             }
 
             // Recursively parse IFD when a IFD pointer tag appears.
             int innerIfdHint = getIfdHintFromTagNumber(tagNumber);
+            if (DEBUG) {
+                Log.d(TAG, "innerIfdHint: " + innerIfdHint + " byteCount: " + byteCount);
+            }
             if (innerIfdHint >= 0) {
                 long offset = -1L;
                 // Get offset from data field
@@ -1650,9 +1682,11 @@
                 if (DEBUG) {
                     Log.d(TAG, String.format("Offset: %d, tagName: %s", offset, tagName));
                 }
-                if (offset > 0L) {
+                if (offset > 0L && offset < dataInputStream.mLength) {
                     dataInputStream.seek(offset);
                     readImageFileDirectory(dataInputStream, innerIfdHint);
+                } else {
+                    Log.w(TAG, "Skip jump into the IFD since its offset is invalid: " + offset);
                 }
 
                 dataInputStream.seek(nextEntryOffset);
@@ -1683,14 +1717,17 @@
             }
         }
 
-        long nextIfdOffset = dataInputStream.readUnsignedInt();
-        if (DEBUG) {
-            Log.d(TAG, String.format("nextIfdOffset: %d", nextIfdOffset));
-        }
-        // The next IFD offset needs to be bigger than 8 since the first IFD offset is at least 8.
-        if (nextIfdOffset > 8) {
-            dataInputStream.seek(nextIfdOffset);
-            readImageFileDirectory(dataInputStream, IFD_THUMBNAIL_HINT);
+        if (dataInputStream.peek() + 4 <= dataInputStream.mLength) {
+            long nextIfdOffset = dataInputStream.readUnsignedInt();
+            if (DEBUG) {
+                Log.d(TAG, String.format("nextIfdOffset: %d", nextIfdOffset));
+            }
+            // The next IFD offset needs to be bigger than 8
+            // since the first IFD offset is at least 8.
+            if (nextIfdOffset > 8 && nextIfdOffset < dataInputStream.mLength) {
+                dataInputStream.seek(nextIfdOffset);
+                readImageFileDirectory(dataInputStream, IFD_THUMBNAIL_HINT);
+            }
         }
     }
 
@@ -1748,17 +1785,18 @@
                 }
 
                 StringBuilder stringBuilder = new StringBuilder();
-                while (true) {
+                while (index < numberOfComponents) {
                     int ch = bytes[index];
-                    if (ch == 0)
+                    if (ch == 0) {
                         break;
-                    if (ch >= 32)
+                    }
+                    if (ch >= 32) {
                         stringBuilder.append((char) ch);
-                    else
+                    }
+                    else {
                         stringBuilder.append('?');
+                    }
                     ++index;
-                    if (index == numberOfComponents)
-                        break;
                 }
                 return stringBuilder.toString();
             }
@@ -1772,8 +1810,9 @@
     // Gets the corresponding IFD group index of the given tag number for writing Exif Tags.
     private static int getIfdHintFromTagNumber(int tagNumber) {
         for (int i = 0; i < IFD_POINTER_TAG_HINTS.length; ++i) {
-            if (IFD_POINTER_TAGS[i].number == tagNumber)
+            if (IFD_POINTER_TAGS[i].number == tagNumber) {
                 return IFD_POINTER_TAG_HINTS[i];
+            }
         }
         return -1;
     }
@@ -2076,8 +2115,9 @@
         public void seek(long byteCount) throws IOException {
             mPosition = 0L;
             reset();
-            if (skip(byteCount) != byteCount)
+            if (skip(byteCount) != byteCount) {
                 throw new IOException("Couldn't seek up to the byteCount");
+            }
         }
 
         public long peek() {
@@ -2086,8 +2126,9 @@
 
         public void readFully(byte[] buffer) throws IOException {
             mPosition += buffer.length;
-            if (mPosition > mLength)
+            if (mPosition > mLength) {
                 throw new EOFException();
+            }
             if (super.read(buffer, 0, buffer.length) != buffer.length) {
                 throw new IOException("Couldn't read up to the length of buffer");
             }
@@ -2095,22 +2136,26 @@
 
         public byte readByte() throws IOException {
             ++mPosition;
-            if (mPosition > mLength)
+            if (mPosition > mLength) {
                 throw new EOFException();
+            }
             int ch = super.read();
-            if (ch < 0)
+            if (ch < 0) {
                 throw new EOFException();
+            }
             return (byte) ch;
         }
 
         public short readShort() throws IOException {
             mPosition += 2;
-            if (mPosition > mLength)
+            if (mPosition > mLength) {
                 throw new EOFException();
+            }
             int ch1 = super.read();
             int ch2 = super.read();
-            if ((ch1 | ch2) < 0)
+            if ((ch1 | ch2) < 0) {
                 throw new EOFException();
+            }
             if (mByteOrder == LITTLE_ENDIAN) {
                 return (short) ((ch2 << 8) + (ch1));
             } else if (mByteOrder == BIG_ENDIAN) {
@@ -2121,14 +2166,16 @@
 
         public int readInt() throws IOException {
             mPosition += 4;
-            if (mPosition > mLength)
+            if (mPosition > mLength) {
                 throw new EOFException();
+            }
             int ch1 = super.read();
             int ch2 = super.read();
             int ch3 = super.read();
             int ch4 = super.read();
-            if ((ch1 | ch2 | ch3 | ch4) < 0)
+            if ((ch1 | ch2 | ch3 | ch4) < 0) {
                 throw new EOFException();
+            }
             if (mByteOrder == LITTLE_ENDIAN) {
                 return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + ch1);
             } else if (mByteOrder == BIG_ENDIAN) {
@@ -2146,12 +2193,14 @@
 
         public int readUnsignedShort() throws IOException {
             mPosition += 2;
-            if (mPosition > mLength)
+            if (mPosition > mLength) {
                 throw new EOFException();
+            }
             int ch1 = super.read();
             int ch2 = super.read();
-            if ((ch1 | ch2) < 0)
+            if ((ch1 | ch2) < 0) {
                 throw new EOFException();
+            }
             if (mByteOrder == LITTLE_ENDIAN) {
                 return ((ch2 << 8) + (ch1));
             } else if (mByteOrder == BIG_ENDIAN) {
@@ -2166,8 +2215,9 @@
 
         public long readLong() throws IOException {
             mPosition += 8;
-            if (mPosition > mLength)
+            if (mPosition > mLength) {
                 throw new EOFException();
+            }
             int ch1 = super.read();
             int ch2 = super.read();
             int ch3 = super.read();
@@ -2176,8 +2226,9 @@
             int ch6 = super.read();
             int ch7 = super.read();
             int ch8 = super.read();
-            if ((ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8) < 0)
+            if ((ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8) < 0) {
                 throw new EOFException();
+            }
             if (mByteOrder == LITTLE_ENDIAN) {
                 return (((long) ch8 << 56) + ((long) ch7 << 48) + ((long) ch6 << 40)
                         + ((long) ch5 << 32) + ((long) ch4 << 24) + ((long) ch3 << 16)
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index db0c5bb..2650ee0 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -1070,16 +1070,15 @@
      * A CryptoSession is obtained using {@link #getCryptoSession}
      */
     public final class CryptoSession {
-        private MediaDrm mDrm;
         private byte[] mSessionId;
 
-        CryptoSession(@NonNull MediaDrm drm, @NonNull byte[] sessionId,
-                @NonNull String cipherAlgorithm, @NonNull String macAlgorithm)
+        CryptoSession(@NonNull byte[] sessionId,
+                      @NonNull String cipherAlgorithm,
+                      @NonNull String macAlgorithm)
         {
             mSessionId = sessionId;
-            mDrm = drm;
-            setCipherAlgorithmNative(drm, sessionId, cipherAlgorithm);
-            setMacAlgorithmNative(drm, sessionId, macAlgorithm);
+            setCipherAlgorithmNative(MediaDrm.this, sessionId, cipherAlgorithm);
+            setMacAlgorithmNative(MediaDrm.this, sessionId, macAlgorithm);
         }
 
         /**
@@ -1092,7 +1091,7 @@
         @NonNull
         public byte[] encrypt(
                 @NonNull byte[] keyid, @NonNull byte[] input, @NonNull byte[] iv) {
-            return encryptNative(mDrm, mSessionId, keyid, input, iv);
+            return encryptNative(MediaDrm.this, mSessionId, keyid, input, iv);
         }
 
         /**
@@ -1105,7 +1104,7 @@
         @NonNull
         public byte[] decrypt(
                 @NonNull byte[] keyid, @NonNull byte[] input, @NonNull byte[] iv) {
-            return decryptNative(mDrm, mSessionId, keyid, input, iv);
+            return decryptNative(MediaDrm.this, mSessionId, keyid, input, iv);
         }
 
         /**
@@ -1116,7 +1115,7 @@
          */
         @NonNull
         public byte[] sign(@NonNull byte[] keyid, @NonNull byte[] message) {
-            return signNative(mDrm, mSessionId, keyid, message);
+            return signNative(MediaDrm.this, mSessionId, keyid, message);
         }
 
         /**
@@ -1130,7 +1129,7 @@
          */
         public boolean verify(
                 @NonNull byte[] keyid, @NonNull byte[] message, @NonNull byte[] signature) {
-            return verifyNative(mDrm, mSessionId, keyid, message, signature);
+            return verifyNative(MediaDrm.this, mSessionId, keyid, message, signature);
         }
     };
 
@@ -1158,7 +1157,7 @@
             @NonNull byte[] sessionId,
             @NonNull String cipherAlgorithm, @NonNull String macAlgorithm)
     {
-        return new CryptoSession(this, sessionId, cipherAlgorithm, macAlgorithm);
+        return new CryptoSession(sessionId, cipherAlgorithm, macAlgorithm);
     }
 
     /**
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 0b0306c..89e4577 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.graphics.Rect;
 import android.media.PlaybackParams;
@@ -1241,6 +1242,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS)
     public void setParentalControlsEnabled(boolean enabled) {
         try {
             mService.setParentalControlsEnabled(enabled, mUserId);
@@ -1292,6 +1294,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS)
     public void addBlockedRating(@NonNull TvContentRating rating) {
         Preconditions.checkNotNull(rating);
         try {
@@ -1310,6 +1313,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS)
     public void removeBlockedRating(@NonNull TvContentRating rating) {
         Preconditions.checkNotNull(rating);
         try {
@@ -1444,6 +1448,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
     public List<TvInputHardwareInfo> getHardwareList() {
         try {
             return mService.getHardwareList();
@@ -1462,6 +1467,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
     public Hardware acquireTvInputHardware(int deviceId, final HardwareCallback callback,
             TvInputInfo info) {
         try {
@@ -1488,6 +1494,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
     public void releaseTvInputHardware(int deviceId, Hardware hardware) {
         try {
             mService.releaseTvInputHardware(deviceId, hardware.getInterface(), mUserId);
diff --git a/media/jni/android_media_Utils.cpp b/media/jni/android_media_Utils.cpp
index 606e4dc..62685c9 100644
--- a/media/jni/android_media_Utils.cpp
+++ b/media/jni/android_media_Utils.cpp
@@ -745,8 +745,15 @@
         case HAL_PIXEL_FORMAT_BLOB:
             // Used for JPEG data, height must be 1, width == size, single plane.
             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
-            LOG_ALWAYS_FATAL_IF(buffer->height != 1,
-                    "BLOB format buffer should has height value %d", buffer->height);
+            // When RGBA override is being used, buffer height will be equal to width
+            if (usingRGBAOverride) {
+                LOG_ALWAYS_FATAL_IF(buffer->height != buffer->width,
+                        "RGBA override BLOB format buffer should have height == width");
+            } else {
+                LOG_ALWAYS_FATAL_IF(buffer->height != 1,
+                        "BLOB format buffer should have height value 1");
+            }
+
 
             pData = buffer->data;
             dataSize = Image_getJpegSize(buffer, usingRGBAOverride);
diff --git a/packages/DocumentsUI/res/layout/dialog_open_scoped_directory.xml b/packages/DocumentsUI/res/layout/dialog_open_scoped_directory.xml
new file mode 100644
index 0000000..d4a450b
--- /dev/null
+++ b/packages/DocumentsUI/res/layout/dialog_open_scoped_directory.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:paddingEnd="24dp"
+    android:paddingStart="24dp" >
+
+    <TextView
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/message"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:paddingEnd="24dp"
+        android:paddingStart="24dp"
+        android:paddingTop="24dp"
+        android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+        android:textColor="@*android:color/primary_text_default_material_light" >
+    </TextView>
+
+    <CheckBox
+        android:id="@+id/do_not_ask_checkbox"
+        style="?android:attr/textAppearanceSmall"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="16dip"
+        android:text="@string/never_ask_again"
+        android:visibility="gone" />
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index e2d1870..e7406e68 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -200,10 +200,12 @@
          during a copy. [CHAR LIMIT=48] -->
     <string name="notification_copy_files_converted_title">Some files were converted</string>
 
-    <!--  DO NOT TRANSLATE - final phrase has not been decided yet (b/26750152) -->
+    <!-- Text in an alert dialog asking user to grant app access to a given directory in an external storage volume -->
     <string name="open_external_dialog_request">Grant <xliff:g id="appName" example="System Settings"><b>^1</b></xliff:g>
-        access to <xliff:g id="directory" example="Pictures"><i>^2</i></xliff:g> folder on
+        access to <xliff:g id="directory" example="Pictures"><i>^2</i></xliff:g> directory on
         <xliff:g id="storage" example="SD Card"><i>^3</i></xliff:g>?</string>
+    <!-- Checkbox that allows user to not be questioned about the directory access request again -->
+    <string name="never_ask_again">Don\'t ask again</string>
     <!-- Text in the button asking user to allow access to a given directory. -->
     <string name="allow">Allow</string>
     <!-- Text in the button asking user to deny access to a given directory. -->
diff --git a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
index c7c61c3..8c4859f 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
@@ -16,10 +16,20 @@
 
 package com.android.documentsui;
 
+import static com.android.documentsui.Shared.DEBUG;
+import static com.android.documentsui.Shared.TAG;
 import static com.android.documentsui.State.MODE_UNKNOWN;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import android.annotation.IntDef;
+import android.annotation.Nullable;
 import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.UserHandle;
 import android.preference.PreferenceManager;
+import android.util.Log;
 
 import com.android.documentsui.State.ViewMode;
 import com.android.documentsui.model.RootInfo;
@@ -29,29 +39,73 @@
     private static final String ROOT_VIEW_MODE_PREFIX = "rootViewMode-";
 
     public static boolean getDisplayFileSize(Context context) {
-        return PreferenceManager.getDefaultSharedPreferences(context)
-                .getBoolean(KEY_FILE_SIZE, false);
+        return getPrefs(context).getBoolean(KEY_FILE_SIZE, false);
     }
 
-    public static @ViewMode int getViewMode(
-            Context context, RootInfo root, @ViewMode int fallback) {
-        return PreferenceManager.getDefaultSharedPreferences(context)
-                .getInt(createKey(root), fallback);
+    public static @ViewMode int getViewMode(Context context, RootInfo root,
+            @ViewMode int fallback) {
+        return getPrefs(context).getInt(createKey(root), fallback);
     }
 
     public static void setDisplayFileSize(Context context, boolean display) {
-        PreferenceManager.getDefaultSharedPreferences(context).edit()
-                .putBoolean(KEY_FILE_SIZE, display).apply();
+        getPrefs(context).edit().putBoolean(KEY_FILE_SIZE, display).apply();
     }
 
     public static void setViewMode(Context context, RootInfo root, @ViewMode int viewMode) {
         assert(viewMode != MODE_UNKNOWN);
 
-        PreferenceManager.getDefaultSharedPreferences(context).edit()
-                .putInt(createKey(root), viewMode).apply();
+        getPrefs(context).edit().putInt(createKey(root), viewMode).apply();
+    }
+
+    private static SharedPreferences getPrefs(Context context) {
+        return PreferenceManager.getDefaultSharedPreferences(context);
     }
 
     private static String createKey(RootInfo root) {
         return ROOT_VIEW_MODE_PREFIX + root.authority + root.rootId;
     }
+
+    public static final int PERMISSION_ASK = 0;
+    public static final int PERMISSION_ASK_AGAIN = 1;
+    public static final int PERMISSION_NEVER_ASK = -1;
+
+    @IntDef(flag = true, value = {
+            PERMISSION_ASK,
+            PERMISSION_ASK_AGAIN,
+            PERMISSION_NEVER_ASK,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PermissionStatus {}
+
+    /**
+     * Methods below are used to keep track of denied user requests on scoped directory access so
+     * the dialog is not offered when user checked the 'Do not ask again' box
+     *
+     * <p>It uses a shared preferences, whose key is:
+     * <ol>
+     * <li>{@code USER_ID|PACKAGE_NAME|VOLUME_UUID|DIRECTORY} for storage volumes that have a UUID
+     * (typically physical volumes like SD cards).
+     * <li>{@code USER_ID|PACKAGE_NAME||DIRECTORY} for storage volumes that do not have a UUID
+     * (typically the emulated volume used for primary storage
+     * </ol>
+     */
+    static @PermissionStatus int getScopedAccessPermissionStatus(Context context,
+            String packageName, @Nullable String uuid, String directory) {
+        final String key = getScopedAccessDenialsKey(packageName, uuid, directory);
+        return getPrefs(context).getInt(key, PERMISSION_ASK);
+    }
+
+    static void setScopedAccessPermissionStatus(Context context, String packageName,
+            @Nullable String uuid, String directory, @PermissionStatus int status) {
+      final String key = getScopedAccessDenialsKey(packageName, uuid, directory);
+      getPrefs(context).edit().putInt(key, status).apply();
+    }
+
+    private static String getScopedAccessDenialsKey(String packageName, String uuid,
+            String directory) {
+        final int userId = UserHandle.myUserId();
+        return uuid == null
+                ? userId + "|" + packageName + "||" + directory
+                : userId + "|" + packageName + "|" + uuid + "|" + directory;
+    }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
index afd308c..deef1c2 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
@@ -411,11 +411,15 @@
     public static final int SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED = 0;
     public static final int SCOPED_DIRECTORY_ACCESS_GRANTED = 1;
     public static final int SCOPED_DIRECTORY_ACCESS_DENIED = 2;
+    public static final int SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST = 3;
+    public static final int SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED = 4;
 
     @IntDef(flag = true, value = {
             SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED,
             SCOPED_DIRECTORY_ACCESS_GRANTED,
-            SCOPED_DIRECTORY_ACCESS_DENIED
+            SCOPED_DIRECTORY_ACCESS_DENIED,
+            SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST,
+            SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ScopedAccessGrant {}
@@ -432,23 +436,34 @@
         final String packageName = activity.getCallingPackage();
         switch (type) {
             case SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED:
-                MetricsLogger.action(activity,
-                        MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_PACKAGE,
-                        packageName);
-                MetricsLogger.action(activity,
-                        MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_FOLDER, index);
+                MetricsLogger.action(activity, MetricsEvent
+                        .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_PACKAGE, packageName);
+                MetricsLogger.action(activity, MetricsEvent
+                        .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_FOLDER, index);
                 break;
             case SCOPED_DIRECTORY_ACCESS_GRANTED:
-                MetricsLogger.action(activity,
-                        MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_PACKAGE, packageName);
-                MetricsLogger.action(activity,
-                        MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_FOLDER, index);
+                MetricsLogger.action(activity, MetricsEvent
+                        .ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_PACKAGE, packageName);
+                MetricsLogger.action(activity, MetricsEvent
+                        .ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_FOLDER, index);
                 break;
             case SCOPED_DIRECTORY_ACCESS_DENIED:
-                MetricsLogger.action(activity,
-                        MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_PACKAGE, packageName);
-                MetricsLogger.action(activity,
-                        MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_FOLDER, index);
+                MetricsLogger.action(activity, MetricsEvent
+                        .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_PACKAGE, packageName);
+                MetricsLogger.action(activity, MetricsEvent
+                        .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_FOLDER, index);
+                break;
+            case SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST:
+                MetricsLogger.action(activity, MetricsEvent
+                        .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST_BY_PACKAGE, packageName);
+                MetricsLogger.action(activity, MetricsEvent
+                        .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST_BY_FOLDER, index);
+                break;
+            case SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED:
+                MetricsLogger.action(activity, MetricsEvent
+                        .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED_BY_PACKAGE, packageName);
+                MetricsLogger.action(activity, MetricsEvent
+                        .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED_BY_FOLDER, index);
                 break;
             default:
                 Log.wtf(TAG, "invalid ScopedAccessGrant: " + type);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java b/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
index dc529ce..f30ab23 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
@@ -20,16 +20,24 @@
 import static android.os.Environment.STANDARD_DIRECTORIES;
 import static android.os.storage.StorageVolume.EXTRA_DIRECTORY_NAME;
 import static android.os.storage.StorageVolume.EXTRA_STORAGE_VOLUME;
-import static com.android.documentsui.Shared.DEBUG;
-import static com.android.documentsui.Metrics.logInvalidScopedAccessRequest;
-import static com.android.documentsui.Metrics.logValidScopedAccessRequest;
+import static com.android.documentsui.LocalPreferences.getScopedAccessPermissionStatus;
+import static com.android.documentsui.LocalPreferences.PERMISSION_ASK;
+import static com.android.documentsui.LocalPreferences.PERMISSION_ASK_AGAIN;
+import static com.android.documentsui.LocalPreferences.PERMISSION_NEVER_ASK;
+import static com.android.documentsui.LocalPreferences.setScopedAccessPermissionStatus;
+import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED;
 import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED;
 import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_DENIED;
+import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST;
 import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_ERROR;
 import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_GRANTED;
 import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS;
 import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY;
+import static com.android.documentsui.Metrics.logInvalidScopedAccessRequest;
+import static com.android.documentsui.Metrics.logValidScopedAccessRequest;
+import static com.android.documentsui.Shared.DEBUG;
 
+import android.annotation.SuppressLint;
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.AlertDialog;
@@ -38,7 +46,6 @@
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
 import android.content.ContentProviderClient;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnClickListener;
@@ -57,6 +64,11 @@
 import android.provider.DocumentsContract;
 import android.text.TextUtils;
 import android.util.Log;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.TextView;
 
 import java.io.File;
 import java.io.IOException;
@@ -72,12 +84,17 @@
     private static final String EXTRA_FILE = "com.android.documentsui.FILE";
     private static final String EXTRA_APP_LABEL = "com.android.documentsui.APP_LABEL";
     private static final String EXTRA_VOLUME_LABEL = "com.android.documentsui.VOLUME_LABEL";
+    private static final String EXTRA_VOLUME_UUID = "com.android.documentsui.VOLUME_UUID";
 
     private ContentProviderClient mExternalStorageClient;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        if (savedInstanceState != null) {
+            if (DEBUG) Log.d(TAG, "activity.onCreateDialog(): reusing instance");
+            return;
+        }
 
         final Intent intent = getIntent();
         if (intent == null) {
@@ -105,9 +122,18 @@
             finish();
             return;
         }
+        final StorageVolume volume = (StorageVolume) storageVolume;
+        if (getScopedAccessPermissionStatus(getApplicationContext(), getCallingPackage(),
+                volume.getUuid(), directoryName) == PERMISSION_NEVER_ASK) {
+            logValidScopedAccessRequest(this, directoryName,
+                    SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED);
+            setResult(RESULT_CANCELED);
+            finish();
+            return;
+        }
 
         final int userId = UserHandle.myUserId();
-        if (!showFragment(this, userId, (StorageVolume) storageVolume, directoryName)) {
+        if (!showFragment(this, userId, volume, directoryName)) {
             setResult(RESULT_CANCELED);
             finish();
             return;
@@ -157,6 +183,7 @@
 
         // Gets volume label and converted path.
         String volumeLabel = null;
+        String volumeUuid = null;
         final List<VolumeInfo> volumes = sm.getVolumes();
         if (DEBUG) Log.d(TAG, "Number of volumes: " + volumes.size());
         for (VolumeInfo volume : volumes) {
@@ -166,6 +193,7 @@
                 if (DEBUG) Log.d(TAG, "Converting " + root + " to " + internalRoot);
                 file = new File(internalRoot, directory);
                 volumeLabel = sm.getBestVolumeDescription(volume);
+                volumeUuid = volume.getFsUuid();
                 break;
             }
         }
@@ -197,6 +225,7 @@
         final Bundle args = new Bundle();
         args.putString(EXTRA_FILE, file.getAbsolutePath());
         args.putString(EXTRA_VOLUME_LABEL, volumeLabel);
+        args.putString(EXTRA_VOLUME_UUID, volumeUuid);
         args.putString(EXTRA_APP_LABEL, appLabel);
 
         final FragmentManager fm = activity.getFragmentManager();
@@ -303,16 +332,21 @@
     public static class OpenExternalDirectoryDialogFragment extends DialogFragment {
 
         private File mFile;
+        private String mVolumeUuid;
         private String mVolumeLabel;
         private String mAppLabel;
+        private CheckBox mDontAskAgain;
         private OpenExternalDirectoryActivity mActivity;
+        private AlertDialog mDialog;
 
         @Override
         public void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
+            setRetainInstance(true);
             final Bundle args = getArguments();
             if (args != null) {
                 mFile = new File(args.getString(EXTRA_FILE));
+                mVolumeUuid = args.getString(EXTRA_VOLUME_UUID);
                 mVolumeLabel = args.getString(EXTRA_VOLUME_LABEL);
                 mAppLabel = args.getString(EXTRA_APP_LABEL);
             }
@@ -320,9 +354,28 @@
         }
 
         @Override
+        public void onDestroyView() {
+            // Workaround for https://code.google.com/p/android/issues/detail?id=17423
+            if (mDialog != null && getRetainInstance()) {
+                mDialog.setDismissMessage(null);
+            }
+            super.onDestroyView();
+        }
+
+        @Override
         public Dialog onCreateDialog(Bundle savedInstanceState) {
+            if (mDialog != null) {
+                if (DEBUG) Log.d(TAG, "fragment.onCreateDialog(): reusing dialog");
+                return mDialog;
+            }
+            if (mActivity != getActivity()) {
+                // Sanity check.
+                Log.wtf(TAG, "activity references don't match on onCreateDialog(): mActivity = "
+                        + mActivity + " , getActivity() = " + getActivity());
+                mActivity = (OpenExternalDirectoryActivity) getActivity();
+            }
             final String directory = mFile.getName();
-            final Activity activity = getActivity();
+            final Context context = mActivity.getApplicationContext();
             final OnClickListener listener = new OnClickListener() {
 
                 @Override
@@ -333,15 +386,25 @@
                                 mActivity.getExternalStorageClient(), mFile);
                     }
                     if (which == DialogInterface.BUTTON_NEGATIVE || intent == null) {
-                        logValidScopedAccessRequest(activity, directory,
+                        logValidScopedAccessRequest(mActivity, directory,
                                 SCOPED_DIRECTORY_ACCESS_DENIED);
-                        activity.setResult(RESULT_CANCELED);
+                        final boolean checked = mDontAskAgain.isChecked();
+                        if (checked) {
+                            logValidScopedAccessRequest(mActivity, directory,
+                                    SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST);
+                            setScopedAccessPermissionStatus(context, mActivity.getCallingPackage(),
+                                    mVolumeUuid, directory, PERMISSION_NEVER_ASK);
+                        } else {
+                            setScopedAccessPermissionStatus(context, mActivity.getCallingPackage(),
+                                    mVolumeUuid, directory, PERMISSION_ASK_AGAIN);
+                        }
+                        mActivity.setResult(RESULT_CANCELED);
                     } else {
-                        logValidScopedAccessRequest(activity, directory,
+                        logValidScopedAccessRequest(mActivity, directory,
                                 SCOPED_DIRECTORY_ACCESS_GRANTED);
-                        activity.setResult(RESULT_OK, intent);
+                        mActivity.setResult(RESULT_OK, intent);
                     }
-                    activity.finish();
+                    mActivity.finish();
                 }
             };
 
@@ -349,11 +412,31 @@
                     .expandTemplate(
                             getText(R.string.open_external_dialog_request), mAppLabel, directory,
                             mVolumeLabel);
-            return new AlertDialog.Builder(activity, R.style.AlertDialogTheme)
-                    .setMessage(message)
+            @SuppressLint("InflateParams")
+            // It's ok pass null ViewRoot on AlertDialogs.
+            final View view = View.inflate(mActivity, R.layout.dialog_open_scoped_directory, null);
+            final TextView messageField = (TextView) view.findViewById(R.id.message);
+            messageField.setText(message);
+            mDialog = new AlertDialog.Builder(mActivity, R.style.AlertDialogTheme)
+                    .setView(view)
                     .setPositiveButton(R.string.allow, listener)
                     .setNegativeButton(R.string.deny, listener)
                     .create();
+
+            mDontAskAgain = (CheckBox) view.findViewById(R.id.do_not_ask_checkbox);
+            if (getScopedAccessPermissionStatus(context, mActivity.getCallingPackage(),
+                    mVolumeUuid, directory) == PERMISSION_ASK_AGAIN) {
+                mDontAskAgain.setVisibility(View.VISIBLE);
+                mDontAskAgain.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+
+                    @Override
+                    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+                        mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(!isChecked);
+                    }
+                });
+            }
+
+            return mDialog;
         }
 
         @Override
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
index 26900a7..b539421 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
@@ -86,12 +86,6 @@
      */
     public static final String EXTRA_IGNORE_STATE = "ignoreState";
 
-
-    /**
-     * String prefix used to indicate the document is a directory.
-     */
-    public static final char DIR_PREFIX = '\001';
-
     private static final Collator sCollator;
 
     static {
@@ -150,12 +144,6 @@
         if (leftEmpty) return -1;
         if (rightEmpty) return 1;
 
-        final boolean leftDir = (lhs.charAt(0) == DIR_PREFIX);
-        final boolean rightDir = (rhs.charAt(0) == DIR_PREFIX);
-
-        if (leftDir && !rightDir) return -1;
-        if (rightDir && !leftDir) return 1;
-
         return sCollator.compare(lhs, rhs);
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
index ab4f5c4..c5ee592 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
@@ -153,48 +153,53 @@
     private void updateModelData() {
         int[] positions = new int[mCursorCount];
         mIds = new String[mCursorCount];
-        String[] stringValues = new String[mCursorCount];
+        boolean[] isDirs = new boolean[mCursorCount];
+        String[] displayNames = null;
         long[] longValues = null;
 
-        if (mSortOrder == SORT_ORDER_LAST_MODIFIED || mSortOrder == SORT_ORDER_SIZE) {
-            longValues = new long[mCursorCount];
+        switch (mSortOrder) {
+            case SORT_ORDER_DISPLAY_NAME:
+                displayNames = new String[mCursorCount];
+                break;
+            case SORT_ORDER_LAST_MODIFIED:
+            case SORT_ORDER_SIZE:
+                longValues = new long[mCursorCount];
+                break;
         }
 
+        String mimeType;
+
         mCursor.moveToPosition(-1);
         for (int pos = 0; pos < mCursorCount; ++pos) {
             mCursor.moveToNext();
             positions[pos] = pos;
             mIds[pos] = createModelId(mCursor);
 
+            mimeType = getCursorString(mCursor, Document.COLUMN_MIME_TYPE);
+            isDirs[pos] = Document.MIME_TYPE_DIR.equals(mimeType);
+
             switch(mSortOrder) {
                 case SORT_ORDER_DISPLAY_NAME:
-                    final String mimeType = getCursorString(mCursor, Document.COLUMN_MIME_TYPE);
                     final String displayName = getCursorString(
                             mCursor, Document.COLUMN_DISPLAY_NAME);
-                    if (Document.MIME_TYPE_DIR.equals(mimeType)) {
-                        stringValues[pos] = Shared.DIR_PREFIX + displayName;
-                    } else {
-                        stringValues[pos] = displayName;
-                    }
+                    displayNames[pos] = displayName;
                     break;
                 case SORT_ORDER_LAST_MODIFIED:
                     longValues[pos] = getLastModified(mCursor);
-                    stringValues[pos] = getCursorString(mCursor, Document.COLUMN_MIME_TYPE);
                     break;
                 case SORT_ORDER_SIZE:
                     longValues[pos] = getCursorLong(mCursor, Document.COLUMN_SIZE);
-                    stringValues[pos] = getCursorString(mCursor, Document.COLUMN_MIME_TYPE);
                     break;
             }
         }
 
         switch (mSortOrder) {
             case SORT_ORDER_DISPLAY_NAME:
-                binarySort(stringValues, positions, mIds);
+                binarySort(displayNames, isDirs, positions, mIds);
                 break;
             case SORT_ORDER_LAST_MODIFIED:
             case SORT_ORDER_SIZE:
-                binarySort(longValues, stringValues, positions, mIds);
+                binarySort(longValues, isDirs, positions, mIds);
                 break;
         }
 
@@ -207,18 +212,20 @@
 
     /**
      * Sorts model data. Takes three columns of index-corresponded data. The first column is the
-     * sort key. Rows are sorted in ascending alphabetical order on the sort key. This code is based
-     * on TimSort.binarySort().
+     * sort key. Rows are sorted in ascending alphabetical order on the sort key.
+     * Directories are always shown first. This code is based on TimSort.binarySort().
      *
      * @param sortKey Data is sorted in ascending alphabetical order.
+     * @param isDirs Array saying whether an item is a directory or not.
      * @param positions Cursor positions to be sorted.
      * @param ids Model IDs to be sorted.
      */
-    private static void binarySort(String[] sortKey, int[] positions, String[] ids) {
+    private static void binarySort(String[] sortKey, boolean[] isDirs, int[] positions, String[] ids) {
         final int count = positions.length;
         for (int start = 1; start < count; start++) {
             final int pivotPosition = positions[start];
             final String pivotValue = sortKey[start];
+            final boolean pivotIsDir = isDirs[start];
             final String pivotId = ids[start];
 
             int left = 0;
@@ -227,9 +234,18 @@
             while (left < right) {
                 int mid = (left + right) >>> 1;
 
-                final String lhs = pivotValue;
-                final String rhs = sortKey[mid];
-                final int compare = Shared.compareToIgnoreCaseNullable(lhs, rhs);
+                // Directories always go in front.
+                int compare = 0;
+                final boolean rhsIsDir = isDirs[mid];
+                if (pivotIsDir && !rhsIsDir) {
+                    compare = -1;
+                } else if (!pivotIsDir && rhsIsDir) {
+                    compare = 1;
+                } else {
+                    final String lhs = pivotValue;
+                    final String rhs = sortKey[mid];
+                    compare = Shared.compareToIgnoreCaseNullable(lhs, rhs);
+                }
 
                 if (compare < 0) {
                     right = mid;
@@ -243,20 +259,24 @@
                 case 2:
                     positions[left + 2] = positions[left + 1];
                     sortKey[left + 2] = sortKey[left + 1];
+                    isDirs[left + 2] = isDirs[left + 1];
                     ids[left + 2] = ids[left + 1];
                 case 1:
                     positions[left + 1] = positions[left];
                     sortKey[left + 1] = sortKey[left];
+                    isDirs[left + 1] = isDirs[left];
                     ids[left + 1] = ids[left];
                     break;
                 default:
                     System.arraycopy(positions, left, positions, left + 1, n);
                     System.arraycopy(sortKey, left, sortKey, left + 1, n);
+                    System.arraycopy(isDirs, left, isDirs, left + 1, n);
                     System.arraycopy(ids, left, ids, left + 1, n);
             }
 
             positions[left] = pivotPosition;
             sortKey[left] = pivotValue;
+            isDirs[left] = pivotIsDir;
             ids[left] = pivotId;
         }
     }
@@ -268,17 +288,17 @@
      * numerical order on the sort key. This code is based on TimSort.binarySort().
      *
      * @param sortKey Data is sorted in descending numerical order.
-     * @param mimeTypes Corresponding mime types. Directories will be sorted ahead of documents.
+     * @param isDirs Array saying whether an item is a directory or not.
      * @param positions Cursor positions to be sorted.
      * @param ids Model IDs to be sorted.
      */
     private static void binarySort(
-            long[] sortKey, String[] mimeTypes, int[] positions, String[] ids) {
+            long[] sortKey, boolean[] isDirs, int[] positions, String[] ids) {
         final int count = positions.length;
         for (int start = 1; start < count; start++) {
             final int pivotPosition = positions[start];
             final long pivotValue = sortKey[start];
-            final String pivotMime = mimeTypes[start];
+            final boolean pivotIsDir = isDirs[start];
             final String pivotId = ids[start];
 
             int left = 0;
@@ -287,13 +307,12 @@
             while (left < right) {
                 int mid = ((left + right) >>> 1);
 
-                // First bucket by mime type.  Directories always go in front.
+                // Directories always go in front.
                 int compare = 0;
-                final boolean lhsIsDir = Document.MIME_TYPE_DIR.equals(pivotMime);
-                final boolean rhsIsDir = Document.MIME_TYPE_DIR.equals(mimeTypes[mid]);
-                if (lhsIsDir && !rhsIsDir) {
+                final boolean rhsIsDir = isDirs[mid];
+                if (pivotIsDir && !rhsIsDir) {
                     compare = -1;
-                } else if (!lhsIsDir && rhsIsDir) {
+                } else if (!pivotIsDir && rhsIsDir) {
                     compare = 1;
                 } else {
                     final long lhs = pivotValue;
@@ -323,24 +342,24 @@
                 case 2:
                     positions[left + 2] = positions[left + 1];
                     sortKey[left + 2] = sortKey[left + 1];
-                    mimeTypes[left + 2] = mimeTypes[left + 1];
+                    isDirs[left + 2] = isDirs[left + 1];
                     ids[left + 2] = ids[left + 1];
                 case 1:
                     positions[left + 1] = positions[left];
                     sortKey[left + 1] = sortKey[left];
-                    mimeTypes[left + 1] = mimeTypes[left];
+                    isDirs[left + 1] = isDirs[left];
                     ids[left + 1] = ids[left];
                     break;
                 default:
                     System.arraycopy(positions, left, positions, left + 1, n);
                     System.arraycopy(sortKey, left, sortKey, left + 1, n);
-                    System.arraycopy(mimeTypes, left, mimeTypes, left + 1, n);
+                    System.arraycopy(isDirs, left, isDirs, left + 1, n);
                     System.arraycopy(ids, left, ids, left + 1, n);
             }
 
             positions[left] = pivotPosition;
             sortKey[left] = pivotValue;
-            mimeTypes[left] = pivotMime;
+            isDirs[left] = pivotIsDir;
             ids[left] = pivotId;
         }
     }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
index 59dc232..e4afc3d 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
@@ -183,6 +183,7 @@
 
     // We don't really need to test the entirety of download support
     // since downloads is (almost) just another provider.
+    @Suppress
     public void testDownload_Queued() throws Exception {
         DownloadManager dm = (DownloadManager) context.getSystemService(
                 Context.DOWNLOAD_SERVICE);
@@ -194,6 +195,7 @@
         bots.directory.assertDocumentsPresent("Queued");
     }
 
+    @Suppress
     public void testDownload_RetryUnsuccessful() throws Exception {
         DownloadManager dm = (DownloadManager) context.getSystemService(
                 Context.DOWNLOAD_SERVICE);
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index d4d4591..58ff401 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -36,7 +36,6 @@
 import android.provider.DocumentsContract;
 import android.provider.DocumentsProvider;
 import android.provider.Settings;
-import android.provider.Settings.SettingNotFoundException;
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
@@ -48,6 +47,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.TimeoutException;
 
 /**
  * DocumentsProvider for MTP devices.
@@ -426,7 +426,7 @@
                     closeDeviceInternal(id);
                 }
                 mRootScanner.pause();
-            } catch (InterruptedException|IOException e) {
+            } catch (InterruptedException | IOException | TimeoutException e) {
                 // It should fail unit tests by throwing runtime exception.
                 throw new RuntimeException(e);
             } finally {
@@ -464,9 +464,6 @@
         getDeviceToolkit(deviceId).close();
         mDeviceToolkits.remove(deviceId);
         mMtpManager.closeDevice(deviceId);
-        if (mDeviceToolkits.size() == 0) {
-            mRootScanner.pause();
-        }
     }
 
     private DeviceToolkit getDeviceToolkit(int deviceId) throws FileNotFoundException {
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java b/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
index 2f66c5c..2e9133b 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
@@ -27,6 +27,7 @@
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 final class RootScanner {
     /**
@@ -95,15 +96,19 @@
      * Stops background thread and wait for its termination.
      * @throws InterruptedException
      */
-    synchronized void pause() throws InterruptedException {
+    synchronized void pause() throws InterruptedException, TimeoutException {
         if (mExecutor == null) {
             return;
         }
         mExecutor.shutdownNow();
-        if (!mExecutor.awaitTermination(AWAIT_TERMINATION_TIMEOUT, TimeUnit.MILLISECONDS)) {
-            Log.e(MtpDocumentsProvider.TAG, "Failed to terminate RootScanner's background thread.");
+        try {
+            if (!mExecutor.awaitTermination(AWAIT_TERMINATION_TIMEOUT, TimeUnit.MILLISECONDS)) {
+                throw new TimeoutException(
+                        "Timeout for terminating RootScanner's background thread.");
+            }
+        } finally {
+            mExecutor = null;
         }
-        mExecutor = null;
     }
 
     /**
@@ -173,6 +178,9 @@
                 }
                 mFirstScanCompleted.countDown();
                 pollingCount++;
+                if (devices.length == 0) {
+                    break;
+                }
                 try {
                     // Use SHORT_POLLING_PERIOD for the first SHORT_POLLING_TIMES because it is
                     // more likely to add new root just after the device is added.
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
index d6ad0f3..afcb457 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
@@ -262,11 +262,9 @@
                 null));
         {
             mProvider.openDevice(0);
-            mProvider.resumeRootScanner();
             mResolver.waitForNotification(ROOTS_URI, 1);
 
             mProvider.openDevice(1);
-            mProvider.resumeRootScanner();
             mResolver.waitForNotification(ROOTS_URI, 2);
 
             final Cursor cursor = mProvider.queryRoots(null);
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
index cdddd81..a08d9ee 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
@@ -48,6 +48,7 @@
     @Override
     protected void tearDown() throws Exception {
         assertTrue(mPipeManager.close());
+        mDatabase.close();
     }
 
     public void testReadDocument_basic() throws Exception {
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
index 47023c1..d0aba22 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
@@ -146,12 +146,13 @@
     public boolean setDisabledByAdmin(EnforcedAdmin admin) {
         final boolean disabled = (admin != null ? true : false);
         mEnforcedAdmin = admin;
-        mPreference.setEnabled(!disabled);
+        boolean changed = false;
         if (mDisabledByAdmin != disabled) {
             mDisabledByAdmin = disabled;
-            return true;
+            changed = true;
         }
-        return false;
+        mPreference.setEnabled(!disabled);
+        return changed;
     }
 
     public boolean isDisabledByAdmin() {
diff --git a/packages/SystemUI/res/layout/tv_pip_onboarding.xml b/packages/SystemUI/res/layout/tv_pip_onboarding.xml
index f031bb4..b0814cf 100644
--- a/packages/SystemUI/res/layout/tv_pip_onboarding.xml
+++ b/packages/SystemUI/res/layout/tv_pip_onboarding.xml
@@ -37,10 +37,13 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginTop="24dp"
+        android:paddingStart="24dp"
+        android:paddingEnd="24dp"
         android:fontFamily="sans-serif"
         android:textSize="16sp"
         android:textColor="#EEEEEE"
         android:lineSpacingMultiplier="1.28"
+        android:gravity="top|center_horizontal"
         android:text="@string/pip_onboarding_description" />
     <Button
         android:id="@+id/close"
diff --git a/packages/SystemUI/res/layout/tv_pip_overlay.xml b/packages/SystemUI/res/layout/tv_pip_overlay.xml
index 40c6fa1..1ba423b 100644
--- a/packages/SystemUI/res/layout/tv_pip_overlay.xml
+++ b/packages/SystemUI/res/layout/tv_pip_overlay.xml
@@ -24,13 +24,19 @@
     <TextView
         android:id="@+id/guide_overlay"
         android:layout_width="match_parent"
-        android:layout_height="32dp"
+        android:layout_height="wrap_content"
         android:layout_alignParentBottom="true"
+        android:paddingTop="6dp"
+        android:paddingBottom="6dp"
+        android:paddingStart="10dp"
+        android:paddingEnd="10dp"
         android:textSize="14sp"
         android:textColor="#EEEEEE"
         android:fontFamily="sans-serif"
         android:background="@drawable/tv_pip_overlay_background"
+        android:lineSpacingMultiplier="1.465"
         android:gravity="center"
+        android:maxLines="2"
         android:text="@string/pip_hold_home" />
     <LinearLayout
         android:id="@+id/guide_buttons"
diff --git a/packages/SystemUI/res/values/strings_tv.xml b/packages/SystemUI/res/values/strings_tv.xml
index b35038d..0e1fe8f 100644
--- a/packages/SystemUI/res/values/strings_tv.xml
+++ b/packages/SystemUI/res/values/strings_tv.xml
@@ -27,13 +27,12 @@
     <string name="pip_play">Play</string>
     <!-- Button to pause the current media on picture-in-picture (PIP) [CHAR LIMIT=16] -->
     <string name="pip_pause">Pause</string>
-    <!-- Overlay text on picture-in-picture (PIP) to indicate that longpress HOME key to control PIP [CHAR LIMIT=25] -->
+    <!-- Overlay text on picture-in-picture (PIP) to indicate that longpress HOME key to control PIP [CHAR LIMIT=52] -->
     <string name="pip_hold_home">Hold <b>HOME</b> to control PIP</string>
     <!-- Picture-in-Picture (PIP) onboarding screen -->
     <eat-comment />
-    <!-- Description for picture-in-picture (PIP) onboarding screen to indicate that longpress HOME key to control PIP.
-         Line break is needed as if we have CHAR LIMIT=25. [CHAR LIMIT=NONE] -->
-    <string name="pip_onboarding_description">Press and hold the HOME\nbutton to control PIP</string>
+    <!-- Description for picture-in-picture (PIP) onboarding screen to indicate that longpress HOME key to control PIP. [CHAR LIMIT=NONE] -->
+    <string name="pip_onboarding_description">Press and hold the HOME button to control PIP</string>
     <!-- Button to close picture-in-picture (PIP) onboarding screen. -->
     <string name="pip_onboarding_button">Got it</string>
     <!-- Font for Recents -->
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 312d3c5..02b860c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -811,7 +811,7 @@
         intent.putExtra("seq", mDelayedShowingSequence);
         PendingIntent sender = PendingIntent.getBroadcast(mContext,
                 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
-        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, sender);
+        mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, sender);
         if (DEBUG) Log.d(TAG, "setting alarm to turn off keyguard, seq = "
                          + mDelayedShowingSequence);
         doKeyguardLaterForChildProfilesLocked();
@@ -828,7 +828,8 @@
                 lockIntent.putExtra(Intent.EXTRA_USER_ID, info.id);
                 PendingIntent lockSender = PendingIntent.getBroadcast(
                         mContext, 0, lockIntent, PendingIntent.FLAG_CANCEL_CURRENT);
-                mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, userWhen, lockSender);
+                mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+                        userWhen, lockSender);
             }
         }
     }
@@ -1542,13 +1543,22 @@
             try {
                 mStatusBarKeyguardViewManager.keyguardGoingAway();
 
+                int flags = 0;
+                if (mStatusBarKeyguardViewManager.shouldDisableWindowAnimationsForUnlock()
+                        || mWakeAndUnlocking) {
+                    flags |= WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
+                }
+                if (mStatusBarKeyguardViewManager.isGoingToNotificationShade()) {
+                    flags |= WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
+                }
+                if (mStatusBarKeyguardViewManager.isUnlockWithWallpaper()) {
+                    flags |= WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
+                }
+
                 // Don't actually hide the Keyguard at the moment, wait for window
                 // manager until it tells us it's safe to do so with
                 // startKeyguardExitAnimation.
-                ActivityManagerNative.getDefault().keyguardGoingAway(
-                        mStatusBarKeyguardViewManager.shouldDisableWindowAnimationsForUnlock()
-                                || mWakeAndUnlocking,
-                        mStatusBarKeyguardViewManager.isGoingToNotificationShade());
+                ActivityManagerNative.getDefault().keyguardGoingAway(flags);
             } catch (RemoteException e) {
                 Log.e(TAG, "Error while calling WindowManager", e);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 906bd0f..bf58611 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1887,10 +1887,16 @@
             if (mBackdrop.getVisibility() != View.VISIBLE) {
                 mBackdrop.setVisibility(View.VISIBLE);
                 if (allowEnterAnimation) {
-                    mBackdrop.animate().alpha(1f);
+                    mBackdrop.animate().alpha(1f).withEndAction(new Runnable() {
+                        @Override
+                        public void run() {
+                            mStatusBarWindowManager.setBackdropShowing(true);
+                        }
+                    });
                 } else {
                     mBackdrop.animate().cancel();
                     mBackdrop.setAlpha(1f);
+                    mStatusBarWindowManager.setBackdropShowing(true);
                 }
                 metaDataChanged = true;
                 if (DEBUG_MEDIA) {
@@ -1948,7 +1954,9 @@
                     // We are unlocking directly - no animation!
                     mBackdrop.setVisibility(View.GONE);
                     mBackdropBack.setImageDrawable(null);
+                    mStatusBarWindowManager.setBackdropShowing(false);
                 } else {
+                    mStatusBarWindowManager.setBackdropShowing(false);
                     mBackdrop.animate()
                             // Never let the alpha become zero - otherwise the RenderNode
                             // won't draw anything and uninitialized memory will show through
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 2ba1562..117e2b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -227,6 +227,10 @@
         mStatusBarWindowManager.setKeyguardNeedsInput(needsInput);
     }
 
+    public boolean isUnlockWithWallpaper() {
+        return mStatusBarWindowManager.isShowingWallpaper();
+    }
+
     public void setOccluded(boolean occluded) {
         if (occluded && !mOccluded && mShowing) {
             if (mPhoneStatusBar.isInLaunchTransition()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index 77ece93..ada7450 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -100,12 +100,16 @@
 
     private void applyKeyguardFlags(State state) {
         if (state.keyguardShowing) {
-            mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
             mLpChanged.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
         } else {
-            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
             mLpChanged.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
         }
+
+        if (state.keyguardShowing && !state.backdropShowing) {
+            mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+        } else {
+            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+        }
     }
 
     private void adjustScreenOrientation(State state) {
@@ -255,6 +259,11 @@
         apply(mCurrentState);
     }
 
+    public void setBackdropShowing(boolean showing) {
+        mCurrentState.backdropShowing = showing;
+        apply(mCurrentState);
+    }
+
     public void setKeyguardFadingAway(boolean keyguardFadingAway) {
         mCurrentState.keyguardFadingAway = keyguardFadingAway;
         apply(mCurrentState);
@@ -323,6 +332,10 @@
         pw.println(mCurrentState);
     }
 
+    public boolean isShowingWallpaper() {
+        return !mCurrentState.backdropShowing;
+    }
+
     private static class State {
         boolean keyguardShowing;
         boolean keyguardOccluded;
@@ -338,6 +351,7 @@
         boolean forceCollapsed;
         boolean forceDozeBrightness;
         boolean forceUserActivity;
+        boolean backdropShowing;
 
         /**
          * The {@link BaseStatusBar} state from the status bar.
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index d36a1d7..d929519 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -1996,6 +1996,22 @@
     // Logs that the user docks window via shortcut key.
     WINDOW_DOCK_SHORTCUTS = 352;
 
+    // User already denied access to the request folder; action takes an integer
+    // representing the folder's index on Environment.STANDARD_DIRECTORIES
+    ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED_BY_FOLDER = 353;
+
+    // User already denied access to the request folder; action pass package name
+    // of calling package.
+    ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED_BY_PACKAGE = 354;
+
+    // User denied access to the request folder and checked 'Do not ask again';
+    // action takes an integer representing the folder's index on Environment.STANDARD_DIRECTORIES
+    ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST_BY_FOLDER = 355;
+
+    // User denied access to the request folder and checked 'Do not ask again';
+    // action pass package name of calling package.
+    ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST_BY_PACKAGE = 356;
+
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
   }
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 3659a40..a4f85db 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -210,6 +210,7 @@
     private final UserManager mUserManager;
     private final AppOpsManager mAppOpsManager;
     private final KeyguardManager mKeyguardManager;
+    private final DevicePolicyManagerInternal mDevicePolicyManagerInternal;
 
     private final SecurityPolicy mSecurityPolicy;
 
@@ -232,6 +233,7 @@
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
         mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
         mKeyguardManager = (KeyguardManager) mContext.getSystemService(KEYGUARD_SERVICE);
+        mDevicePolicyManagerInternal = LocalServices.getService(DevicePolicyManagerInternal.class);
         mSaveStateHandler = BackgroundThread.getHandler();
         mCallbackHandler = new CallbackHandler(mContext.getMainLooper());
         mBackupRestoreController = new BackupRestoreController();
@@ -298,11 +300,9 @@
     }
 
     private void registerOnCrossProfileProvidersChangedListener() {
-        DevicePolicyManagerInternal devicePolicyManager = LocalServices.getService(
-                DevicePolicyManagerInternal.class);
         // The device policy is an optional component.
-        if (devicePolicyManager != null) {
-            devicePolicyManager.addOnCrossProfileWidgetProvidersChangeListener(this);
+        if (mDevicePolicyManagerInternal != null) {
+            mDevicePolicyManagerInternal.addOnCrossProfileWidgetProvidersChangeListener(this);
         }
     }
 
@@ -588,7 +588,7 @@
             try {
                 UserInfo userInfo = mUserManager.getUserInfo(providerUserId);
                 showBadge = userInfo.isManagedProfile();
-                onClickIntent = UnlaunchableAppActivity.createPackageSuspendedDialogIntent(
+                onClickIntent = mDevicePolicyManagerInternal.createPackageSuspendedDialogIntent(
                         providerPackage, providerUserId);
             } finally {
                 Binder.restoreCallingIdentity(identity);
@@ -3574,15 +3574,12 @@
         }
 
         public boolean isProviderWhiteListed(String packageName, int profileId) {
-            DevicePolicyManagerInternal devicePolicyManager = LocalServices.getService(
-                    DevicePolicyManagerInternal.class);
-
             // If the policy manager is not available on the device we deny it all.
-            if (devicePolicyManager == null) {
+            if (mDevicePolicyManagerInternal == null) {
                 return false;
             }
 
-            List<String> crossProfilePackages = devicePolicyManager
+            List<String> crossProfilePackages = mDevicePolicyManagerInternal
                     .getCrossProfileWidgetProviders(profileId);
 
             return crossProfilePackages.contains(packageName);
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 11888ff..4198af9 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -67,7 +67,8 @@
         "/system/bin/audioserver",
         "/system/bin/mediaserver",
         "/system/bin/sdcard",
-        "/system/bin/surfaceflinger"
+        "/system/bin/surfaceflinger",
+        "media.log"
     };
 
     static Watchdog sWatchdog;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f99d035..95dbd0f 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6497,15 +6497,13 @@
     }
 
     @Override
-    public void keyguardGoingAway(boolean disableWindowAnimations,
-            boolean keyguardGoingToNotificationShade) {
+    public void keyguardGoingAway(int flags) {
         enforceNotIsolatedCaller("keyguardGoingAway");
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (this) {
                 if (DEBUG_LOCKSCREEN) logLockScreen("");
-                mWindowManager.keyguardGoingAway(disableWindowAnimations,
-                        keyguardGoingToNotificationShade);
+                mWindowManager.keyguardGoingAway(flags);
                 if (mLockScreenShown == LOCK_SCREEN_SHOWN) {
                     mLockScreenShown = LOCK_SCREEN_HIDDEN;
                     updateSleepIfNeededLocked();
@@ -11198,7 +11196,6 @@
     }
 
     void finishRunningVoiceLocked() {
-        Slog.d(TAG, "finishRunningVoiceLocked()  >>>>");
         if (mRunningVoice != null) {
             mRunningVoice = null;
             mVoiceWakeLock.release();
diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
index e4b4c2d..13d90e3 100644
--- a/services/core/java/com/android/server/am/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
@@ -29,6 +29,7 @@
 import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
 
 import android.app.KeyguardManager;
+import android.app.admin.DevicePolicyManagerInternal;
 import android.content.IIntentSender;
 import android.content.Intent;
 import android.content.IntentSender;
@@ -40,6 +41,7 @@
 import android.os.UserManager;
 
 import com.android.internal.app.UnlaunchableAppActivity;
+import com.android.server.LocalServices;
 
 /**
  * A class that contains activity intercepting logic for {@link ActivityStarter#startActivityLocked}
@@ -133,8 +135,10 @@
                 (mAInfo.applicationInfo.flags & FLAG_SUSPENDED) == 0) {
             return false;
         }
-        mIntent = UnlaunchableAppActivity.createPackageSuspendedDialogIntent(mAInfo.packageName,
-                mUserId);
+        DevicePolicyManagerInternal devicePolicyManager = LocalServices.getService(
+                DevicePolicyManagerInternal.class);
+        mIntent = devicePolicyManager.createPackageSuspendedDialogIntent(
+                mAInfo.packageName, mUserId);
         mCallingPid = mRealCallingPid;
         mCallingUid = mRealCallingUid;
         mResolvedType = null;
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index e1d208e..e5342ce 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -78,8 +78,9 @@
 import android.util.Log;
 import android.util.Pair;
 import android.util.Slog;
-import android.util.SparseArray;
 
+import com.android.server.LocalServices;
+import com.android.server.job.JobSchedulerInternal;
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
 
@@ -113,9 +114,7 @@
  * All scheduled syncs will be passed on to JobScheduler as jobs
  * (See {@link #scheduleSyncOperationH(SyncOperation, long)}. This function schedules a job
  * with JobScheduler with appropriate delay and constraints (according to backoffs and extras).
- * A local copy of each scheduled SyncOperation object is stored in {@link mScheduledSyncs}.This
- * acts as a cache, so that we don't have to query JobScheduler every time we want to get a list of
- * all scheduled operations. The scheduleSyncOperationH function also assigns a unique jobId to each
+ * The scheduleSyncOperationH function also assigns a unique jobId to each
  * SyncOperation.
  *
  * Periodic Syncs:
@@ -129,14 +128,6 @@
  * run at a later time. Similarly, when a sync succeeds, backoff is cleared and all associated syncs
  * are rescheduled. A rescheduled sync will get a new jobId.
  *
- * State of {@link mScheduledSyncs}:
- * Every one-off SyncOperation will be put into this SparseArray when it is scheduled with
- * JobScheduler. And it will be removed once JobScheduler has started the job. Periodic syncs work
- * differently. They will always be present in mScheduledSyncs until the periodic sync is removed.
- * This is to ensure that if a request to add a periodic sync comes in, we add a new one only if a
- * duplicate doesn't exist. At every point of time, mScheduledSyncs and JobScheduler will show the
- * same pending syncs.
- *
  * @hide
  */
 public class SyncManager {
@@ -220,6 +211,7 @@
     private final NotificationManager mNotificationMgr;
     private final IBatteryStats mBatteryStats;
     private JobScheduler mJobScheduler;
+    private JobSchedulerInternal mJobSchedulerInternal;
     private SyncJobService mSyncJobService;
 
     private SyncStorageEngine mSyncStorageEngine;
@@ -235,14 +227,13 @@
 
     protected SyncAdaptersCache mSyncAdapters;
 
-    // Cache of all operations scheduled on the JobScheduler so that JobScheduler doesn't have
-    // to be queried often.
-    private SparseArray<SyncOperation> mScheduledSyncs = new SparseArray<SyncOperation>(32);
     private final Random mRand;
 
-    private boolean isJobIdInUseLockedH(int jobId) {
-        if (mScheduledSyncs.indexOfKey(jobId) >= 0) {
-            return true;
+    private boolean isJobIdInUseLockedH(int jobId, List<JobInfo> pendingJobs) {
+        for (JobInfo job: pendingJobs) {
+            if (job.getId() == jobId) {
+                return true;
+            }
         }
         for (ActiveSyncContext asc: mActiveSyncContexts) {
             if (asc.mSyncOperation.jobId == jobId) {
@@ -253,35 +244,25 @@
     }
 
     private int getUnusedJobIdH() {
-        synchronized (mScheduledSyncs) {
-            int newJobId;
-            do {
-                newJobId = MIN_SYNC_JOB_ID + mRand.nextInt(MAX_SYNC_JOB_ID - MIN_SYNC_JOB_ID);
-            } while (isJobIdInUseLockedH(newJobId));
-            return newJobId;
-        }
+        int newJobId;
+        do {
+            newJobId = MIN_SYNC_JOB_ID + mRand.nextInt(MAX_SYNC_JOB_ID - MIN_SYNC_JOB_ID);
+        } while (isJobIdInUseLockedH(newJobId,
+                mJobSchedulerInternal.getSystemScheduledPendingJobs()));
+        return newJobId;
     }
 
-    private void addSyncOperationToCache(SyncOperation op) {
-        synchronized (mScheduledSyncs) {
-            mScheduledSyncs.put(op.jobId, op);
-        }
-    }
-
-    private void removeSyncOperationFromCache(int jobId) {
-        synchronized (mScheduledSyncs) {
-            mScheduledSyncs.remove(jobId);
-        }
-    }
-
-    private List<SyncOperation> getAllPendingSyncsFromCache() {
-        synchronized (mScheduledSyncs) {
-            List<SyncOperation> pending = new ArrayList<SyncOperation>(mScheduledSyncs.size());
-            for (int i=0; i<mScheduledSyncs.size(); i++) {
-                pending.add(mScheduledSyncs.valueAt(i));
+    private List<SyncOperation> getAllPendingSyncs() {
+        verifyJobScheduler();
+        List<JobInfo> pendingJobs = mJobSchedulerInternal.getSystemScheduledPendingJobs();
+        List<SyncOperation> pendingSyncs = new ArrayList<SyncOperation>(pendingJobs.size());
+        for (JobInfo job: pendingJobs) {
+            SyncOperation op = SyncOperation.maybeCreateFromJobExtras(job.getExtras());
+            if (op != null) {
+                pendingSyncs.add(op);
             }
-            return pending;
         }
+        return pendingSyncs;
     }
 
     private final BroadcastReceiver mStorageIntentReceiver =
@@ -443,7 +424,7 @@
         mSyncHandler.postAtFrontOfQueue(new Runnable() {
             @Override
             public void run() {
-                List<SyncOperation> ops = getAllPendingSyncsFromCache();
+                List<SyncOperation> ops = getAllPendingSyncs();
                 Set<String> cleanedKeys = new HashSet<String>();
                 for (SyncOperation opx: ops) {
                     if (cleanedKeys.contains(opx.key)) {
@@ -455,7 +436,6 @@
                             continue;
                         }
                         if (opx.key.equals(opy.key)) {
-                            removeSyncOperationFromCache(opy.jobId);
                             mJobScheduler.cancel(opy.jobId);
                         }
                     }
@@ -473,18 +453,16 @@
         }
         mJobScheduler = (JobScheduler) mContext.getSystemService(
                 Context.JOB_SCHEDULER_SERVICE);
+        mJobSchedulerInternal = LocalServices.getService(JobSchedulerInternal.class);
         // Get all persisted syncs from JobScheduler
         List<JobInfo> pendingJobs = mJobScheduler.getAllPendingJobs();
-        synchronized (mScheduledSyncs) {
-            for (JobInfo job : pendingJobs) {
-                SyncOperation op = SyncOperation.maybeCreateFromJobExtras(job.getExtras());
-                if (op != null) {
-                    mScheduledSyncs.put(op.jobId, op);
-                    if (!op.isPeriodic) {
-                        // Set the pending status of this EndPoint to true. Pending icon is
-                        // shown on the settings activity.
-                        mSyncStorageEngine.markPending(op.target, true);
-                    }
+        for (JobInfo job : pendingJobs) {
+            SyncOperation op = SyncOperation.maybeCreateFromJobExtras(job.getExtras());
+            if (op != null) {
+                if (!op.isPeriodic) {
+                    // Set the pending status of this EndPoint to true. Pending icon is
+                    // shown on the settings activity.
+                    mSyncStorageEngine.markPending(op.target, true);
                 }
             }
         }
@@ -707,7 +685,7 @@
     }
 
     private void setAuthorityPendingState(EndPoint info) {
-        List<SyncOperation> ops = getAllPendingSyncsFromCache();
+        List<SyncOperation> ops = getAllPendingSyncs();
         for (SyncOperation op: ops) {
             if (!op.isPeriodic && op.target.matchesSpec(info)) {
                 getSyncStorageEngine().markPending(info, true);
@@ -927,11 +905,10 @@
 
     private void removeSyncsForAuthority(EndPoint info) {
         verifyJobScheduler();
-        List<SyncOperation> ops = getAllPendingSyncsFromCache();
+        List<SyncOperation> ops = getAllPendingSyncs();
         for (SyncOperation op: ops) {
             if (op.target.matchesSpec(info)) {
-                removeSyncOperationFromCache(op.jobId);
-                getJobScheduler().cancel(op.jobId);
+                 getJobScheduler().cancel(op.jobId);
             }
         }
     }
@@ -961,7 +938,7 @@
      * Get a list of periodic syncs corresponding to the given target.
      */
     public List<PeriodicSync> getPeriodicSyncs(EndPoint target) {
-        List<SyncOperation> ops = getAllPendingSyncsFromCache();
+        List<SyncOperation> ops = getAllPendingSyncs();
         List<PeriodicSync> periodicSyncs = new ArrayList<PeriodicSync>();
 
         for (SyncOperation op: ops) {
@@ -1145,12 +1122,11 @@
      * to current backoff and delayUntil values of this EndPoint.
      */
     private void rescheduleSyncs(EndPoint target) {
-        List<SyncOperation> ops = getAllPendingSyncsFromCache();
+        List<SyncOperation> ops = getAllPendingSyncs();
         int count = 0;
         for (SyncOperation op: ops) {
             if (!op.isPeriodic && op.target.matchesSpec(target)) {
                 count++;
-                removeSyncOperationFromCache(op.jobId);
                 getJobScheduler().cancel(op.jobId);
                 postScheduleSyncMessage(op);
             }
@@ -1251,7 +1227,7 @@
             int duplicatesCount = 0;
             long now = SystemClock.elapsedRealtime();
             syncOperation.expectedRuntime = now + minDelay;
-            List<SyncOperation> pending = getAllPendingSyncsFromCache();
+            List<SyncOperation> pending = getAllPendingSyncs();
             SyncOperation opWithLeastExpectedRuntime = syncOperation;
             for (SyncOperation op : pending) {
                 if (op.isPeriodic) {
@@ -1276,7 +1252,6 @@
                         if (isLoggable) {
                             Slog.v(TAG, "Cancelling duplicate sync " + op);
                         }
-                        removeSyncOperationFromCache(op.jobId);
                         getJobScheduler().cancel(op.jobId);
                     }
                 }
@@ -1294,7 +1269,6 @@
         if (syncOperation.jobId == SyncOperation.NO_JOB_ID) {
             syncOperation.jobId = getUnusedJobIdH();
         }
-        addSyncOperationToCache(syncOperation);
 
         if (isLoggable) {
             Slog.v(TAG, "scheduling sync operation " + syncOperation.toString());
@@ -1335,10 +1309,9 @@
      * have null account/provider info to specify all accounts/providers.
      */
     public void clearScheduledSyncOperations(SyncStorageEngine.EndPoint info) {
-        List<SyncOperation> ops = getAllPendingSyncsFromCache();
+        List<SyncOperation> ops = getAllPendingSyncs();
         for (SyncOperation op: ops) {
             if (!op.isPeriodic && op.target.matchesSpec(info)) {
-                removeSyncOperationFromCache(op.jobId);
                 getJobScheduler().cancel(op.jobId);
                 getSyncStorageEngine().markPending(op.target, false);
             }
@@ -1353,11 +1326,10 @@
      * @param extras extras bundle to uniquely identify sync.
      */
     public void cancelScheduledSyncOperation(SyncStorageEngine.EndPoint info, Bundle extras) {
-        List<SyncOperation> ops = getAllPendingSyncsFromCache();
+        List<SyncOperation> ops = getAllPendingSyncs();
         for (SyncOperation op: ops) {
             if (!op.isPeriodic && op.target.matchesSpec(info)
                     && syncExtrasEquals(extras, op.extras, false)) {
-                removeSyncOperationFromCache(op.jobId);
                 getJobScheduler().cancel(op.jobId);
             }
         }
@@ -1466,10 +1438,9 @@
 
         // Clean up the storage engine database
         mSyncStorageEngine.doDatabaseCleanup(new Account[0], userId);
-        List<SyncOperation> ops = getAllPendingSyncsFromCache();
+        List<SyncOperation> ops = getAllPendingSyncs();
         for (SyncOperation op: ops) {
             if (op.target.userId == userId) {
-                removeSyncOperationFromCache(op.jobId);
                 getJobScheduler().cancel(op.jobId);
             }
         }
@@ -1635,7 +1606,7 @@
 
     protected void dumpPendingSyncs(PrintWriter pw) {
         pw.println("Pending Syncs:");
-        List<SyncOperation> pendingSyncs = getAllPendingSyncsFromCache();
+        List<SyncOperation> pendingSyncs = getAllPendingSyncs();
         int count = 0;
         for (SyncOperation op: pendingSyncs) {
             if (!op.isPeriodic) {
@@ -1649,7 +1620,7 @@
 
     protected void dumpPeriodicSyncs(PrintWriter pw) {
         pw.println("Periodic Syncs:");
-        List<SyncOperation> pendingSyncs = getAllPendingSyncsFromCache();
+        List<SyncOperation> pendingSyncs = getAllPendingSyncs();
         int count = 0;
         for (SyncOperation op: pendingSyncs) {
             if (op.isPeriodic) {
@@ -2259,10 +2230,6 @@
         private boolean tryEnqueueMessageUntilReadyToRun(Message msg) {
             synchronized (this) {
                 if (!mBootCompleted || !mProvisioned) {
-                    if (msg.what == MESSAGE_START_SYNC) {
-                        SyncOperation op = (SyncOperation) msg.obj;
-                        addSyncOperationToCache(op);
-                    }
                     // Need to copy the message bc looper will recycle it.
                     Message m = Message.obtain(msg);
                     mUnreadyQueue.add(m);
@@ -2479,7 +2446,6 @@
             if (op.isPeriodic) {
                 scheduleSyncOperationH(op.createOneTimeSyncOperation(), delay);
             } else {
-                removeSyncOperationFromCache(op.jobId);
                 scheduleSyncOperationH(op, delay);
             }
         }
@@ -2489,7 +2455,6 @@
             if (op.isPeriodic) {
                 scheduleSyncOperationH(op.createOneTimeSyncOperation(), delay);
             } else {
-                removeSyncOperationFromCache(op.jobId);
                 scheduleSyncOperationH(op, delay);
             }
         }
@@ -2515,7 +2480,7 @@
             if (op.isPeriodic) {
                 // Don't allow this periodic to run if a previous instance failed and is currently
                 // scheduled according to some backoff criteria.
-                List<SyncOperation> ops = getAllPendingSyncsFromCache();
+                List<SyncOperation> ops = getAllPendingSyncs();
                 for (SyncOperation syncOperation: ops) {
                     if (syncOperation.sourcePeriodicId == op.jobId) {
                         mSyncJobService.callJobFinished(op.jobId, false);
@@ -2535,9 +2500,6 @@
                     deferSyncH(op, 0 /* No minimum delay */);
                     return;
                 }
-            } else {
-                // Remove SyncOperation entry from mScheduledSyncs cache for non periodic jobs.
-                removeSyncOperationFromCache(op.jobId);
             }
 
             // Check for conflicting syncs.
@@ -2616,10 +2578,9 @@
                 }
             }
 
-            List<SyncOperation> ops = getAllPendingSyncsFromCache();
+            List<SyncOperation> ops = getAllPendingSyncs();
             for (SyncOperation op: ops) {
                 if (!containsAccountAndUser(accounts, op.target.account, op.target.userId)) {
-                    removeSyncOperationFromCache(op.jobId);
                     getJobScheduler().cancel(op.jobId);
                 }
             }
@@ -2665,7 +2626,7 @@
                         + " flexMillis: " + flex
                         + " extras: " + extras.toString());
             }
-            List<SyncOperation> ops = getAllPendingSyncsFromCache();
+            List<SyncOperation> ops = getAllPendingSyncs();
             for (SyncOperation op: ops) {
                 if (op.isPeriodic && op.target.matchesSpec(target)
                         && syncExtrasEquals(op.extras, extras, true /* includeSyncSettings */)) {
@@ -2704,7 +2665,7 @@
          */
         private void removePeriodicSyncInternalH(SyncOperation syncOperation) {
             // Remove this periodic sync and all one-off syncs initiated by it.
-            List<SyncOperation> ops = getAllPendingSyncsFromCache();
+            List<SyncOperation> ops = getAllPendingSyncs();
             for (SyncOperation op: ops) {
                 if (op.sourcePeriodicId == syncOperation.jobId || op.jobId == syncOperation.jobId) {
                     ActiveSyncContext asc = findActiveSyncContextH(syncOperation.jobId);
@@ -2712,7 +2673,6 @@
                         mSyncJobService.callJobFinished(syncOperation.jobId, false);
                         runSyncFinishedOrCanceledH(null, asc);
                     }
-                    removeSyncOperationFromCache(op.jobId);
                     getJobScheduler().cancel(op.jobId);
                 }
             }
@@ -2720,7 +2680,7 @@
 
         private void removePeriodicSyncH(EndPoint target, Bundle extras) {
             verifyJobScheduler();
-            List<SyncOperation> ops = getAllPendingSyncsFromCache();
+            List<SyncOperation> ops = getAllPendingSyncs();
             for (SyncOperation op: ops) {
                 if (op.isPeriodic && op.target.matchesSpec(target)
                         && syncExtrasEquals(op.extras, extras, true /* includeSyncSettings */)) {
@@ -2896,7 +2856,7 @@
         private void reschedulePeriodicSyncH(SyncOperation syncOperation) {
             // Ensure that the periodic sync wasn't removed.
             SyncOperation periodicSync = null;
-            List<SyncOperation> ops = getAllPendingSyncsFromCache();
+            List<SyncOperation> ops = getAllPendingSyncs();
             for (SyncOperation op: ops) {
                 if (op.isPeriodic && syncOperation.matchesPeriodicOperation(op)) {
                     periodicSync = op;
diff --git a/services/core/java/com/android/server/job/JobSchedulerInternal.java b/services/core/java/com/android/server/job/JobSchedulerInternal.java
new file mode 100644
index 0000000..75170ec
--- /dev/null
+++ b/services/core/java/com/android/server/job/JobSchedulerInternal.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job;
+
+import android.app.job.JobInfo;
+
+import java.util.List;
+
+/**
+ * JobScheduler local system service interface.
+ * {@hide} Only for use within the system server.
+ */
+public interface JobSchedulerInternal {
+
+    /**
+     * Returns a list of pending jobs scheduled by the system service.
+     */
+    List<JobInfo> getSystemScheduledPendingJobs();
+}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index d2b77aa..cee46195 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -45,6 +45,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.Process;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
@@ -505,6 +506,7 @@
 
     @Override
     public void onStart() {
+        publishLocalService(JobSchedulerInternal.class, new LocalService());
         publishBinderService(Context.JOB_SCHEDULER_SERVICE, mJobSchedulerStub);
     }
 
@@ -1178,6 +1180,28 @@
         return -1;
     }
 
+    final class LocalService implements JobSchedulerInternal {
+
+        /**
+         * Returns a list of all pending jobs. A running job is not considered pending. Periodic
+         * jobs are always considered pending.
+         */
+        public List<JobInfo> getSystemScheduledPendingJobs() {
+            synchronized (mLock) {
+                final List<JobInfo> pendingJobs = new ArrayList<JobInfo>();
+                mJobs.forEachJob(Process.SYSTEM_UID, new JobStatusFunctor() {
+                    @Override
+                    public void process(JobStatus job) {
+                        if (job.getJob().isPeriodic() || !isCurrentlyActiveLocked(job)) {
+                            pendingJobs.add(job.getJob());
+                        }
+                    }
+                });
+                return pendingJobs;
+            }
+        }
+    }
+
     /**
      * Binder stub trampoline implementation
      */
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index 9837a56..55f37b8 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -210,6 +210,10 @@
         mJobSet.forEachJob(functor);
     }
 
+    public void forEachJob(int uid, JobStatusFunctor functor) {
+        mJobSet.forEachJob(uid, functor);
+    }
+
     public interface JobStatusFunctor {
         public void process(JobStatus jobStatus);
     }
@@ -870,5 +874,14 @@
                 }
             }
         }
+
+        public void forEachJob(int uid, JobStatusFunctor functor) {
+            ArraySet<JobStatus> jobs = mJobs.get(uid);
+            if (jobs != null) {
+                for (int i = jobs.size() - 1; i >= 0; i--) {
+                    functor.process(jobs.valueAt(i));
+                }
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index b7cd318..6cc0544 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -99,6 +99,15 @@
             mShortcutServiceInternal.addListener(mPackageMonitor);
         }
 
+        @VisibleForTesting
+        int injectBinderCallingUid() {
+            return getCallingUid();
+        }
+
+        private int getCallingUserId() {
+            return UserHandle.getUserId(injectBinderCallingUid());
+        }
+
         /*
          * @see android.content.pm.ILauncherApps#addOnAppsChangedListener(
          *          android.content.pm.IOnAppsChangedListener)
@@ -296,17 +305,21 @@
             }
         }
 
-        private void enforceShortcutPermission(UserHandle user) {
+        private void ensureShortcutPermission(@NonNull String callingPackage, UserHandle user) {
+            verifyCallingPackage(callingPackage);
             ensureInUserProfiles(user, "Cannot start activity for unrelated profile " + user);
-            // STOPSHIP Implement it
+
+            if (!mShortcutServiceInternal.hasShortcutHostPermission(callingPackage,
+                    user.getIdentifier())) {
+                throw new SecurityException("Caller can't access shortcut information");
+            }
         }
 
         @Override
         public ParceledListSlice getShortcuts(String callingPackage, long changedSince,
                 String packageName, ComponentName componentName, int flags, UserHandle user)
                 throws RemoteException {
-            enforceShortcutPermission(user);
-            verifyCallingPackage(callingPackage);
+            ensureShortcutPermission(callingPackage, user);
 
             return new ParceledListSlice<>(
                     mShortcutServiceInternal.getShortcuts(callingPackage, changedSince, packageName,
@@ -316,8 +329,7 @@
         @Override
         public ParceledListSlice getShortcutInfo(String callingPackage, String packageName,
                 List<String> ids, UserHandle user) throws RemoteException {
-            enforceShortcutPermission(user);
-            verifyCallingPackage(callingPackage);
+            ensureShortcutPermission(callingPackage, user);
 
             return new ParceledListSlice<>(
                     mShortcutServiceInternal.getShortcutInfo(callingPackage, packageName,
@@ -327,8 +339,7 @@
         @Override
         public void pinShortcuts(String callingPackage, String packageName, List<String> ids,
                 UserHandle user) throws RemoteException {
-            enforceShortcutPermission(user);
-            verifyCallingPackage(callingPackage);
+            ensureShortcutPermission(callingPackage, user);
 
             mShortcutServiceInternal.pinShortcuts(callingPackage, packageName,
                     ids, user.getIdentifier());
@@ -337,8 +348,7 @@
         @Override
         public int getShortcutIconResId(String callingPackage, ShortcutInfo shortcut,
                 UserHandle user) {
-            enforceShortcutPermission(user);
-            verifyCallingPackage(callingPackage);
+            ensureShortcutPermission(callingPackage, user);
 
             return mShortcutServiceInternal.getShortcutIconResId(callingPackage, shortcut,
                     user.getIdentifier());
@@ -347,19 +357,24 @@
         @Override
         public ParcelFileDescriptor getShortcutIconFd(String callingPackage, ShortcutInfo shortcut,
                 UserHandle user) {
-            enforceShortcutPermission(user);
-            verifyCallingPackage(callingPackage);
+            ensureShortcutPermission(callingPackage, user);
 
             return mShortcutServiceInternal.getShortcutIconFd(callingPackage, shortcut,
                     user.getIdentifier());
         }
 
         @Override
+        public boolean hasShortcutHostPermission(String callingPackage) throws RemoteException {
+            verifyCallingPackage(callingPackage);
+            return mShortcutServiceInternal.hasShortcutHostPermission(callingPackage,
+                    getCallingUserId());
+        }
+
+        @Override
         public boolean startShortcut(String callingPackage, String packageName, String shortcutId,
                 Rect sourceBounds, Bundle startActivityOptions, UserHandle user)
                 throws RemoteException {
-            enforceShortcutPermission(user);
-            verifyCallingPackage(callingPackage);
+            ensureShortcutPermission(callingPackage, user);
 
             final Intent intent = mShortcutServiceInternal.createShortcutIntent(callingPackage,
                     packageName, shortcutId, user.getIdentifier());
@@ -656,6 +671,9 @@
                     IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
                     UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i);
                     if (!isEnabledProfileOf(user, listeningUser, "onShortcutChanged")) continue;
+
+                    // STOPSHIP Skip if the receiver doesn't have the permission.
+
                     try {
                         listener.onShortcutChanged(user, packageName,
                                 new ParceledListSlice<>(shortcuts));
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 9a1ecd7..b624087 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -16456,14 +16456,17 @@
 
     @Override
     public ComponentName getHomeActivities(List<ResolveInfo> allHomeCandidates) {
+        return getHomeActivitiesAsUser(allHomeCandidates, UserHandle.getCallingUserId());
+    }
+
+    ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates,
+            int userId) {
         Intent intent = new Intent(Intent.ACTION_MAIN);
         intent.addCategory(Intent.CATEGORY_HOME);
-
-        final int callingUserId = UserHandle.getCallingUserId();
         List<ResolveInfo> list = queryIntentActivitiesInternal(intent, null,
-                PackageManager.GET_META_DATA, callingUserId);
+                PackageManager.GET_META_DATA, userId);
         ResolveInfo preferred = findPreferredActivity(intent, null, 0, list, 0,
-                true, false, false, callingUserId);
+                true, false, false, userId);
 
         allHomeCandidates.clear();
         if (list != null) {
@@ -19252,6 +19255,12 @@
         public ApplicationInfo getApplicationInfo(String packageName, int userId) {
             return PackageManagerService.this.getApplicationInfo(packageName, 0 /*flags*/, userId);
         }
+
+        @Override
+        public ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates,
+                int userId) {
+            return PackageManagerService.this.getHomeActivitiesAsUser(allHomeCandidates, userId);
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 0b0f7ab..3791eb0 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -28,7 +28,9 @@
 import android.content.pm.LauncherApps.ShortcutQuery;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.ParceledListSlice;
+import android.content.pm.ResolveInfo;
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutServiceInternal;
 import android.content.pm.ShortcutServiceInternal.ShortcutChangeListener;
@@ -71,6 +73,7 @@
 import com.android.server.SystemService;
 
 import libcore.io.IoUtils;
+import libcore.util.Objects;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -88,7 +91,6 @@
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 import java.util.function.Predicate;
 
 /**
@@ -156,6 +158,7 @@
     static final String TAG_INTENT_EXTRAS = "intent-extras";
     static final String TAG_EXTRAS = "extras";
     static final String TAG_SHORTCUT = "shortcut";
+    static final String TAG_LAUNCHER = "launcher";
 
     static final String ATTR_VALUE = "value";
     static final String ATTR_NAME = "name";
@@ -251,10 +254,13 @@
     private CompressFormat mIconPersistFormat;
     private int mIconPersistQuality;
 
+    private final PackageManagerInternal mPackageManagerInternal;
+
     public ShortcutService(Context context) {
         mContext = Preconditions.checkNotNull(context);
         LocalServices.addService(ShortcutServiceInternal.class, new LocalService());
         mHandler = new Handler(BackgroundThread.get().getLooper());
+        mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
     }
 
     /**
@@ -460,6 +466,11 @@
         writeTagValue(out, tag, Long.toString(value));
     }
 
+    static void writeTagValue(XmlSerializer out, String tag, ComponentName name) throws IOException {
+        if (name == null) return;
+        writeTagValue(out, tag, name.flattenToString());
+    }
+
     static void writeTagExtra(XmlSerializer out, String tag, PersistableBundle bundle)
             throws IOException, XmlPullParserException {
         if (bundle == null) return;
@@ -658,7 +669,7 @@
     }
 
     // TODO Actually make it async.
-    private void scheduleSaveUser(@UserIdInt int userId) {
+    void scheduleSaveUser(@UserIdInt int userId) {
         synchronized (mLock) {
             saveUserLocked(userId);
         }
@@ -676,6 +687,10 @@
         return mRawLastResetTime + mResetInterval;
     }
 
+    static boolean isClockValid(long time) {
+        return time >= 1420070400; // Thu, 01 Jan 2015 00:00:00 GMT
+    }
+
     /**
      * Update the last reset time.
      */
@@ -690,8 +705,10 @@
             mRawLastResetTime = now;
         } else if (now < mRawLastResetTime) {
             // Clock rewound.
-            // TODO Randomize??
-            mRawLastResetTime = now;
+            if (isClockValid(now)) {
+                // TODO Randomize??
+                mRawLastResetTime = now;
+            }
         } else {
             // TODO Do it properly.
             while ((mRawLastResetTime + mResetInterval) <= now) {
@@ -1277,18 +1294,98 @@
     public void resetThrottling() {
         enforceSystemOrShell();
 
-        resetThrottlingInner();
+        resetThrottlingInner(getCallingUserId());
     }
 
-    @VisibleForTesting
-    void resetThrottlingInner() {
+    void resetThrottlingInner(@UserIdInt int userId) {
         synchronized (mLock) {
-            mRawLastResetTime = injectCurrentTimeMillis();
+            getUserShortcutsLocked(userId).resetThrottling();
         }
-        scheduleSaveBaseState();
+        scheduleSaveUser(userId);
         Slog.i(TAG, "ShortcutManager: throttling counter reset");
     }
 
+    // We override this method in unit tests to do a simpler check.
+    boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId) {
+        return hasShortcutHostPermissionInner(callingPackage, userId);
+    }
+
+    // This method is extracted so we can directly call this method from unit tests,
+    // even when hasShortcutPermission() is overridden.
+    @VisibleForTesting
+    boolean hasShortcutHostPermissionInner(@NonNull String callingPackage, int userId) {
+        synchronized (mLock) {
+            long start = 0;
+            if (DEBUG) {
+                start = System.currentTimeMillis();
+            }
+
+            final UserShortcuts user = getUserShortcutsLocked(userId);
+
+            final List<ResolveInfo> allHomeCandidates = new ArrayList<>();
+
+            // Default launcher from package manager.
+            final ComponentName defaultLauncher = injectPackageManagerInternal()
+                    .getHomeActivitiesAsUser(allHomeCandidates, userId);
+
+            ComponentName detected;
+            if (defaultLauncher != null) {
+                detected = defaultLauncher;
+                if (DEBUG) {
+                    Slog.v(TAG, "Default launcher from PM: " + detected);
+                }
+            } else {
+                detected = user.getLauncherComponent();
+
+                // TODO: Make sure it's still enabled.
+                if (DEBUG) {
+                    Slog.v(TAG, "Cached launcher: " + detected);
+                }
+            }
+
+            if (detected == null) {
+                // If we reach here, that means it's the first check since the user was created,
+                // and there's already multiple launchers and there's no default set.
+                // Find the system one with the highest priority.
+                // (We need to check the priority too because of FallbackHome in Settings.)
+                // If there's no system launcher yet, then no one can access shortcuts, until
+                // the user explicitly
+                final int size = allHomeCandidates.size();
+
+                int lastPriority = Integer.MIN_VALUE;
+                for (int i = 0; i < size; i++) {
+                    final ResolveInfo ri = allHomeCandidates.get(i);
+                    if (!ri.activityInfo.applicationInfo.isSystemApp()) {
+                        continue;
+                    }
+                    if (DEBUG) {
+                        Slog.d(TAG, String.format("hasShortcutPermissionInner: pkg=%s prio=%d",
+                                ri.activityInfo.getComponentName(), ri.priority));
+                    }
+                    if (ri.priority < lastPriority) {
+                        continue;
+                    }
+                    detected = ri.activityInfo.getComponentName();
+                    lastPriority = ri.priority;
+                }
+            }
+            if (DEBUG) {
+                long end = System.currentTimeMillis();
+                Slog.v(TAG, String.format("hasShortcutPermission took %d ms", end - start));
+            }
+            if (detected != null) {
+                if (DEBUG) {
+                    Slog.v(TAG, "Detected launcher: " + detected);
+                }
+                user.setLauncherComponent(this, detected);
+                return detected.getPackageName().equals(callingPackage);
+            } else {
+                // Default launcher not found.
+                return false;
+            }
+        }
+    }
+
     /**
      * Entry point from {@link LauncherApps}.
      */
@@ -1434,6 +1531,11 @@
                 }
             }
         }
+
+        @Override
+        public boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId) {
+            return ShortcutService.this.hasShortcutHostPermission(callingPackage, userId);
+        }
     }
 
     // === Dump ===
@@ -1512,37 +1614,74 @@
         (new MyShellCommand()).exec(this, in, out, err, args, resultReceiver);
     }
 
+    static class CommandException extends Exception {
+        public CommandException(String message) {
+            super(message);
+        }
+    }
+
     /**
      * Handle "adb shell cmd".
      */
     private class MyShellCommand extends ShellCommand {
+
+        private int mUserId = UserHandle.USER_SYSTEM;
+
+        private void parseOptions(boolean takeUser)
+                throws CommandException {
+            String opt;
+            while ((opt = getNextOption()) != null) {
+                switch (opt) {
+                    case "--user":
+                        if (takeUser) {
+                            mUserId = UserHandle.parseUserArg(getNextArgRequired());
+                            break;
+                        }
+                        // fallthrough
+                    default:
+                        throw new CommandException("Unknown option: " + opt);
+                }
+            }
+        }
+
         @Override
         public int onCommand(String cmd) {
             if (cmd == null) {
                 return handleDefaultCommands(cmd);
             }
             final PrintWriter pw = getOutPrintWriter();
-            int ret = 1;
-            switch (cmd) {
-                case "reset-package-throttling":
-                    ret = handleResetPackageThrottling();
-                    break;
-                case "reset-throttling":
-                    ret = handleResetThrottling();
-                    break;
-                case "override-config":
-                    ret = handleOverrideConfig();
-                    break;
-                case "reset-config":
-                    ret = handleResetConfig();
-                    break;
-                default:
-                    return handleDefaultCommands(cmd);
+            try {
+                switch (cmd) {
+                    case "reset-package-throttling":
+                        handleResetPackageThrottling();
+                        break;
+                    case "reset-throttling":
+                        handleResetThrottling();
+                        break;
+                    case "override-config":
+                        handleOverrideConfig();
+                        break;
+                    case "reset-config":
+                        handleResetConfig();
+                        break;
+                    case "clear-default-launcher":
+                        handleClearDefaultLauncher();
+                        break;
+                    case "get-default-launcher":
+                        handleGetDefaultLauncher();
+                        break;
+                    case "refresh-default-launcher":
+                        handleRefreshDefaultLauncher();
+                        break;
+                    default:
+                        return handleDefaultCommands(cmd);
+                }
+            } catch (CommandException e) {
+                pw.println("Error: " + e.getMessage());
+                return 1;
             }
-            if (ret == 0) {
-                pw.println("Success");
-            }
-            return ret;
+            pw.println("Success");
+            return 0;
         }
 
         @Override
@@ -1562,56 +1701,85 @@
             pw.println("cmd shortcut reset-config");
             pw.println("    Reset the configuration set with \"update-config\"");
             pw.println();
+            pw.println("cmd shortcut clear-default-launcher [--user USER_ID]");
+            pw.println("    Clear the cached default launcher");
+            pw.println();
+            pw.println("cmd shortcut get-default-launcher [--user USER_ID]");
+            pw.println("    Show the cached default launcher");
+            pw.println();
+            pw.println("cmd shortcut refresh-default-launcher [--user USER_ID]");
+            pw.println("    Refresh the cached default launcher");
+            pw.println();
         }
 
-        private int handleResetThrottling() {
-            resetThrottling();
+        private int handleResetThrottling() throws CommandException {
+            parseOptions(/* takeUser =*/ true);
+
+            resetThrottlingInner(mUserId);
             return 0;
         }
 
-        private int handleResetPackageThrottling() {
-            final PrintWriter pw = getOutPrintWriter();
+        private void handleResetPackageThrottling() throws CommandException {
+            parseOptions(/* takeUser =*/ true);
 
-            int userId = UserHandle.USER_SYSTEM;
-            String opt;
-            while ((opt = getNextOption()) != null) {
-                switch (opt) {
-                    case "--user":
-                        userId = UserHandle.parseUserArg(getNextArgRequired());
-                        break;
-                    default:
-                        pw.println("Error: Unknown option: " + opt);
-                        return 1;
-                }
-            }
             final String packageName = getNextArgRequired();
 
             synchronized (mLock) {
-                getPackageShortcutsLocked(packageName, userId).resetRateLimitingForCommandLine();
-                saveUserLocked(userId);
+                getPackageShortcutsLocked(packageName, mUserId).resetRateLimitingForCommandLine();
+                saveUserLocked(mUserId);
             }
-
-            return 0;
         }
 
-        private int handleOverrideConfig() {
-            final PrintWriter pw = getOutPrintWriter();
+        private void handleOverrideConfig() throws CommandException {
             final String config = getNextArgRequired();
 
             synchronized (mLock) {
                 if (!updateConfigurationLocked(config)) {
-                    pw.println("override-config failed.  See logcat for details.");
-                    return 1;
+                    throw new CommandException("override-config failed.  See logcat for details.");
                 }
             }
-            return 0;
         }
 
-        private int handleResetConfig() {
+        private void handleResetConfig() {
             synchronized (mLock) {
                 loadConfigurationLocked();
             }
-            return 0;
+        }
+
+        private void clearLauncher() {
+            synchronized (mLock) {
+                getUserShortcutsLocked(mUserId).setLauncherComponent(
+                        ShortcutService.this, null);
+            }
+        }
+
+        private void showLauncher() {
+            synchronized (mLock) {
+                // This ensures to set the cached launcher.  Package name doesn't matter.
+                hasShortcutHostPermissionInner("-", mUserId);
+
+                getOutPrintWriter().println("Launcher: "
+                        + getUserShortcutsLocked(mUserId).getLauncherComponent());
+            }
+        }
+
+        private void handleClearDefaultLauncher() throws CommandException {
+            parseOptions(/* takeUser =*/ true);
+
+            clearLauncher();
+        }
+
+        private void handleGetDefaultLauncher() throws CommandException {
+            parseOptions(/* takeUser =*/ true);
+
+            showLauncher();
+        }
+
+        private void handleRefreshDefaultLauncher() throws CommandException {
+            parseOptions(/* takeUser =*/ true);
+
+            clearLauncher();
+            showLauncher();
         }
     }
 
@@ -1627,6 +1795,10 @@
         return getCallingUid();
     }
 
+    final int getCallingUserId() {
+        return UserHandle.getUserId(injectBinderCallingUid());
+    }
+
     File injectSystemDataPath() {
         return Environment.getDataSystemDirectory();
     }
@@ -1640,6 +1812,10 @@
         return ActivityManager.isLowRamDeviceStatic();
     }
 
+    PackageManagerInternal injectPackageManagerInternal() {
+        return mPackageManagerInternal;
+    }
+
     File getUserBitmapFilePath(@UserIdInt int userId) {
         return new File(injectUserDataPath(userId), DIRECTORY_BITMAPS);
     }
@@ -1687,6 +1863,9 @@
     }
 }
 
+/**
+ * Per-user information.
+ */
 class UserShortcuts {
     private static final String TAG = ShortcutService.TAG;
 
@@ -1695,6 +1874,8 @@
 
     private final ArrayMap<String, PackageShortcuts> mPackages = new ArrayMap<>();
 
+    private ComponentName mLauncherComponent;
+
     public UserShortcuts(int userId) {
         mUserId = userId;
     }
@@ -1706,11 +1887,11 @@
     public void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
         out.startTag(null, ShortcutService.TAG_USER);
 
-        for (int i = 0; i < mPackages.size(); i++) {
-            final String packageName = mPackages.keyAt(i);
-            final PackageShortcuts packageShortcuts = mPackages.valueAt(i);
+        ShortcutService.writeTagValue(out, ShortcutService.TAG_LAUNCHER,
+                mLauncherComponent);
 
-            packageShortcuts.saveToXml(out);
+        for (int i = 0; i < mPackages.size(); i++) {
+            mPackages.valueAt(i).saveToXml(out);
         }
 
         out.endTag(null, ShortcutService.TAG_USER);
@@ -1730,6 +1911,10 @@
             final int depth = parser.getDepth();
             final String tag = parser.getName();
             switch (tag) {
+                case ShortcutService.TAG_LAUNCHER:
+                    ret.mLauncherComponent = ShortcutService.parseComponentNameAttribute(
+                            parser, ShortcutService.ATTR_VALUE);
+                    continue;
                 case ShortcutService.TAG_PACKAGE:
                     final PackageShortcuts shortcuts = PackageShortcuts.loadFromXml(parser, userId);
 
@@ -1742,12 +1927,36 @@
         return ret;
     }
 
+    public ComponentName getLauncherComponent() {
+        return mLauncherComponent;
+    }
+
+    public void setLauncherComponent(ShortcutService s, ComponentName launcherComponent) {
+        if (Objects.equal(mLauncherComponent, launcherComponent)) {
+            return;
+        }
+        mLauncherComponent = launcherComponent;
+        s.scheduleSaveUser(mUserId);
+    }
+
+    public void resetThrottling() {
+        for (int i = mPackages.size() - 1; i >= 0; i--) {
+            mPackages.valueAt(i).resetThrottling();
+        }
+    }
+
     public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) {
-        pw.print("  ");
+        pw.print(prefix);
         pw.print("User: ");
         pw.print(mUserId);
         pw.println();
 
+        pw.print(prefix);
+        pw.print("  ");
+        pw.print("Default launcher: ");
+        pw.print(mLauncherComponent);
+        pw.println();
+
         for (int i = 0; i < mPackages.size(); i++) {
             mPackages.valueAt(i).dump(s, pw, prefix + "  ");
         }
@@ -1791,7 +2000,6 @@
         mPackageName = packageName;
     }
 
-    @GuardedBy("mLock")
     @Nullable
     public ShortcutInfo findShortcutById(String id) {
         return mShortcuts.get(id);
@@ -1818,7 +2026,6 @@
      *
      * It checks the max number of dynamic shortcuts.
      */
-    @GuardedBy("mLock")
     public void updateShortcutWithCapping(@NonNull ShortcutService s,
             @NonNull ShortcutInfo newShortcut) {
         final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());
@@ -1868,7 +2075,6 @@
         }
     }
 
-    @GuardedBy("mLock")
     public void deleteAllDynamicShortcuts(@NonNull ShortcutService s) {
         for (int i = mShortcuts.size() - 1; i >= 0; i--) {
             mShortcuts.valueAt(i).clearFlags(ShortcutInfo.FLAG_DYNAMIC);
@@ -1877,7 +2083,6 @@
         mDynamicShortcutCount = 0;
     }
 
-    @GuardedBy("mLock")
     public void deleteDynamicWithId(@NonNull ShortcutService s, @NonNull String shortcutId) {
         final ShortcutInfo oldShortcut = mShortcuts.get(shortcutId);
 
@@ -1894,7 +2099,6 @@
         }
     }
 
-    @GuardedBy("mLock")
     public void replacePinned(@NonNull ShortcutService s, String launcherPackage,
             List<String> shortcutIds) {
 
@@ -1919,12 +2123,11 @@
     /**
      * Number of calls that the caller has made, since the last reset.
      */
-    @GuardedBy("mLock")
     public int getApiCallCount(@NonNull ShortcutService s) {
         final long last = s.getLastResetTimeLocked();
 
         final long now = s.injectCurrentTimeMillis();
-        if (mLastResetTime > now) {
+        if (ShortcutService.isClockValid(now) && mLastResetTime > now) {
             // Clock rewound. // TODO Test it
             mLastResetTime = now;
         }
@@ -1941,7 +2144,6 @@
      * If the caller app hasn't been throttled yet, increment {@link #mApiCallCount}
      * and return true.  Otherwise just return false.
      */
-    @GuardedBy("mLock")
     public boolean tryApiCall(@NonNull ShortcutService s) {
         if (getApiCallCount(s) >= s.mMaxDailyUpdates) {
             return false;
@@ -1950,7 +2152,6 @@
         return true;
     }
 
-    @GuardedBy("mLock")
     public void resetRateLimitingForCommandLine() {
         mApiCallCount = 0;
         mLastResetTime = 0;
@@ -1959,7 +2160,6 @@
     /**
      * Find all shortcuts that match {@code query}.
      */
-    @GuardedBy("mLock")
     public void findAll(@NonNull List<ShortcutInfo> result,
             @Nullable Predicate<ShortcutInfo> query, int cloneFlag) {
         for (int i = 0; i < mShortcuts.size(); i++) {
@@ -1970,6 +2170,10 @@
         }
     }
 
+    public void resetThrottling() {
+        mApiCallCount = 0;
+    }
+
     public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) {
         pw.print(prefix);
         pw.print("Package: ");
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index ffdd89a..3cf9590 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -730,13 +730,27 @@
     public void systemRunning() {
         if (DEBUG) Slog.v(TAG, "systemReady");
         WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM);
-        // No crop file? Make sure we've finished the processing sequence if necessary
-        if (!wallpaper.cropExists()) {
-            generateCrop(wallpaper);
-        }
-        // Still nothing?  Fall back to default.
-        if (!wallpaper.cropExists()) {
-            clearWallpaperLocked(false, FLAG_SET_SYSTEM, UserHandle.USER_SYSTEM, null);
+        // If we think we're going to be using the system image wallpaper imagery, make
+        // sure we have something to render
+        if (mImageWallpaper.equals(wallpaper.nextWallpaperComponent)) {
+            // No crop file? Make sure we've finished the processing sequence if necessary
+            if (!wallpaper.cropExists()) {
+                if (DEBUG) {
+                    Slog.i(TAG, "No crop; regenerating from source");
+                }
+                generateCrop(wallpaper);
+            }
+            // Still nothing?  Fall back to default.
+            if (!wallpaper.cropExists()) {
+                if (DEBUG) {
+                    Slog.i(TAG, "Unable to regenerate crop; resetting");
+                }
+                clearWallpaperLocked(false, FLAG_SET_SYSTEM, UserHandle.USER_SYSTEM, null);
+            }
+        } else {
+            if (DEBUG) {
+                Slog.i(TAG, "Nondefault wallpaper component; gracefully ignoring");
+            }
         }
         switchWallpaper(wallpaper, null);
         wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index 55b3c7b..3a5dec9 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -171,17 +171,21 @@
         transformation.setAlpha(mAppToken.isVisible() ? 1 : 0);
     }
 
+    void setNullAnimation() {
+        animation = null;
+        usingTransferredAnimation = false;
+    }
+
     public void clearAnimation() {
         if (animation != null) {
-            animation = null;
             animating = true;
         }
         clearThumbnail();
+        setNullAnimation();
         if (mAppToken.deferClearAllDrawn) {
             mAppToken.allDrawn = false;
             mAppToken.deferClearAllDrawn = false;
         }
-        usingTransferredAnimation = false;
     }
 
     public boolean isAnimating() {
@@ -202,9 +206,9 @@
 
         if (animation != null) {
             toAppAnimator.animation = animation;
-            animation = null;
             toAppAnimator.animating = animating;
             toAppAnimator.animLayerAdjustment = animLayerAdjustment;
+            setNullAnimation();
             animLayerAdjustment = 0;
             toAppAnimator.updateLayers();
             updateLayers();
@@ -311,7 +315,7 @@
                 if (mProlongAnimation == PROLONG_ANIMATION_AT_END) {
                     hasMoreFrames = true;
                 } else {
-                    animation = null;
+                    setNullAnimation();
                     clearThumbnail();
                     if (DEBUG_ANIM) Slog.v(TAG, "Finished animation in " + mAppToken + " @ "
                             + currentTime);
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 9795c93..4ec297e 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -322,23 +322,6 @@
         }
     }
 
-    void setWindowsExiting(boolean exiting) {
-        for (int i = allAppWindows.size() - 1; i >= 0; i--) {
-            WindowState win = allAppWindows.get(i);
-            // If the app already requested to remove its window, we don't modify
-            // its exiting state. Otherwise the stale window won't get removed on
-            // exit and could cause focus to be given to the wrong window.
-            if (!(win.mRemoveOnExit && win.mAnimatingExit)) {
-                win.mAnimatingExit = exiting;
-            }
-            // If we're no longer exiting, remove the window from destroying list
-            if (!win.mAnimatingExit && win.mDestroying) {
-                win.mDestroying = false;
-                service.mDestroySurface.remove(win);
-            }
-        }
-    }
-
     // Here we destroy surfaces which have been marked as eligible by the animator, taking care
     // to ensure the client has finished with them. If the client could still be using them
     // we will skip destruction and try again when the client has stopped.
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index e42658e..b702180 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -24,6 +24,7 @@
 
 import android.app.ActivityManagerNative;
 import android.graphics.Rect;
+import android.os.Debug;
 import android.os.RemoteException;
 import android.util.Log;
 import android.util.Slog;
@@ -36,6 +37,7 @@
 import com.android.server.input.InputManagerService;
 import com.android.server.input.InputWindowHandle;
 
+import java.io.PrintWriter;
 import java.util.Arrays;
 
 final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
@@ -47,6 +49,9 @@
     // When true, prevents input dispatch from proceeding until set to false again.
     private boolean mInputDispatchFrozen;
 
+    // The reason the input is currently frozen or null if the input isn't frozen.
+    private String mInputFreezeReason = null;
+
     // When true, input dispatch proceeds normally.  Otherwise all events are dropped.
     // Initially false, so that input does not get dispatched until boot is finished at
     // which point the ActivityManager will enable dispatching.
@@ -474,12 +479,16 @@
     }
 
     public void freezeInputDispatchingLw() {
-        if (! mInputDispatchFrozen) {
+        if (!mInputDispatchFrozen) {
             if (DEBUG_INPUT) {
                 Slog.v(TAG_WM, "Freezing input dispatching");
             }
 
             mInputDispatchFrozen = true;
+
+            if (DEBUG_INPUT || true) {
+                mInputFreezeReason = Debug.getCallers(6);
+            }
             updateInputDispatchModeLw();
         }
     }
@@ -491,6 +500,7 @@
             }
 
             mInputDispatchFrozen = false;
+            mInputFreezeReason = null;
             updateInputDispatchModeLw();
         }
     }
@@ -509,4 +519,10 @@
     private void updateInputDispatchModeLw() {
         mService.mInputManager.setInputDispatchMode(mInputDispatchEnabled, mInputDispatchFrozen);
     }
+
+    void dump(PrintWriter pw, String prefix) {
+        if (mInputFreezeReason != null) {
+            pw.println(prefix + "mInputFreezeReason=" + mInputFreezeReason);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 2e424d0..e44b0f3 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -508,10 +508,11 @@
 
             replacing = replacing || w.mWillReplaceWindow;
 
-            // If the app is executing an animation because the keyguard is going away,
-            // keep the wallpaper during the animation so it doesn't flicker out.
+            // If the app is executing an animation because the keyguard is going away (and the
+            // keyguard was showing the wallpaper) keep the wallpaper during the animation so it
+            // doesn't flicker out.
             final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0
-                    || (w.mAppToken != null && w.mWinAnimator.mKeyguardGoingAwayAnimation);
+                    || (w.mAppToken != null && w.mWinAnimator.mKeyguardGoingAwayWithWallpaper);
             if (hasWallpaper && w.isOnScreen() && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
                 if (DEBUG_WALLPAPER) Slog.v(TAG, "Found wallpaper target: #" + i + "=" + w);
                 result.setWallpaperTarget(w, i);
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 4698e4e..f243761 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -22,6 +22,9 @@
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
+import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
+import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
+import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEYGUARD;
@@ -98,8 +101,7 @@
     boolean mInitialized = false;
 
     boolean mKeyguardGoingAway;
-    boolean mKeyguardGoingAwayToNotificationShade;
-    boolean mKeyguardGoingAwayDisableWindowAnimations;
+    int mKeyguardGoingAwayFlags;
 
     /** Use one animation for all entering activities after keyguard is dismissed. */
     Animation mPostKeyguardExitAnimation;
@@ -243,6 +245,13 @@
 
         final WindowList windows = mService.getWindowListLocked(displayId);
 
+        final boolean keyguardGoingAwayToShade =
+                (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0;
+        final boolean keyguardGoingAwayNoAnimation =
+                (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS) != 0;
+        final boolean keyguardGoingAwayWithWallpaper =
+                (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER) != 0;
+
         if (mKeyguardGoingAway) {
             for (int i = windows.size() - 1; i >= 0; i--) {
                 WindowState win = windows.get(i);
@@ -261,6 +270,8 @@
                         winAnimator.mAnimationIsEntrance = false;
                         winAnimator.mAnimationStartTime = -1;
                         winAnimator.mKeyguardGoingAwayAnimation = true;
+                        winAnimator.mKeyguardGoingAwayWithWallpaper
+                                = keyguardGoingAwayWithWallpaper;
                     }
                 } else {
                     if (DEBUG_KEYGUARD) Slog.d(TAG,
@@ -392,10 +403,13 @@
                             if (DEBUG_KEYGUARD) Slog.v(TAG,
                                     "Applying existing Keyguard exit animation to new window: win="
                                             + win);
-                            Animation a = mPolicy.createForceHideEnterAnimation(
-                                    false, mKeyguardGoingAwayToNotificationShade);
+
+                            Animation a = mPolicy.createForceHideEnterAnimation(false,
+                                    keyguardGoingAwayToShade);
                             winAnimator.setAnimation(a, mPostKeyguardExitAnimation.getStartTime());
                             winAnimator.mKeyguardGoingAwayAnimation = true;
+                            winAnimator.mKeyguardGoingAwayWithWallpaper
+                                    = keyguardGoingAwayWithWallpaper;
                         }
                         final WindowState currentFocus = mService.mCurrentFocus;
                         if (currentFocus == null || currentFocus.mLayer < win.mLayer) {
@@ -463,18 +477,20 @@
         // being force-hidden, apply the appropriate animation to them if animations are not
         // disabled.
         if (unForceHiding != null) {
-            if (!mKeyguardGoingAwayDisableWindowAnimations) {
+            if (!keyguardGoingAwayNoAnimation) {
                 boolean first = true;
                 for (int i=unForceHiding.size()-1; i>=0; i--) {
                     final WindowStateAnimator winAnimator = unForceHiding.get(i);
                     Animation a = mPolicy.createForceHideEnterAnimation(
                             wallpaperInUnForceHiding && !startingInUnForceHiding,
-                            mKeyguardGoingAwayToNotificationShade);
+                            keyguardGoingAwayToShade);
                     if (a != null) {
                         if (DEBUG_KEYGUARD) Slog.v(TAG,
                                 "Starting keyguard exit animation on window " + winAnimator.mWin);
                         winAnimator.setAnimation(a);
                         winAnimator.mKeyguardGoingAwayAnimation = true;
+                        winAnimator.mKeyguardGoingAwayWithWallpaper
+                                = keyguardGoingAwayWithWallpaper;
                         if (first) {
                             mPostKeyguardExitAnimation = a;
                             mPostKeyguardExitAnimation.setStartTime(mCurrentTime);
@@ -489,11 +505,10 @@
 
 
             // Wallpaper is going away in un-force-hide motion, animate it as well.
-            if (!wallpaperInUnForceHiding && wallpaper != null
-                    && !mKeyguardGoingAwayDisableWindowAnimations) {
+            if (!wallpaperInUnForceHiding && wallpaper != null && !keyguardGoingAwayNoAnimation) {
                 if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: wallpaper animating away");
                 Animation a = mPolicy.createForceHideWallpaperExitAnimation(
-                        mKeyguardGoingAwayToNotificationShade);
+                        keyguardGoingAwayToShade);
                 if (a != null) {
                     wallpaper.mWinAnimator.setAnimation(a);
                 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 1ae4394..e60e163 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2826,10 +2826,12 @@
         if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) {
             focusMayChange = isDefaultDisplay;
             win.mAnimatingExit = true;
+            win.mWinAnimator.mAnimating = true;
         } else if (win.mWinAnimator.isAnimating()) {
             // Currently in a hide animation... turn this into
             // an exit.
             win.mAnimatingExit = true;
+            win.mWinAnimator.mAnimating = true;
         } else if (mWallpaperControllerLocked.isWallpaperTarget(win)) {
             // If the wallpaper is currently behind this
             // window, we need to change both of them inside
@@ -4086,7 +4088,7 @@
 
             if (transit != AppTransition.TRANSIT_UNSET) {
                 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
-                    wtoken.mAppAnimator.animation = null;
+                    wtoken.mAppAnimator.setNullAnimation();
                 }
                 if (applyAnimationLocked(wtoken, lp, transit, visible, isVoiceInteraction)) {
                     delayed = runningAppAnimation = true;
@@ -4196,7 +4198,7 @@
     void updateTokenInPlaceLocked(AppWindowToken wtoken, int transit) {
         if (transit != AppTransition.TRANSIT_UNSET) {
             if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
-                wtoken.mAppAnimator.animation = null;
+                wtoken.mAppAnimator.setNullAnimation();
             }
             applyAnimationLocked(wtoken, null, transit, false, false);
         }
@@ -4256,7 +4258,6 @@
                 if (DEBUG_ADD_REMOVE) Slog.v(
                         TAG_WM, "No longer Stopped: " + wtoken);
                 wtoken.mAppStopped = false;
-                wtoken.setWindowsExiting(false);
                 mOpeningApps.add(wtoken);
                 wtoken.startingMoved = false;
 
@@ -4288,6 +4289,11 @@
                 // animation is going on (in this case an application transition). If the animation
                 // was transferred from another application/animator, no dummy animator should be
                 // created since an animation is already in progress.
+                if (wtoken.mAppAnimator.usingTransferredAnimation
+                        && wtoken.mAppAnimator.animation == null) {
+                    Slog.wtf(TAG_WM, "Will NOT set dummy animation on: " + wtoken
+                            + ", using null transfered animation!");
+                }
                 if (!wtoken.mAppAnimator.usingTransferredAnimation &&
                         (!wtoken.startingDisplayed || mSkipAppTransitionAnimation)) {
                     if (DEBUG_APP_TRANSITIONS) Slog.v(
@@ -4298,7 +4304,6 @@
                 if (visible) {
                     wtoken.mEnteringAnimation = true;
                 } else {
-                    wtoken.setWindowsExiting(true);
                     mClosingApps.add(wtoken);
                     wtoken.mEnteringAnimation = false;
                 }
@@ -5174,18 +5179,16 @@
     }
 
     @Override
-    public void keyguardGoingAway(boolean disableWindowAnimations,
-            boolean keyguardGoingToNotificationShade) {
+    public void keyguardGoingAway(int flags) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
                 != PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
         }
-        if (DEBUG_KEYGUARD) Slog.d(TAG_WM, "keyguardGoingAway: disableWinAnim="
-                + disableWindowAnimations + " kgToNotifShade=" + keyguardGoingToNotificationShade);
+        if (DEBUG_KEYGUARD) Slog.d(TAG_WM,
+                "keyguardGoingAway: flags=0x" + Integer.toHexString(flags));
         synchronized (mWindowMap) {
             mAnimator.mKeyguardGoingAway = true;
-            mAnimator.mKeyguardGoingAwayToNotificationShade = keyguardGoingToNotificationShade;
-            mAnimator.mKeyguardGoingAwayDisableWindowAnimations = disableWindowAnimations;
+            mAnimator.mKeyguardGoingAwayFlags = flags;
             mWindowPlacerLocked.requestTraversal();
         }
     }
@@ -9908,6 +9911,9 @@
                     pw.print(mLastFinishedFreezeSource);
                 }
                 pw.println();
+
+        mInputMonitor.dump(pw, "  ");
+
         if (dumpAll) {
             pw.print("  mSystemDecorLayer="); pw.print(mSystemDecorLayer);
                     pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString());
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index aff668b..cd771ba 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -670,8 +670,8 @@
             }
 
             if (windowsAreFloating) {
-                // In floating modes (e.g. freeform, pinned) we have only to set the rectangle 
-                // if it wasn't set already. No need to intersect it with the (visible) 
+                // In floating modes (e.g. freeform, pinned) we have only to set the rectangle
+                // if it wasn't set already. No need to intersect it with the (visible)
                 // "content frame" since it is allowed to be outside the visible desktop.
                 if (mContainingFrame.isEmpty()) {
                     mContainingFrame.set(cf);
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index bf8a62e..6ce1a64 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -160,6 +160,7 @@
     boolean mEnteringAnimation;
 
     boolean mKeyguardGoingAwayAnimation;
+    boolean mKeyguardGoingAwayWithWallpaper;
 
     /** The pixel format of the underlying SurfaceControl */
     int mSurfaceFormat;
@@ -250,6 +251,7 @@
             mAnimation.cancel();
             mAnimation = null;
             mKeyguardGoingAwayAnimation = false;
+            mKeyguardGoingAwayWithWallpaper = false;
         }
     }
 
@@ -381,6 +383,7 @@
 
         mAnimating = false;
         mKeyguardGoingAwayAnimation = false;
+        mKeyguardGoingAwayWithWallpaper = false;
         mLocalAnimating = false;
         if (mAnimation != null) {
             mAnimation.cancel();
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 8ada2f1..5ad771f 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -1158,7 +1158,7 @@
 
             if (!appAnimator.usingTransferredAnimation) {
                 appAnimator.clearThumbnail();
-                appAnimator.animation = null;
+                appAnimator.setNullAnimation();
             }
             wtoken.inPendingTransaction = false;
 
@@ -1231,7 +1231,7 @@
             final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
             appAnimator.clearThumbnail();
-            appAnimator.animation = null;
+            appAnimator.setNullAnimation();
             wtoken.inPendingTransaction = false;
             mService.setTokenVisibilityLocked(wtoken, animLp, false, transit, false,
                     voiceInteraction);
@@ -1494,7 +1494,7 @@
                 if (DEBUG_APP_TRANSITIONS)
                     Slog.v(TAG, "Now animating app in place " + wtoken);
                 appAnimator.clearThumbnail();
-                appAnimator.animation = null;
+                appAnimator.setNullAnimation();
                 mService.updateTokenInPlaceLocked(wtoken, transit);
                 wtoken.updateReportedVisibilityLocked();
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b48c185..2e8b026 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1664,12 +1664,14 @@
         } else {
             if (mOwners.hasDeviceOwner()) {
                 mInjector.systemPropertiesSet(PROPERTY_DEVICE_OWNER_PRESENT, "true");
+                Slog.i(LOG_TAG, "Set ro.device_owner property to true");
                 disableDeviceLoggingIfNotCompliant();
                 if (mInjector.securityLogGetLoggingEnabledProperty()) {
                     mSecurityLogMonitor.start();
                 }
             } else {
                 mInjector.systemPropertiesSet(PROPERTY_DEVICE_OWNER_PRESENT, "false");
+                Slog.i(LOG_TAG, "Set ro.device_owner property to false");
             }
         }
     }
@@ -7893,6 +7895,29 @@
             }
             return false;
         }
+
+        @Override
+        public Intent createPackageSuspendedDialogIntent(String packageName, int userId) {
+            Intent intent = new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS);
+            intent.putExtra(Intent.EXTRA_USER_ID, userId);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            synchronized (DevicePolicyManagerService.this) {
+                ComponentName profileOwner = mOwners.getProfileOwnerComponent(userId);
+                if (profileOwner != null) {
+                    intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, profileOwner);
+                    return intent;
+                }
+
+                if (mOwners.getDeviceOwnerUserId() == userId) {
+                    ComponentName deviceOwner = mOwners.getDeviceOwnerComponent();
+                    if (deviceOwner != null) {
+                        intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, deviceOwner);
+                        return intent;
+                    }
+                }
+            }
+            return null;
+        }
     }
 
     /**
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
index f2c42db..f978d84 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
@@ -16,6 +16,7 @@
 package com.android.server.pm;
 
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
@@ -27,6 +28,7 @@
 import android.content.pm.LauncherApps;
 import android.content.pm.LauncherApps.ShortcutQuery;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutManager;
 import android.content.pm.ShortcutServiceInternal;
@@ -191,6 +193,17 @@
         boolean injectIsLowRamDevice() {
             return mInjectdIsLowRamDevice;
         }
+
+        @Override
+        PackageManagerInternal injectPackageManagerInternal() {
+            return mMockPackageManagerInternal;
+        }
+
+        @Override
+        boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId) {
+            // Sort of hack; do a simpler check.
+            return LAUNCHER_1.equals(callingPackage) || LAUNCHER_2.equals(callingPackage);
+        }
     }
 
     /** ShortcutManager with injection override methods. */
@@ -258,6 +271,7 @@
     private Map<String, Integer> mInjectedPackageUidMap;
 
     private PackageManager mMockPackageManager;
+    private PackageManagerInternal mMockPackageManagerInternal;
     private UserManager mMockUserManager;
 
     private static final String CALLING_PACKAGE_1 = "com.android.test.1";
@@ -298,6 +312,7 @@
         mClientContext = new ClientContext();
 
         mMockPackageManager = mock(PackageManager.class);
+        mMockPackageManagerInternal = mock(PackageManagerInternal.class);
         mMockUserManager = mock(UserManager.class);
 
         // Prepare injection values.
@@ -907,7 +922,7 @@
         dumpsysOnLogcat();
 
         mInjectedCurrentTimeLillis++; // Need to advance the clock for reset to work.
-        mService.resetThrottlingInner();
+        mService.resetThrottlingInner(UserHandle.USER_SYSTEM);
 
         dumpsysOnLogcat();
 
@@ -1889,6 +1904,9 @@
             assertEquals(2, mManager.getRemainingCallCount());
         });
 
+        mService.getShortcutsForTest().get(UserHandle.USER_SYSTEM).setLauncherComponent(
+                mService, new ComponentName("pkg1", "class"));
+
         // Restore.
         initService();
 
@@ -1918,6 +1936,9 @@
             assertEquals("title2-2", getCallerShortcut("s2").getTitle());
         });
 
+        assertEquals("pkg1", mService.getShortcutsForTest().get(UserHandle.USER_SYSTEM)
+                .getLauncherComponent().getPackageName());
+
         // Start another user
         mService.onStartUserLocked(USER_10);
 
@@ -1932,6 +1953,7 @@
             assertEquals("title10-1-1", getCallerShortcut("s1").getTitle());
             assertEquals("title10-1-2", getCallerShortcut("s2").getTitle());
         });
+        assertNull(mService.getShortcutsForTest().get(USER_10).getLauncherComponent());
 
         // Try stopping the user
         mService.onCleanupUserInner(USER_10);
@@ -1941,4 +1963,8 @@
 
         // TODO Check all other fields
     }
+
+    // TODO Detailed test for hasShortcutPermissionInner().
+
+    // TODO Add tests for the command line functions too.
 }
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 10808da..afb7d93 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -95,6 +95,19 @@
     public static final int STATE_DISCONNECTING = 10;
 
     /**
+     * The state of an external call which is in the process of being pulled from a remote device to
+     * the local device.
+     * <p>
+     * A call can only be in this state if the {@link Details#PROPERTY_IS_EXTERNAL_CALL} property
+     * and {@link Details#CAPABILITY_CAN_PULL_CALL} capability are set on the call.
+     * <p>
+     * An {@link InCallService} will only see this state if it has the
+     * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its
+     * manifest.
+     */
+    public static final int STATE_PULLING_CALL = 11;
+
+    /**
      * The key to retrieve the optional {@code PhoneAccount}s Telecom can bundle with its Call
      * extras. Used to pass the phone accounts to display on the front end to the user in order to
      * select phone accounts to (for example) place a call.
@@ -226,8 +239,23 @@
          */
         public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00400000;
 
+        /**
+         * When set for an external call, indicates that this {@code Call} can be pulled from a
+         * remote device to the current device.
+         * <p>
+         * Should only be set on a {@code Call} where {@link #PROPERTY_IS_EXTERNAL_CALL} is set.
+         * <p>
+         * An {@link InCallService} will only see calls with this capability if it has the
+         * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
+         * in its manifest.
+         * <p>
+         * See {@link Connection#CAPABILITY_CAN_PULL_CALL} and
+         * {@link Connection#CAPABILITY_IS_EXTERNAL_CALL}.
+         */
+        public static final int CAPABILITY_CAN_PULL_CALL = 0x00800000;
+
         //******************************************************************************************
-        // Next CAPABILITY value: 0x00800000
+        // Next CAPABILITY value: 0x01000000
         //******************************************************************************************
 
         /**
@@ -261,8 +289,25 @@
          */
         public static final int PROPERTY_WORK_CALL = 0x00000020;
 
+        /**
+         * When set, indicates that this {@code Call} does not actually exist locally for the
+         * {@link ConnectionService}.
+         * <p>
+         * Consider, for example, a scenario where a user has two phones with the same phone number.
+         * When a user places a call on one device, the telephony stack can represent that call on
+         * the other device by adding it to the {@link ConnectionService} with the
+         * {@link Connection#CAPABILITY_IS_EXTERNAL_CALL} capability set.
+         * <p>
+         * An {@link InCallService} will only see calls with this property if it has the
+         * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
+         * in its manifest.
+         * <p>
+         * See {@link Connection#CAPABILITY_IS_EXTERNAL_CALL}.
+         */
+        public static final int PROPERTY_IS_EXTERNAL_CALL = 0x00000040;
+
         //******************************************************************************************
-        // Next PROPERTY value: 0x00000040
+        // Next PROPERTY value: 0x00000100
         //******************************************************************************************
 
         private final String mTelecomCallId;
@@ -362,6 +407,9 @@
             if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
                 builder.append(" CAPABILITY_CAN_PAUSE_VIDEO");
             }
+            if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
+                builder.append(" CAPABILITY_CAN_PULL_CALL");
+            }
             builder.append("]");
             return builder.toString();
         }
@@ -411,6 +459,9 @@
             if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
                 builder.append(" PROPERTY_EMERGENCY_CALLBACK_MODE");
             }
+            if (hasProperty(properties, PROPERTY_IS_EXTERNAL_CALL)) {
+                builder.append(" PROPERTY_IS_EXTERNAL_CALL");
+            }
             builder.append("]");
             return builder.toString();
         }
@@ -723,6 +774,17 @@
          *          conferenced.
          */
         public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {}
+
+        /**
+         * Invoked when a call receives an event from its associated {@link Connection}.
+         * <p>
+         * See {@link Connection#sendConnectionEvent(String, Bundle)}.
+         *
+         * @param call The {@code Call} receiving the event.
+         * @param event The event.
+         * @param extras Extras associated with the connection event.
+         */
+        public void onConnectionEvent(Call call, String event, Bundle extras) {}
     }
 
     /**
@@ -889,6 +951,43 @@
     }
 
     /**
+     * Initiates a request to the {@link ConnectionService} to pull an external call to the local
+     * device.
+     * <p>
+     * Calls to this method are ignored if the call does not have the
+     * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property set.
+     * <p>
+     * An {@link InCallService} will only see calls which support this method if it has the
+     * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
+     * in its manifest.
+     */
+    public void pullExternalCall() {
+        // If this isn't an external call, ignore the request.
+        if (!mDetails.hasProperty(Details.PROPERTY_IS_EXTERNAL_CALL)) {
+            return;
+        }
+
+        mInCallAdapter.pullExternalCall(mTelecomCallId);
+    }
+
+    /**
+     * Sends a {@code Call} event from this {@code Call} to the associated {@link Connection} in
+     * the {@link ConnectionService}.
+     * <p>
+     * Events are exposed to {@link ConnectionService} implementations via
+     * {@link android.telecom.Connection#onCallEvent(String, Bundle)}.
+     * <p>
+     * No assumptions should be made as to how a {@link ConnectionService} will handle these events.
+     * Events should be fully qualified (e.g., com.example.event.MY_EVENT) to avoid conflicts.
+     *
+     * @param event The connection event.
+     * @param extras Bundle containing extra information associated with the event.
+     */
+    public void sendCallEvent(String event, Bundle extras) {
+        mInCallAdapter.sendCallEvent(mTelecomCallId, event, extras);
+    }
+
+    /**
      * Obtains the parent of this {@code Call} in a conference, if any.
      *
      * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
@@ -1211,6 +1310,11 @@
         }
     }
 
+    /** {@hide} */
+    final void internalOnConnectionEvent(String event, Bundle extras) {
+        fireOnConnectionEvent(event, extras);
+    }
+
     private void fireStateChanged(final int newState) {
         for (CallbackRecord<Callback> record : mCallbackRecords) {
             final Call call = this;
@@ -1358,6 +1462,27 @@
     }
 
     /**
+     * Notifies listeners of an incoming connection event.
+     * <p>
+     * Connection events are issued via {@link Connection#sendConnectionEvent(String, Bundle)}.
+     *
+     * @param event
+     * @param extras
+     */
+    private void fireOnConnectionEvent(final String event, final Bundle extras) {
+        for (CallbackRecord<Callback> record : mCallbackRecords) {
+            final Call call = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onConnectionEvent(call, event, extras);
+                }
+            });
+        }
+    }
+
+    /**
      * Determines if two bundles are equal.
      *
      * @param bundle The original bundle.
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 4547c6a..51a6588 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -93,6 +93,15 @@
     public static final int STATE_DISCONNECTED = 6;
 
     /**
+     * The state of an external connection which is in the process of being pulled from a remote
+     * device to the local device.
+     * <p>
+     * A connection can only be in this state if the {@link #CAPABILITY_IS_EXTERNAL_CALL} and
+     * {@link #CAPABILITY_CAN_PULL_CALL} capability bits are set on the connection.
+     */
+    public static final int STATE_PULLING_CALL = 7;
+
+    /**
      * Connection can currently be put on hold or unheld. This is distinct from
      * {@link #CAPABILITY_SUPPORT_HOLD} in that although a connection may support 'hold' most times,
      * it does not at the moment support the function. This can be true while the call is in the
@@ -251,7 +260,6 @@
     /**
      * Indicates that the connection itself wants to handle any sort of reply response, rather than
      * relying on SMS.
-     * @hide
      */
     public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 0x00400000;
 
@@ -270,8 +278,33 @@
      */
     public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00800000;
 
+    /**
+     * When set, indicates that the {@code Connection} does not actually exist locally for the
+     * {@link ConnectionService}.
+     * <p>
+     * Consider, for example, a scenario where a user has two devices with the same phone number.
+     * When a user places a call on one devices, the telephony stack can represent that call on the
+     * other device by adding is to the {@link ConnectionService} with the
+     * {@code CAPABILITY_IS_EXTERNAL_CALL} capability set.
+     * <p>
+     * An {@link ConnectionService} should not assume that all {@link InCallService}s will handle
+     * external connections.  Only those {@link InCallService}s which have the
+     * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its
+     * manifest will see external connections.
+     */
+    public static final int CAPABILITY_IS_EXTERNAL_CALL = 0x01000000;
+
+    /**
+     * When set for an external connection, indicates that this {@code Connection} can be pulled
+     * from a remote device to the current device.
+     * <p>
+     * Should only be set on a {@code Connection} where {@link #CAPABILITY_IS_EXTERNAL_CALL}
+     * is set.
+     */
+    public static final int CAPABILITY_CAN_PULL_CALL = 0x02000000;
+
     //**********************************************************************************************
-    // Next CAPABILITY value: 0x01000000
+    // Next CAPABILITY value: 0x04000000
     //**********************************************************************************************
 
     /**
@@ -315,6 +348,18 @@
     public static final String EVENT_ON_HOLD_TONE_END =
             "android.telecom.event.ON_HOLD_TONE_END";
 
+    /**
+     * Connection event used to inform {@link InCallService}s when pulling of an external call has
+     * failed.  The user interface should inform the user of the error.
+     * <p>
+     * Expected to be used by the {@link ConnectionService} when the {@link Call#pullExternalCall()}
+     * API is called on a {@link Call} with the properties
+     * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} and
+     * {@link Call.Details#CAPABILITY_CAN_PULL_CALL}, but the {@link ConnectionService} could not
+     * pull the external call due to an error condition.
+     */
+    public static final String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED";
+
     // Flag controlling whether PII is emitted into the logs
     private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
 
@@ -434,6 +479,12 @@
         if (can(capabilities, CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION)) {
             builder.append(" CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION");
         }
+        if (can(capabilities, CAPABILITY_IS_EXTERNAL_CALL)) {
+            builder.append(" CAPABILITY_IS_EXTERNAL_CALL");
+        }
+        if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
+            builder.append(" CAPABILITY_CAN_PULL_CALL");
+        }
 
         builder.append("]");
         return builder.toString();
@@ -465,8 +516,7 @@
         public void onConferenceStarted() {}
         public void onConferenceMergeFailed(Connection c) {}
         public void onExtrasChanged(Connection c, Bundle extras) {}
-        /** @hide */
-        public void onConnectionEvent(Connection c, String event) {}
+        public void onConnectionEvent(Connection c, String event, Bundle extras) {}
     }
 
     /**
@@ -1836,9 +1886,8 @@
     public void onReject() {}
 
     /**
-     * Notifies ths Connection of a request reject with a message.
-     *
-     * @hide
+     * Notifies this Connection, which is in {@link #STATE_RINGING}, of
+     * a request to reject with a message.
      */
     public void onReject(String replyMessage) {}
 
@@ -1854,6 +1903,31 @@
      */
     public void onPostDialContinue(boolean proceed) {}
 
+    /**
+     * Notifies this Connection of a request to pull an external call to the local device.
+     * <p>
+     * The {@link InCallService} issues a request to pull an external call to the local device via
+     * {@link Call#pullExternalCall()}.
+     * <p>
+     * For a Connection to be pulled, both the {@link Connection#CAPABILITY_CAN_PULL_CALL} and
+     * {@link Connection#CAPABILITY_IS_EXTERNAL_CALL} capability bits must be set.
+     * <p>
+     * For more information on external calls, see {@link Connection#CAPABILITY_IS_EXTERNAL_CALL}.
+     */
+    public void onPullExternalCall() {}
+
+    /**
+     * Notifies this Connection of a {@link Call} event initiated from an {@link InCallService}.
+     * <p>
+     * The {@link InCallService} issues a Call event via {@link Call#sendCallEvent(String, Bundle)}.
+     * <p>
+     * See also {@link Call#sendCallEvent(String, Bundle)}.
+     *
+     * @param event The call event.
+     * @param extras Extras associated with the call event.
+     */
+    public void onCallEvent(String event, Bundle extras) {}
+
     static String toLogSafePhoneNumber(String number) {
         // For unknown number, log empty string.
         if (number == null) {
@@ -2008,14 +2082,20 @@
     }
 
     /**
-     * Sends a connection event to Telecom.
+     * Sends an event associated with this {@code Connection}, with associated event extras.
+     *
+     * Events are exposed to {@link InCallService} implementations via the
+     * {@link Call.Callback#onConnectionEvent(Call, String, Bundle)} API.
+     *
+     * No assumptions should be made as to how an In-Call UI or service will handle these events.
+     * Events should be fully qualified (e.g., com.example.event.MY_EVENT) to avoid conflicts.
      *
      * @param event The connection event.
-     * @hide
+     * @param extras Bundle containing extra information associated with the event.
      */
-    protected void sendConnectionEvent(String event) {
+    public void sendConnectionEvent(String event, Bundle extras) {
         for (Listener l : mListeners) {
-            l.onConnectionEvent(this, event);
+            l.onConnectionEvent(this, event, null);
         }
     }
 }
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 5b62e03..d18b317 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -103,6 +103,8 @@
     private static final int MSG_SWAP_CONFERENCE = 19;
     private static final int MSG_REJECT_WITH_MESSAGE = 20;
     private static final int MSG_SILENCE = 21;
+    private static final int MSG_PULL_EXTERNAL_CALL = 22;
+    private static final int MSG_SEND_CALL_EVENT = 23;
 
     private static Connection sNullConnection;
 
@@ -245,6 +247,20 @@
             args.argi1 = proceed ? 1 : 0;
             mHandler.obtainMessage(MSG_ON_POST_DIAL_CONTINUE, args).sendToTarget();
         }
+
+        @Override
+        public void pullExternalCall(String callId) {
+            mHandler.obtainMessage(MSG_PULL_EXTERNAL_CALL, callId).sendToTarget();
+        }
+
+        @Override
+        public void sendCallEvent(String callId, String event, Bundle extras) {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = callId;
+            args.arg2 = event;
+            args.arg3 = extras;
+            mHandler.obtainMessage(MSG_SEND_CALL_EVENT, args).sendToTarget();
+        }
     };
 
     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@@ -382,6 +398,22 @@
                     }
                     break;
                 }
+                case MSG_PULL_EXTERNAL_CALL: {
+                    pullExternalCall((String) msg.obj);
+                    break;
+                }
+                case MSG_SEND_CALL_EVENT: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        String callId = (String) args.arg1;
+                        String event = (String) args.arg2;
+                        Bundle extras = (Bundle) args.arg3;
+                        sendCallEvent(callId, event, extras);
+                    } finally {
+                        args.recycle();
+                    }
+                    break;
+                }
                 default:
                     break;
             }
@@ -615,10 +647,10 @@
         }
 
         @Override
-        public void onConnectionEvent(Connection connection, String event) {
+        public void onConnectionEvent(Connection connection, String event, Bundle extras) {
             String id = mIdByConnection.get(connection);
             if (id != null) {
-                mAdapter.onConnectionEvent(id, event);
+                mAdapter.onConnectionEvent(id, event, extras);
             }
         }
     };
@@ -864,6 +896,39 @@
         }
     }
 
+    /**
+     * Notifies a {@link Connection} of a request to pull an external call.
+     *
+     * See {@link Call#pullExternalCall()}.
+     *
+     * @param callId The ID of the call to pull.
+     */
+    private void pullExternalCall(String callId) {
+        Log.d(this, "pullExternalCall(%s)", callId);
+        Connection connection = findConnectionForAction(callId, "pullExternalCall");
+        if (connection != null) {
+            connection.onPullExternalCall();
+        }
+    }
+
+    /**
+     * Notifies a {@link Connection} of a call event.
+     *
+     * See {@link Call#sendCallEvent(String, Bundle)}.
+     *
+     * @param callId The ID of the call receiving the event.
+     * @param event The event.
+     * @param extras Extras associated with the event.
+     */
+    private void sendCallEvent(String callId, String event, Bundle extras) {
+        Log.d(this, "sendCallEvent(%s, %s)", callId, event);
+        Connection connection = findConnectionForAction(callId, "sendCallEvent");
+        if (connection != null) {
+            connection.onCallEvent(event, extras);
+        }
+
+    }
+
     private void onPostDialContinue(String callId, boolean proceed) {
         Log.d(this, "onPostDialContinue(%s)", callId);
         findConnectionForAction(callId, "stopDtmfTone").onPostDialContinue(proceed);
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
index 30fc5ad..e91128f 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
@@ -418,12 +418,13 @@
      *
      * @param callId The unique ID of the call.
      * @param event The event.
+     * @param extras Extras associated with the event.
      */
-    void onConnectionEvent(String callId, String event) {
+    void onConnectionEvent(String callId, String event, Bundle extras) {
         Log.v(this, "onConnectionEvent: %s", event);
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.onConnectionEvent(callId, event);
+                adapter.onConnectionEvent(callId, event, extras);
             } catch (RemoteException ignored) {
             }
         }
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
index 6a8c1cb..4b15e54 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
@@ -245,7 +245,8 @@
                 case MSG_ON_CONNECTION_EVENT: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.onConnectionEvent((String) args.arg1, (String) args.arg2);
+                        mDelegate.onConnectionEvent((String) args.arg1, (String) args.arg2,
+                                (Bundle) args.arg3);
                     } finally {
                         args.recycle();
                     }
@@ -432,10 +433,11 @@
         }
 
         @Override
-        public final void onConnectionEvent(String connectionId, String event) {
+        public final void onConnectionEvent(String connectionId, String event, Bundle extras) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = event;
+            args.arg3 = extras;
             mHandler.obtainMessage(MSG_ON_CONNECTION_EVENT, args).sendToTarget();
         }
     };
diff --git a/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java
index 2eef7ee..cf73d4f 100644
--- a/telecomm/java/android/telecom/DisconnectCause.java
+++ b/telecomm/java/android/telecom/DisconnectCause.java
@@ -64,6 +64,17 @@
      */
     public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10;
 
+    /**
+     * Disconnected because the user did not locally answer the incoming call, but it was answered
+     * on another device where the call was ringing.
+     */
+    public static final int ANSWERED_ELSEWHERE = 11;
+
+    /**
+     * Disconnected because the call was pulled from the current device to another device.
+     */
+    public static final int CALL_PULLED = 12;
+
     private int mDisconnectCode;
     private CharSequence mDisconnectLabel;
     private CharSequence mDisconnectDescription;
diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java
index 0cf7212b..52ef4a7 100644
--- a/telecomm/java/android/telecom/InCallAdapter.java
+++ b/telecomm/java/android/telecom/InCallAdapter.java
@@ -16,6 +16,7 @@
 
 package android.telecom;
 
+import android.os.Bundle;
 import android.os.RemoteException;
 
 import com.android.internal.telecom.IInCallAdapter;
@@ -251,6 +252,32 @@
     }
 
     /**
+     * Instructs Telecom to pull an external call to the local device.
+     *
+     * @param callId The callId to pull.
+     */
+    public void pullExternalCall(String callId) {
+        try {
+            mAdapter.pullExternalCall(callId);
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    /**
+     * Intructs Telecom to send a call event.
+     *
+     * @param callId The callId to send the event for.
+     * @param event The event.
+     * @param extras Extras associated with the event.
+     */
+    public void sendCallEvent(String callId, String event, Bundle extras) {
+        try {
+            mAdapter.sendCallEvent(callId, event, extras);
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    /**
      * Instructs Telecom to turn the proximity sensor on.
      */
     public void turnProximitySensorOn() {
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index 671399b..df6715d 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -22,6 +22,7 @@
 import android.content.Intent;
 import android.hardware.camera2.CameraManager;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -74,6 +75,7 @@
     private static final int MSG_BRING_TO_FOREGROUND = 6;
     private static final int MSG_ON_CAN_ADD_CALL_CHANGED = 7;
     private static final int MSG_SILENCE_RINGER = 8;
+    private static final int MSG_ON_CONNECTION_EVENT = 9;
 
     /** Default Handler used to consolidate binder method calls onto a single thread. */
     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@@ -118,6 +120,18 @@
                 case MSG_SILENCE_RINGER:
                     mPhone.internalSilenceRinger();
                     break;
+                case MSG_ON_CONNECTION_EVENT: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        String callId = (String) args.arg1;
+                        String event = (String) args.arg2;
+                        Bundle extras = (Bundle) args.arg3;
+                        mPhone.internalOnConnectionEvent(callId, event, extras);
+                    } finally {
+                        args.recycle();
+                    }
+                    break;
+                }
                 default:
                     break;
             }
@@ -174,6 +188,15 @@
         public void silenceRinger() {
             mHandler.obtainMessage(MSG_SILENCE_RINGER).sendToTarget();
         }
+
+        @Override
+        public void onConnectionEvent(String callId, String event, Bundle extras) {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = callId;
+            args.arg2 = event;
+            args.arg3 = extras;
+            mHandler.obtainMessage(MSG_ON_CONNECTION_EVENT, args).sendToTarget();
+        }
     }
 
     private Phone.Listener mPhoneListener = new Phone.Listener() {
@@ -426,6 +449,19 @@
     }
 
     /**
+     * Called when a {@link Call} has received a connection event issued by the
+     * {@link ConnectionService}.
+     * <p>
+     * See {@link Connection#sendConnectionEvent(String, Bundle)}.
+     *
+     * @param call The call the event is associated with.
+     * @param event The event.
+     * @param extras Any associated extras.
+     */
+    public void onConnectionEvent(Call call, String event, Bundle extras) {
+    }
+
+    /**
      * Used to issue commands to the {@link Connection.VideoProvider} associated with a
      * {@link Call}.
      */
diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java
index d45938c..a4ef560 100644
--- a/telecomm/java/android/telecom/Phone.java
+++ b/telecomm/java/android/telecom/Phone.java
@@ -17,6 +17,7 @@
 package android.telecom;
 
 import android.annotation.SystemApi;
+import android.os.Bundle;
 import android.util.ArrayMap;
 
 import java.util.Collections;
@@ -190,6 +191,13 @@
         fireSilenceRinger();
     }
 
+    final void internalOnConnectionEvent(String telecomId, String event, Bundle extras) {
+        Call call = mCallByTelecomCallId.get(telecomId);
+        if (call != null) {
+            call.internalOnConnectionEvent(event, extras);
+        }
+    }
+
     /**
      * Called to destroy the phone and cleanup any lingering calls.
      */
diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java
index 0185808..5b602eb 100644
--- a/telecomm/java/android/telecom/RemoteConnection.java
+++ b/telecomm/java/android/telecom/RemoteConnection.java
@@ -212,12 +212,14 @@
 
         /**
          * Handles a connection event propagated to this {@link RemoteConnection}.
+         * <p>
+         * Connection events originate from {@link Connection#sendConnectionEvent(String, Bundle)}.
          *
          * @param connection The {@code RemoteConnection} invoking this method.
          * @param event The connection event.
-         * @hide
+         * @param extras Extras associated with the event.
          */
-        public void onConnectionEvent(RemoteConnection connection, String event) {}
+        public void onConnectionEvent(RemoteConnection connection, String event, Bundle extras) {}
     }
 
     /**
@@ -962,6 +964,20 @@
     }
 
     /**
+     * Instructs this {@link RemoteConnection} to pull itself to the local device.
+     * <p>
+     * See {@link Call#pullExternalCall()} for more information.
+     */
+    public void pullExternalCall() {
+        try {
+            if (mConnected) {
+                mConnectionService.pullExternalCall(mConnectionId);
+            }
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    /**
      * Set the audio state of this {@code RemoteConnection}.
      *
      * @param state The audio state of this {@code RemoteConnection}.
@@ -1301,14 +1317,14 @@
     }
 
     /** @hide */
-    void onConnectionEvent(final String event) {
+    void onConnectionEvent(final String event, final Bundle extras) {
         for (CallbackRecord record : mCallbackRecords) {
             final RemoteConnection connection = this;
             final Callback callback = record.getCallback();
             record.getHandler().post(new Runnable() {
                 @Override
                 public void run() {
-                    callback.onConnectionEvent(connection, event);
+                    callback.onConnectionEvent(connection, event, extras);
                 }
             });
         }
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index b85382f..fa7183a 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -332,9 +332,10 @@
         }
 
         @Override
-        public void onConnectionEvent(String callId, String event) {
+        public void onConnectionEvent(String callId, String event, Bundle extras) {
             if (mConnectionById.containsKey(callId)) {
-                findConnectionForAction(callId, "onConnectionEvent").onConnectionEvent(event);
+                findConnectionForAction(callId, "onConnectionEvent").onConnectionEvent(event,
+                        extras);
             }
         }
     };
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 8afb455..4fa8fe9 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -317,6 +317,18 @@
             "android.telecom.IN_CALL_SERVICE_RINGING";
 
     /**
+     * A boolean meta-data value indicating whether an {@link InCallService} wants to be informed of
+     * calls which have the {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property.  An external
+     * call is one which a {@link ConnectionService} knows about, but is not connected to directly.
+     * Dialer implementations (see {@link #getDefaultDialerPackage()}) which would like to be
+     * informed of external calls should set this meta-data to {@code true} in the manifest
+     * registration of their {@link InCallService}.  By default, the {@link InCallService} will NOT
+     * be informed of external calls.
+     */
+    public static final String METADATA_INCLUDE_EXTERNAL_CALLS =
+            "android.telecom.INCLUDE_EXTERNAL_CALLS";
+
+    /**
      * The dual tone multi-frequency signaling character sent to indicate the dialing system should
      * pause for a predefined period.
      */
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
index 8a54add..3ee0e9f 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
@@ -75,4 +75,8 @@
     void swapConference(String conferenceCallId);
 
     void onPostDialContinue(String callId, boolean proceed);
+
+    void pullExternalCall(String callId);
+
+    void sendCallEvent(String callId, String event, in Bundle extras);
 }
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
index 569c244..dff1b11 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
@@ -87,5 +87,5 @@
 
     void setExtras(String callId, in Bundle extras);
 
-    void onConnectionEvent(String callId, String event);
+    void onConnectionEvent(String callId, String event, in Bundle extras);
 }
diff --git a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
index 863fff2..0678fe2 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
@@ -16,6 +16,7 @@
 
 package com.android.internal.telecom;
 
+import android.os.Bundle;
 import android.telecom.PhoneAccountHandle;
 
 /**
@@ -60,4 +61,8 @@
     void turnOnProximitySensor();
 
     void turnOffProximitySensor(boolean screenOnImmediately);
+
+    void pullExternalCall(String callId);
+
+    void sendCallEvent(String callId, String event, in Bundle extras);
 }
diff --git a/telecomm/java/com/android/internal/telecom/IInCallService.aidl b/telecomm/java/com/android/internal/telecom/IInCallService.aidl
index 0088e0c..3e43fe2 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallService.aidl
@@ -17,6 +17,7 @@
 package com.android.internal.telecom;
 
 import android.app.PendingIntent;
+import android.os.Bundle;
 import android.telecom.CallAudioState;
 import android.telecom.ParcelableCall;
 
@@ -47,4 +48,6 @@
     void onCanAddCallChanged(boolean canAddCall);
 
     void silenceRinger();
+
+    void onConnectionEvent(String callId, String event, in Bundle extras);
 }
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 7f90731..4f0e036 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -97,6 +97,12 @@
     int NETWORK_REJECT = 53;                  /* Request is rejected by network */
     int OPERATION_NOT_ALLOWED = 54;           /* Not allowed the request now */
     int EMPTY_RECORD = 55;                    /* The request record is empty */
+    int INVALID_SMS_FORMAT = 56;              /* Invalid sms format */
+    int ENCODING_ERR = 57;                    /* Message not encoded properly */
+    int INVALID_SMSC_ADDRESS = 58;            /* SMSC address specified is invalid */
+    int NO_SUCH_ENTRY = 59;                   /* No such entry present to perform the request */
+    int NETWORK_NOT_READY = 60;               /* Network is not ready to perform the request */
+    int NOT_PROVISIONED = 61;                 /* Device doesnot have this value provisioned */
     // Below is list of OEM specific error codes which can by used by OEMs in case they don't want to
     // reveal particular replacement for Generic failure
     int OEM_ERROR_1 = 501;
diff --git a/tests/SoundTriggerTests/Android.mk b/tests/SoundTriggerTests/Android.mk
index ac562b9..e67134d 100644
--- a/tests/SoundTriggerTests/Android.mk
+++ b/tests/SoundTriggerTests/Android.mk
@@ -27,6 +27,7 @@
   LOCAL_SRC_FILES := src/android/hardware/soundtrigger/SoundTriggerTest.java
 endif
 
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
 LOCAL_PACKAGE_NAME := SoundTriggerTests
diff --git a/tests/SoundTriggerTests/AndroidManifest.xml b/tests/SoundTriggerTests/AndroidManifest.xml
index e8b9dd3..f7454c7 100644
--- a/tests/SoundTriggerTests/AndroidManifest.xml
+++ b/tests/SoundTriggerTests/AndroidManifest.xml
@@ -17,7 +17,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="android.hardware.soundtrigger">
     <uses-permission android:name="android.permission.MANAGE_SOUND_TRIGGER" />
-
+    <uses-permission android:name="android.permission.INTERNET" />
+    
     <application>
         <uses-library android:name="android.test.runner" />
     </application>
diff --git a/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java
index 7acb472..ad02d2b 100644
--- a/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java
+++ b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java
@@ -16,70 +16,180 @@
 
 package android.hardware.soundtrigger;
 
-import java.util.Random;
-import java.util.UUID;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
 
 import android.content.Context;
+import android.hardware.soundtrigger.SoundTrigger.GenericRecognitionEvent;
 import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
+import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionEvent;
+import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
 import android.media.soundtrigger.SoundTriggerManager;
 import android.os.ParcelUuid;
 import android.os.ServiceManager;
 import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.internal.app.ISoundTriggerService;
 
-import java.util.Arrays;
+import java.io.DataOutputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.util.ArrayList;
 import java.util.Random;
 import java.util.UUID;
 
+import org.mockito.MockitoAnnotations;
+
 public class GenericSoundModelTest extends AndroidTestCase {
-    private Random mRandom = new Random();
+    static final int MSG_DETECTION_ERROR = -1;
+    static final int MSG_DETECTION_RESUME = 0;
+    static final int MSG_DETECTION_PAUSE = 1;
+    static final int MSG_KEYPHRASE_TRIGGER = 2;
+    static final int MSG_GENERIC_TRIGGER = 4;
+
+    private Random random = new Random();
+    private ArrayList<UUID> loadedModelUuids;
+    private ISoundTriggerService soundTriggerService;
+    private SoundTriggerManager soundTriggerManager;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        MockitoAnnotations.initMocks(this);
+
+        Context context = getContext();
+        soundTriggerService = ISoundTriggerService.Stub.asInterface(
+                ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE));
+        soundTriggerManager = (SoundTriggerManager) context.getSystemService(
+                Context.SOUND_TRIGGER_SERVICE);
+
+        loadedModelUuids = new ArrayList<UUID>();
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        for (UUID modelUuid : loadedModelUuids) {
+            soundTriggerService.deleteSoundModel(new ParcelUuid(modelUuid));
+        }
+        super.tearDown();
+    }
+
+    GenericSoundModel new_sound_model() {
+        // Create sound model
+        byte[] data = new byte[1024];
+        random.nextBytes(data);
+        UUID modelUuid = UUID.randomUUID();
+        UUID mVendorUuid = UUID.randomUUID();
+        return new GenericSoundModel(modelUuid, mVendorUuid, data);
+    }
 
     @SmallTest
     public void testUpdateGenericSoundModel() throws Exception {
-        Context context = getContext();
-        ISoundTriggerService mSoundTriggerService = ISoundTriggerService.Stub.asInterface(
-            ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE));
-        SoundTriggerManager mSoundTriggerManager = (SoundTriggerManager) context.getSystemService(
-            Context.SOUND_TRIGGER_SERVICE);
+        GenericSoundModel model = new_sound_model();
 
-        byte[] data = new byte[1024];
-        mRandom.nextBytes(data);
-        UUID modelUuid = UUID.randomUUID();
-        UUID mVendorUuid = UUID.randomUUID();
-        GenericSoundModel model = new GenericSoundModel(modelUuid, mVendorUuid, data);
+        // Update sound model
+        soundTriggerService.updateSoundModel(model);
+        loadedModelUuids.add(model.uuid);
 
-        mSoundTriggerService.updateSoundModel(model);
+        // Confirm it was updated
         GenericSoundModel returnedModel =
-            mSoundTriggerService.getSoundModel(new ParcelUuid(modelUuid));
-
+                soundTriggerService.getSoundModel(new ParcelUuid(model.uuid));
         assertEquals(model, returnedModel);
-
-        // Cleanup sound model
-        mSoundTriggerService.deleteSoundModel(new ParcelUuid(modelUuid));
     }
 
-
     @SmallTest
     public void testDeleteGenericSoundModel() throws Exception {
-        Context context = getContext();
-        ISoundTriggerService mSoundTriggerService = ISoundTriggerService.Stub.asInterface(
-            ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE));
-        SoundTriggerManager mSoundTriggerManager = (SoundTriggerManager) context.getSystemService(
-            Context.SOUND_TRIGGER_SERVICE);
+        GenericSoundModel model = new_sound_model();
 
-        byte[] data = new byte[1024];
-        mRandom.nextBytes(data);
-        UUID modelUuid = UUID.randomUUID();
-        UUID mVendorUuid = UUID.randomUUID();
-        GenericSoundModel model = new GenericSoundModel(modelUuid, mVendorUuid, data);
+        // Update sound model
+        soundTriggerService.updateSoundModel(model);
+        loadedModelUuids.add(model.uuid);
 
-        mSoundTriggerService.updateSoundModel(model);
-        mSoundTriggerService.deleteSoundModel(new ParcelUuid(modelUuid));
+        // Delete sound model
+        soundTriggerService.deleteSoundModel(new ParcelUuid(model.uuid));
+        loadedModelUuids.remove(model.uuid);
 
+        // Confirm it was deleted
         GenericSoundModel returnedModel =
-            mSoundTriggerService.getSoundModel(new ParcelUuid(modelUuid));
+                soundTriggerService.getSoundModel(new ParcelUuid(model.uuid));
         assertEquals(null, returnedModel);
     }
+
+    @LargeTest
+    public void testStartStopGenericSoundModel() throws Exception {
+        GenericSoundModel model = new_sound_model();
+
+        boolean captureTriggerAudio = true;
+        boolean allowMultipleTriggers = true;
+        RecognitionConfig config = new RecognitionConfig(captureTriggerAudio, allowMultipleTriggers,
+                null, null);
+        TestRecognitionStatusCallback spyCallback = spy(new TestRecognitionStatusCallback());
+
+        // Update and start sound model recognition
+        soundTriggerService.updateSoundModel(model);
+        loadedModelUuids.add(model.uuid);
+        int r = soundTriggerService.startRecognition(new ParcelUuid(model.uuid), spyCallback,
+                config);
+        assertEquals("Could Not Start Recognition with code: " + r,
+                android.hardware.soundtrigger.SoundTrigger.STATUS_OK, r);
+
+        // Stop recognition
+        r = soundTriggerService.stopRecognition(new ParcelUuid(model.uuid), spyCallback);
+        assertEquals("Could Not Stop Recognition with code: " + r,
+                android.hardware.soundtrigger.SoundTrigger.STATUS_OK, r);
+    }
+
+    @LargeTest
+    public void testTriggerGenericSoundModel() throws Exception {
+        GenericSoundModel model = new_sound_model();
+
+        boolean captureTriggerAudio = true;
+        boolean allowMultipleTriggers = true;
+        RecognitionConfig config = new RecognitionConfig(captureTriggerAudio, allowMultipleTriggers,
+                null, null);
+        TestRecognitionStatusCallback spyCallback = spy(new TestRecognitionStatusCallback());
+
+        // Update and start sound model
+        soundTriggerService.updateSoundModel(model);
+        loadedModelUuids.add(model.uuid);
+        soundTriggerService.startRecognition(new ParcelUuid(model.uuid), spyCallback, config);
+
+        // Send trigger to stub HAL
+        Socket socket = new Socket(InetAddress.getLocalHost(), 14035);
+        DataOutputStream out = new DataOutputStream(socket.getOutputStream());
+        out.writeBytes("trig " + model.uuid.toString() + "\r\n");
+        out.flush();
+        socket.close();
+
+        // Verify trigger was received
+        verify(spyCallback, timeout(100)).onGenericSoundTriggerDetected(any());
+    }
+
+
+    public class TestRecognitionStatusCallback extends IRecognitionStatusCallback.Stub {
+        @Override
+        public void onGenericSoundTriggerDetected(GenericRecognitionEvent recognitionEvent) {
+        }
+
+        @Override
+        public void onKeyphraseDetected(KeyphraseRecognitionEvent recognitionEvent) {
+        }
+
+        @Override
+        public void onError(int status) {
+        }
+
+        @Override
+        public void onRecognitionPaused() {
+        }
+
+        @Override
+        public void onRecognitionResumed() {
+        }
+    }
 }
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 62f91f7..7f41348 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -492,8 +492,7 @@
     }
 
     @Override
-    public void keyguardGoingAway(boolean disableWindowAnimations,
-            boolean keyguardGoingToNotificationShade) throws RemoteException {
+    public void keyguardGoingAway(int flags) throws RemoteException {
     }
 
     @Override