Merge "Incremental local builds for services"
diff --git a/api/current.txt b/api/current.txt
index daac1ba..537ae8a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2625,6 +2625,7 @@
     method public final android.accessibilityservice.AccessibilityService.MagnificationController getMagnificationController();
     method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
     method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
+    method public final android.accessibilityservice.AccessibilityService.SoftKeyboardController getSoftKeyboardController();
     method public java.util.List<android.view.accessibility.AccessibilityWindowInfo> getWindows();
     method public abstract void onAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     method public final android.os.IBinder onBind(android.content.Intent);
@@ -2683,6 +2684,18 @@
     method public abstract void onMagnificationChanged(android.accessibilityservice.AccessibilityService.MagnificationController, android.graphics.Region, float, float, float);
   }
 
+  public static final class AccessibilityService.SoftKeyboardController {
+    method public void addOnShowModeChangedListener(android.accessibilityservice.AccessibilityService.SoftKeyboardController.OnShowModeChangedListener);
+    method public void addOnShowModeChangedListener(android.accessibilityservice.AccessibilityService.SoftKeyboardController.OnShowModeChangedListener, android.os.Handler);
+    method public int getShowMode();
+    method public boolean removeOnShowModeChangedListener(android.accessibilityservice.AccessibilityService.SoftKeyboardController.OnShowModeChangedListener);
+    method public boolean setShowMode(int);
+  }
+
+  public static abstract interface AccessibilityService.SoftKeyboardController.OnShowModeChangedListener {
+    method public abstract void onShowModeChanged(android.accessibilityservice.AccessibilityService.SoftKeyboardController, int);
+  }
+
   public class AccessibilityServiceInfo implements android.os.Parcelable {
     ctor public AccessibilityServiceInfo();
     method public static java.lang.String capabilityToString(int);
@@ -5824,6 +5837,7 @@
     method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
     method public long getMaximumTimeToLock(android.content.ComponentName);
     method public int getOrganizationColor(android.content.ComponentName);
+    method public java.lang.String getOrganizationName(android.content.ComponentName);
     method public boolean getPackageSuspended(android.content.ComponentName, java.lang.String);
     method public android.app.admin.DevicePolicyManager getParentProfileInstance(android.content.ComponentName);
     method public long getPasswordExpiration(android.content.ComponentName);
@@ -5893,6 +5907,7 @@
     method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
     method public void setMaximumTimeToLock(android.content.ComponentName, long);
     method public void setOrganizationColor(android.content.ComponentName, int);
+    method public void setOrganizationName(android.content.ComponentName, java.lang.String);
     method public boolean setPackageSuspended(android.content.ComponentName, java.lang.String, boolean);
     method public void setPasswordExpirationTimeout(android.content.ComponentName, long);
     method public void setPasswordHistoryLength(android.content.ComponentName, int);
@@ -22898,6 +22913,7 @@
     method public void onInputAdded(java.lang.String);
     method public void onInputRemoved(java.lang.String);
     method public void onInputStateChanged(java.lang.String, int);
+    method public void onInputUpdated(java.lang.String);
     method public void onTvInputInfoChanged(android.media.tv.TvInputInfo);
   }
 
@@ -51314,6 +51330,9 @@
   public abstract class Inherited implements java.lang.annotation.Annotation {
   }
 
+  public abstract class Repeatable implements java.lang.annotation.Annotation {
+  }
+
   public abstract class Retention implements java.lang.annotation.Annotation {
   }
 
diff --git a/api/system-current.txt b/api/system-current.txt
index 06187504..1091ff1 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -2727,6 +2727,7 @@
     method public final android.accessibilityservice.AccessibilityService.MagnificationController getMagnificationController();
     method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
     method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
+    method public final android.accessibilityservice.AccessibilityService.SoftKeyboardController getSoftKeyboardController();
     method public java.util.List<android.view.accessibility.AccessibilityWindowInfo> getWindows();
     method public abstract void onAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     method public final android.os.IBinder onBind(android.content.Intent);
@@ -2785,6 +2786,18 @@
     method public abstract void onMagnificationChanged(android.accessibilityservice.AccessibilityService.MagnificationController, android.graphics.Region, float, float, float);
   }
 
+  public static final class AccessibilityService.SoftKeyboardController {
+    method public void addOnShowModeChangedListener(android.accessibilityservice.AccessibilityService.SoftKeyboardController.OnShowModeChangedListener);
+    method public void addOnShowModeChangedListener(android.accessibilityservice.AccessibilityService.SoftKeyboardController.OnShowModeChangedListener, android.os.Handler);
+    method public int getShowMode();
+    method public boolean removeOnShowModeChangedListener(android.accessibilityservice.AccessibilityService.SoftKeyboardController.OnShowModeChangedListener);
+    method public boolean setShowMode(int);
+  }
+
+  public static abstract interface AccessibilityService.SoftKeyboardController.OnShowModeChangedListener {
+    method public abstract void onShowModeChanged(android.accessibilityservice.AccessibilityService.SoftKeyboardController, int);
+  }
+
   public class AccessibilityServiceInfo implements android.os.Parcelable {
     ctor public AccessibilityServiceInfo();
     method public static java.lang.String capabilityToString(int);
@@ -5964,6 +5977,7 @@
     method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
     method public long getMaximumTimeToLock(android.content.ComponentName);
     method public int getOrganizationColor(android.content.ComponentName);
+    method public java.lang.String getOrganizationName(android.content.ComponentName);
     method public boolean getPackageSuspended(android.content.ComponentName, java.lang.String);
     method public android.app.admin.DevicePolicyManager getParentProfileInstance(android.content.ComponentName);
     method public long getPasswordExpiration(android.content.ComponentName);
@@ -6039,6 +6053,7 @@
     method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
     method public void setMaximumTimeToLock(android.content.ComponentName, long);
     method public void setOrganizationColor(android.content.ComponentName, int);
+    method public void setOrganizationName(android.content.ComponentName, java.lang.String);
     method public boolean setPackageSuspended(android.content.ComponentName, java.lang.String, boolean);
     method public void setPasswordExpirationTimeout(android.content.ComponentName, long);
     method public void setPasswordHistoryLength(android.content.ComponentName, int);
@@ -54068,6 +54083,9 @@
   public abstract class Inherited implements java.lang.annotation.Annotation {
   }
 
+  public abstract class Repeatable implements java.lang.annotation.Annotation {
+  }
+
   public abstract class Retention implements java.lang.annotation.Annotation {
   }
 
diff --git a/api/test-current.txt b/api/test-current.txt
index 684b385..09a9cca 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2625,6 +2625,7 @@
     method public final android.accessibilityservice.AccessibilityService.MagnificationController getMagnificationController();
     method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
     method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
+    method public final android.accessibilityservice.AccessibilityService.SoftKeyboardController getSoftKeyboardController();
     method public java.util.List<android.view.accessibility.AccessibilityWindowInfo> getWindows();
     method public abstract void onAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     method public final android.os.IBinder onBind(android.content.Intent);
@@ -2683,6 +2684,18 @@
     method public abstract void onMagnificationChanged(android.accessibilityservice.AccessibilityService.MagnificationController, android.graphics.Region, float, float, float);
   }
 
+  public static final class AccessibilityService.SoftKeyboardController {
+    method public void addOnShowModeChangedListener(android.accessibilityservice.AccessibilityService.SoftKeyboardController.OnShowModeChangedListener);
+    method public void addOnShowModeChangedListener(android.accessibilityservice.AccessibilityService.SoftKeyboardController.OnShowModeChangedListener, android.os.Handler);
+    method public int getShowMode();
+    method public boolean removeOnShowModeChangedListener(android.accessibilityservice.AccessibilityService.SoftKeyboardController.OnShowModeChangedListener);
+    method public boolean setShowMode(int);
+  }
+
+  public static abstract interface AccessibilityService.SoftKeyboardController.OnShowModeChangedListener {
+    method public abstract void onShowModeChanged(android.accessibilityservice.AccessibilityService.SoftKeyboardController, int);
+  }
+
   public class AccessibilityServiceInfo implements android.os.Parcelable {
     ctor public AccessibilityServiceInfo();
     method public static java.lang.String capabilityToString(int);
@@ -5826,6 +5839,7 @@
     method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
     method public long getMaximumTimeToLock(android.content.ComponentName);
     method public int getOrganizationColor(android.content.ComponentName);
+    method public java.lang.String getOrganizationName(android.content.ComponentName);
     method public boolean getPackageSuspended(android.content.ComponentName, java.lang.String);
     method public android.app.admin.DevicePolicyManager getParentProfileInstance(android.content.ComponentName);
     method public long getPasswordExpiration(android.content.ComponentName);
@@ -5895,6 +5909,7 @@
     method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
     method public void setMaximumTimeToLock(android.content.ComponentName, long);
     method public void setOrganizationColor(android.content.ComponentName, int);
+    method public void setOrganizationName(android.content.ComponentName, java.lang.String);
     method public boolean setPackageSuspended(android.content.ComponentName, java.lang.String, boolean);
     method public void setPasswordExpirationTimeout(android.content.ComponentName, long);
     method public void setPasswordHistoryLength(android.content.ComponentName, int);
@@ -22907,6 +22922,7 @@
     method public void onInputAdded(java.lang.String);
     method public void onInputRemoved(java.lang.String);
     method public void onInputStateChanged(java.lang.String, int);
+    method public void onInputUpdated(java.lang.String);
     method public void onTvInputInfoChanged(android.media.tv.TvInputInfo);
   }
 
@@ -51331,6 +51347,9 @@
   public abstract class Inherited implements java.lang.annotation.Annotation {
   }
 
+  public abstract class Repeatable implements java.lang.annotation.Annotation {
+  }
+
   public abstract class Retention implements java.lang.annotation.Annotation {
   }
 
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index be93926..c96cca2 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -17,6 +17,7 @@
 package android.accessibilityservice;
 
 import android.accessibilityservice.GestureDescription.MotionEventGenerator;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.Service;
@@ -29,6 +30,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
+import android.provider.Settings;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Pair;
@@ -46,6 +48,8 @@
 import com.android.internal.os.HandlerCaller;
 import com.android.internal.os.SomeArgs;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.List;
 
 /**
@@ -363,9 +367,26 @@
         public boolean onKeyEvent(KeyEvent event);
         public void onMagnificationChanged(@NonNull Region region,
                 float scale, float centerX, float centerY);
+        public void onSoftKeyboardShowModeChanged(int showMode);
         public void onPerformGestureResult(int sequence, boolean completedSuccessfully);
     }
 
+    /**
+     * Annotations for Soft Keyboard show modes so tools can catch invalid show modes.
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({SHOW_MODE_AUTO, SHOW_MODE_HIDDEN})
+    public @interface SoftKeyboardShowMode {};
+    /**
+     * @hide
+     */
+    public static final int SHOW_MODE_AUTO = 0;
+    /**
+     * @hide
+     */
+    public static final int SHOW_MODE_HIDDEN = 1;
+
     private int mConnectionId;
 
     private AccessibilityServiceInfo mInfo;
@@ -375,6 +396,7 @@
     private WindowManager mWindowManager;
 
     private MagnificationController mMagnificationController;
+    private SoftKeyboardController mSoftKeyboardController;
 
     private int mGestureStatusCallbackSequence;
 
@@ -563,10 +585,12 @@
      */
     @NonNull
     public final MagnificationController getMagnificationController() {
-        if (mMagnificationController == null) {
-            mMagnificationController = new MagnificationController(this);
+        synchronized (mLock) {
+            if (mMagnificationController == null) {
+                mMagnificationController = new MagnificationController(this, mLock);
+            }
+            return mMagnificationController;
         }
-        return mMagnificationController;
     }
 
     /**
@@ -670,17 +694,21 @@
          * first magnification listener.
          */
         private ArrayMap<OnMagnificationChangedListener, Handler> mListeners;
+        private final Object mLock;
 
-        MagnificationController(@NonNull AccessibilityService service) {
+        MagnificationController(@NonNull AccessibilityService service, @NonNull Object lock) {
             mService = service;
+            mLock = lock;
         }
 
         /**
          * Called when the service is connected.
          */
         void onServiceConnected() {
-            if (mListeners != null && !mListeners.isEmpty()) {
-                setMagnificationCallbackEnabled(true);
+            synchronized (mLock) {
+                if (mListeners != null && !mListeners.isEmpty()) {
+                    setMagnificationCallbackEnabled(true);
+                }
             }
         }
 
@@ -707,17 +735,19 @@
          */
         public void addListener(@NonNull OnMagnificationChangedListener listener,
                 @Nullable Handler handler) {
-            if (mListeners == null) {
-                mListeners = new ArrayMap<>();
-            }
+            synchronized (mLock) {
+                if (mListeners == null) {
+                    mListeners = new ArrayMap<>();
+                }
 
-            final boolean shouldEnableCallback = mListeners.isEmpty();
-            mListeners.put(listener, handler);
+                final boolean shouldEnableCallback = mListeners.isEmpty();
+                mListeners.put(listener, handler);
 
-            if (shouldEnableCallback) {
-                // This may fail if the service is not connected yet, but if we
-                // still have listeners when it connects then we can try again.
-                setMagnificationCallbackEnabled(true);
+                if (shouldEnableCallback) {
+                    // This may fail if the service is not connected yet, but if we
+                    // still have listeners when it connects then we can try again.
+                    setMagnificationCallbackEnabled(true);
+                }
             }
         }
 
@@ -734,19 +764,21 @@
                 return false;
             }
 
-            final int keyIndex = mListeners.indexOfKey(listener);
-            final boolean hasKey = keyIndex >= 0;
-            if (hasKey) {
-                mListeners.removeAt(keyIndex);
-            }
+            synchronized (mLock) {
+                final int keyIndex = mListeners.indexOfKey(listener);
+                final boolean hasKey = keyIndex >= 0;
+                if (hasKey) {
+                    mListeners.removeAt(keyIndex);
+                }
 
-            if (hasKey && mListeners.isEmpty()) {
-                // We just removed the last listener, so we don't need
-                // callbacks from the service anymore.
-                setMagnificationCallbackEnabled(false);
-            }
+                if (hasKey && mListeners.isEmpty()) {
+                    // We just removed the last listener, so we don't need
+                    // callbacks from the service anymore.
+                    setMagnificationCallbackEnabled(false);
+                }
 
-            return hasKey;
+                return hasKey;
+            }
         }
 
         private void setMagnificationCallbackEnabled(boolean enabled) {
@@ -768,17 +800,19 @@
          */
         void dispatchMagnificationChanged(final @NonNull Region region, final float scale,
                 final float centerX, final float centerY) {
-            if (mListeners == null || mListeners.isEmpty()) {
-                Slog.d(LOG_TAG, "Received magnification changed "
-                        + "callback with no listeners registered!");
-                setMagnificationCallbackEnabled(false);
-                return;
-            }
+            final ArrayMap<OnMagnificationChangedListener, Handler> entries;
+            synchronized (mLock) {
+                if (mListeners == null || mListeners.isEmpty()) {
+                    Slog.d(LOG_TAG, "Received magnification changed "
+                            + "callback with no listeners registered!");
+                    setMagnificationCallbackEnabled(false);
+                    return;
+                }
 
-            // Listeners may remove themselves. Perform a shallow copy to avoid
-            // concurrent modification.
-            final ArrayMap<OnMagnificationChangedListener, Handler> entries =
-                    new ArrayMap<>(mListeners);
+                // Listeners may remove themselves. Perform a shallow copy to avoid concurrent
+                // modification.
+                entries = new ArrayMap<>(mListeners);
+            }
 
             for (int i = 0, count = entries.size(); i < count; i++) {
                 final OnMagnificationChangedListener listener = entries.keyAt(i);
@@ -1011,6 +1045,243 @@
     }
 
     /**
+     * Returns the soft keyboard controller, which may be used to query and modify the soft keyboard
+     * show mode.
+     *
+     * @return the soft keyboard controller
+     */
+    @NonNull
+    public final SoftKeyboardController getSoftKeyboardController() {
+        synchronized (mLock) {
+            if (mSoftKeyboardController == null) {
+                mSoftKeyboardController = new SoftKeyboardController(this, mLock);
+            }
+            return mSoftKeyboardController;
+        }
+    }
+
+    private void onSoftKeyboardShowModeChanged(int showMode) {
+        if (mSoftKeyboardController != null) {
+            mSoftKeyboardController.dispatchSoftKeyboardShowModeChanged(showMode);
+        }
+    }
+
+    /**
+     * Used to control and query the soft keyboard show mode.
+     */
+    public static final class SoftKeyboardController {
+        private final AccessibilityService mService;
+
+        /**
+         * Map of listeners to their handlers. Lazily created when adding the first
+         * soft keyboard change listener.
+         */
+        private ArrayMap<OnShowModeChangedListener, Handler> mListeners;
+        private final Object mLock;
+
+        SoftKeyboardController(@NonNull AccessibilityService service, @NonNull Object lock) {
+            mService = service;
+            mLock = lock;
+        }
+
+        /**
+         * Called when the service is connected.
+         */
+        void onServiceConnected() {
+            synchronized(mLock) {
+                if (mListeners != null && !mListeners.isEmpty()) {
+                    setSoftKeyboardCallbackEnabled(true);
+                }
+            }
+        }
+
+        /**
+         * Adds the specified change listener to the list of show mode change listeners. The
+         * callback will occur on the service's main thread. Listener is not called on registration.
+         */
+        public void addOnShowModeChangedListener(@NonNull OnShowModeChangedListener listener) {
+            addOnShowModeChangedListener(listener, null);
+        }
+
+        /**
+         * Adds the specified change listener to the list of soft keyboard show mode change
+         * listeners. The callback will occur on the specified {@link Handler}'s thread, or on the
+         * services's main thread if the handler is {@code null}.
+         *
+         * @param listener the listener to add, must be non-null
+         * @param handler the handler on which to callback should execute, or {@code null} to
+         *        execute on the service's main thread
+         */
+        public void addOnShowModeChangedListener(@NonNull OnShowModeChangedListener listener,
+                @Nullable Handler handler) {
+            synchronized (mLock) {
+                if (mListeners == null) {
+                    mListeners = new ArrayMap<>();
+                }
+
+                final boolean shouldEnableCallback = mListeners.isEmpty();
+                mListeners.put(listener, handler);
+
+                if (shouldEnableCallback) {
+                    // This may fail if the service is not connected yet, but if we still have
+                    // listeners when it connects, we can try again.
+                    setSoftKeyboardCallbackEnabled(true);
+                }
+            }
+        }
+
+        /**
+         * Removes all instances of the specified change listener from teh list of magnification
+         * change listeners.
+         *
+         * @param listener the listener to remove, must be non-null
+         * @return {@code true} if at least one instance of the listener was removed
+         */
+        public boolean removeOnShowModeChangedListener(@NonNull OnShowModeChangedListener listener) {
+            if (mListeners == null) {
+                return false;
+            }
+
+            synchronized (mLock) {
+                final int keyIndex = mListeners.indexOfKey(listener);
+                final boolean hasKey = keyIndex >= 0;
+                if (hasKey) {
+                    mListeners.removeAt(keyIndex);
+                }
+
+                if (hasKey && mListeners.isEmpty()) {
+                    // We just removed the last listener, so we don't need callbacks from the
+                    // service anymore.
+                    setSoftKeyboardCallbackEnabled(false);
+                }
+
+                return hasKey;
+            }
+        }
+
+        private void setSoftKeyboardCallbackEnabled(boolean enabled) {
+            final IAccessibilityServiceConnection connection =
+                    AccessibilityInteractionClient.getInstance().getConnection(
+                            mService.mConnectionId);
+            if (connection != null) {
+                try {
+                    connection.setSoftKeyboardCallbackEnabled(enabled);
+                } catch (RemoteException re) {
+                    throw new RuntimeException(re);
+                }
+            }
+        }
+
+        /**
+         * Dispatches the soft keyboard show mode change to any registered listeners. This should
+         * be called on the service's main thread.
+         */
+        void dispatchSoftKeyboardShowModeChanged(final int showMode) {
+            final ArrayMap<OnShowModeChangedListener, Handler> entries;
+            synchronized (mLock) {
+                if (mListeners == null || mListeners.isEmpty()) {
+                    Slog.d(LOG_TAG, "Received soft keyboard show mode changed callback"
+                            + " with no listeners registered!");
+                    setSoftKeyboardCallbackEnabled(false);
+                    return;
+                }
+
+                // Listeners may remove themselves. Perform a shallow copy to avoid concurrent
+                // modification.
+                entries = new ArrayMap<>(mListeners);
+            }
+
+            for (int i = 0, count = entries.size(); i < count; i++) {
+                final OnShowModeChangedListener listener = entries.keyAt(i);
+                final Handler handler = entries.valueAt(i);
+                if (handler != null) {
+                    handler.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            listener.onShowModeChanged(SoftKeyboardController.this, showMode);
+                        }
+                    });
+                } else {
+                    // We're already on the main thread, just run the listener.
+                    listener.onShowModeChanged(this, showMode);
+                }
+            }
+        }
+
+        /**
+         * Returns the show mode of the soft keyboard. The default show mode is
+         * {@code Settings.Secure.SHOW_MODE_AUTO}, where the soft keyboard is shown when a text
+         * input field is focused. An AccessibilityService can also request the show mode
+         * {@code Settings.Secure.SHOW_MODE_HIDDEN}, where the soft keyboard is never shown.
+         *
+         * @return the current soft keyboard show mode
+         *
+         * @see Settings#Secure#SHOW_MODE_AUTO
+         * @see Settings#Secure#SHOW_MODE_HIDDEN
+         */
+        @SoftKeyboardShowMode
+        public int getShowMode() {
+           try {
+               return Settings.Secure.getInt(mService.getContentResolver(),
+                       Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE);
+           } catch (Settings.SettingNotFoundException e) {
+               Log.v(LOG_TAG, "Failed to obtain the soft keyboard mode", e);
+               // The settings hasn't been changed yet, so it's value is null. Return the default.
+               return 0;
+           }
+        }
+
+        /**
+         * Sets the soft keyboard show mode. The default show mode is
+         * {@code Settings.Secure.SHOW_MODE_AUTO}, where the soft keyboard is shown when a text
+         * input field is focused. An AccessibilityService can also request the show mode
+         * {@code Settings.Secure.SHOW_MODE_HIDDEN}, where the soft keyboard is never shown. The
+         * The lastto this method will be honored, regardless of any previous calls (including those
+         * made by other AccessibilityServices).
+         * <p>
+         * <strong>Note:</strong> If the service is not yet conected (e.g.
+         * {@link AccessibilityService#onServiceConnected()} has not yet been called) or the
+         * service has been disconnected, this method will hav no effect and return {@code false}.
+         *
+         * @param showMode the new show mode for the soft keyboard
+         * @return {@code true} on success
+         *
+         * @see Settings#Secure#SHOW_MODE_AUTO
+         * @see Settings#Secure#SHOW_MODE_HIDDEN
+         */
+        public boolean setShowMode(@SoftKeyboardShowMode int showMode) {
+           final IAccessibilityServiceConnection connection =
+                   AccessibilityInteractionClient.getInstance().getConnection(
+                           mService.mConnectionId);
+           if (connection != null) {
+               try {
+                   return connection.setSoftKeyboardShowMode(showMode);
+               } catch (RemoteException re) {
+                   Log.w(LOG_TAG, "Falied to set soft keyboard behavior", re);
+               }
+           }
+           return false;
+        }
+
+        /**
+         * Listener for changes in the soft keyboard show mode.
+         */
+        public interface OnShowModeChangedListener {
+           /**
+            * Called when the soft keyboard behavior changes. The default show mode is
+            * {@code Settings.Secure.SHOW_MODE_AUTO}, where the soft keyboard is shown when a text
+            * input field is focused. An AccessibilityService can also request the show mode
+            * {@code Settings.Secure.SHOW_MODE_HIDDEN}, where the soft keyboard is never shown.
+            *
+            * @param controller the soft keyboard controller
+            * @param showMode the current soft keyboard show mode
+            */
+            void onShowModeChanged(@NonNull SoftKeyboardController controller,
+                    @SoftKeyboardShowMode int showMode);
+        }
+    }
+
+    /**
      * Performs a global action. Such an action can be performed
      * at any moment regardless of the current application or user
      * location in that application. For example going back, going
@@ -1184,6 +1455,11 @@
             }
 
             @Override
+            public void onSoftKeyboardShowModeChanged(int showMode) {
+                AccessibilityService.this.onSoftKeyboardShowModeChanged(showMode);
+            }
+
+            @Override
             public void onPerformGestureResult(int sequence, boolean completedSuccessfully) {
                 AccessibilityService.this.onPerformGestureResult(sequence, completedSuccessfully);
             }
@@ -1205,7 +1481,8 @@
         private static final int DO_CLEAR_ACCESSIBILITY_CACHE = 5;
         private static final int DO_ON_KEY_EVENT = 6;
         private static final int DO_ON_MAGNIFICATION_CHANGED = 7;
-        private static final int DO_GESTURE_COMPLETE = 8;
+        private static final int DO_ON_SOFT_KEYBOARD_SHOW_MODE_CHANGED = 8;
+        private static final int DO_GESTURE_COMPLETE = 9;
 
         private final HandlerCaller mCaller;
 
@@ -1264,6 +1541,12 @@
             mCaller.sendMessage(message);
         }
 
+        public void onSoftKeyboardShowModeChanged(int showMode) {
+          final Message message =
+                  mCaller.obtainMessageI(DO_ON_SOFT_KEYBOARD_SHOW_MODE_CHANGED, showMode);
+          mCaller.sendMessage(message);
+        }
+
         public void onPerformGestureResult(int sequence, boolean successfully) {
             Message message = mCaller.obtainMessageII(DO_GESTURE_COMPLETE, sequence,
                     successfully ? 1 : 0);
@@ -1354,6 +1637,11 @@
                     mCallback.onMagnificationChanged(region, scale, centerX, centerY);
                 } return;
 
+                case DO_ON_SOFT_KEYBOARD_SHOW_MODE_CHANGED: {
+                    final int showMode = (int) message.arg1;
+                    mCallback.onSoftKeyboardShowModeChanged(showMode);
+                } return;
+
                 case DO_GESTURE_COMPLETE: {
                     final boolean successfully = message.arg2 == 1;
                     mCallback.onPerformGestureResult(message.arg1, successfully);
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
index 6280542..ef05d6f 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
@@ -43,5 +43,7 @@
 
     void onMagnificationChanged(in Region region, float scale, float centerX, float centerY);
 
+    void onSoftKeyboardShowModeChanged(int showMode);
+
     void onPerformGestureResult(int sequence, boolean completedSuccessfully);
 }
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index e58ef2f..d5e8a11 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -84,5 +84,9 @@
 
     void setMagnificationCallbackEnabled(boolean enabled);
 
+    boolean setSoftKeyboardShowMode(int showMode);
+
+    void setSoftKeyboardCallbackEnabled(boolean enabled);
+
     void sendMotionEvents(int sequence, in ParceledListSlice events);
 }
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 79d383c..5ec59b4 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -1088,6 +1088,11 @@
                 }
 
                 @Override
+                public void onSoftKeyboardShowModeChanged(int showMode) {
+                    /* do nothing */
+                }
+
+                @Override
                 public void onPerformGestureResult(int sequence, boolean completedSuccessfully) {
                     /* do nothing */
                 }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index e4e97a1..c79c407 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -3346,6 +3346,10 @@
      * <p>If the device owner information contains only whitespaces then the message on the lock
      * screen will be blank and the user will not be allowed to change it.
      *
+     * <p>If the device owner information needs to be localized, it is the responsibility of the
+     * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast
+     * and set a new version of this string accordingly.
+     *
      * @param admin The name of the admin component to check.
      * @param info Device owner information which will be displayed instead of the user
      * owner info.
@@ -5211,6 +5215,10 @@
      *  for support."
      * If the message is longer than 200 characters it may be truncated.
      *
+     * <p>If the short support message needs to be localized, it is the responsibility of the
+     * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast
+     * and set a new version of this string accordingly.
+     *
      * @see #setLongSupportMessage
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
@@ -5250,6 +5258,10 @@
      * Called by a device admin to set the long support message. This will
      * be displayed to the user in the device administators settings screen.
      *
+     * <p>If the long support message needs to be localized, it is the responsibility of the
+     * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast
+     * and set a new version of this string accordingly.
+     *
      * @see #setShortSupportMessage
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
@@ -5414,6 +5426,58 @@
     }
 
     /**
+     * Called by a profile owner of a managed profile to set the name of the organization under
+     * management.
+     *
+     * <p>If the organization name needs to be localized, it is the responsibility of the
+     * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast
+     * and set a new version of this string accordingly.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param title The organization name or {@code null} to clear a previously set name.
+     */
+    public void setOrganizationName(@NonNull ComponentName admin, @Nullable String title) {
+        try {
+            mService.setOrganizationName(admin, title);
+        } catch (RemoteException re) {
+            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE);
+        }
+    }
+
+    /**
+     * Called by a profile owner of a managed profile to retrieve the name of the organization
+     * under management.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @return The organization name or {@code null} if none is set.
+     */
+    public String getOrganizationName(@NonNull ComponentName admin) {
+        try {
+            return mService.getOrganizationName(admin);
+        } catch (RemoteException re) {
+            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE);
+            return null;
+        }
+    }
+
+    /**
+     * Retrieve the default title message used in the confirm credentials screen for a given user.
+     *
+     * @param userHandle The user id of the user we're interested in.
+     * @return The organization name or {@code null} if none is set.
+     *
+     * @hide
+     */
+    public String getOrganizationNameForUser(int userHandle) {
+        try {
+            return mService.getOrganizationNameForUser(userHandle);
+        } catch (RemoteException re) {
+            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE);
+            return null;
+        }
+    }
+
+    /**
      * @return the {@link UserProvisioningState} for the current user - for unmanaged users will
      *         return {@link #STATE_USER_UNMANAGED}
      * @hide
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 6333013..37d13e5 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -276,6 +276,10 @@
     int getOrganizationColor(in ComponentName admin);
     int getOrganizationColorForUser(int userHandle);
 
+    void setOrganizationName(in ComponentName admin, in String title);
+    String getOrganizationName(in ComponentName admin);
+    String getOrganizationNameForUser(int userHandle);
+
     int getUserProvisioningState();
     void setUserProvisioningState(int state, int userHandle);
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index c9c0cde..6e92ec1 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4856,6 +4856,29 @@
                 "accessibility_display_magnification_auto_update";
 
         /**
+         * Setting that specifies what mode the soft keyboard is in (default or hidden). Can be
+         * modified from an AccessibilityService using the SoftKeyboardController.
+         *
+         * @hide
+         */
+        public static final String ACCESSIBILITY_SOFT_KEYBOARD_MODE =
+                "accessibility_soft_keyboard_mode";
+
+        /**
+         * Default soft keyboard behavior.
+         *
+         * @hide
+         */
+        public static final int SHOW_MODE_AUTO = 0;
+
+        /**
+         * Soft keyboard is never shown.
+         *
+         * @hide
+         */
+        public static final int SHOW_MODE_HIDDEN = 1;
+
+        /**
          * Setting that specifies whether timed text (captions) should be
          * displayed in video content. Text display properties are controlled by
          * the following settings:
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index df84970..7b6fa6d 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -565,6 +565,12 @@
     private Runnable mTouchModeReset;
 
     /**
+     * Whether the most recent touch event stream resulted in a successful
+     * long-press action. This is reset on TOUCH_DOWN.
+     */
+    private boolean mHasPerformedLongPress;
+
+    /**
      * This view is in transcript mode -- it shows the bottom of the list when the data
      * changes
      */
@@ -3108,7 +3114,9 @@
                         handled = performLongPress(child, longPressPosition, longPressId);
                     }
                 }
+
                 if (handled) {
+                    mHasPerformedLongPress = true;
                     mTouchMode = TOUCH_MODE_REST;
                     setPressed(false);
                     child.setPressed(false);
@@ -3811,6 +3819,7 @@
     }
 
     private void onTouchDown(MotionEvent ev) {
+        mHasPerformedLongPress = false;
         mActivePointerId = ev.getPointerId(0);
 
         if (mTouchMode == TOUCH_MODE_OVERFLING) {
@@ -3874,6 +3883,11 @@
     }
 
     private void onTouchMove(MotionEvent ev, MotionEvent vtev) {
+        if (mHasPerformedLongPress) {
+            // Consume all move events following a successful long press.
+            return;
+        }
+
         int pointerIndex = ev.findPointerIndex(mActivePointerId);
         if (pointerIndex == -1) {
             pointerIndex = 0;
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 617d3dd..3a61fcd 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -2872,6 +2872,7 @@
         protected PopupWindow mPopupWindow;
         protected ViewGroup mContentView;
         int mPositionX, mPositionY;
+        int mClippingLimitLeft, mClippingLimitRight;
 
         protected abstract void createPopupWindow();
         protected abstract void initContentView();
@@ -2939,8 +2940,9 @@
             // Horizontal clipping
             final DisplayMetrics displayMetrics = mTextView.getResources().getDisplayMetrics();
             final int width = mContentView.getMeasuredWidth();
-            positionX = Math.min(displayMetrics.widthPixels - width, positionX);
-            positionX = Math.max(0, positionX);
+            positionX = Math.min(
+                    displayMetrics.widthPixels - width + mClippingLimitRight, positionX);
+            positionX = Math.max(-mClippingLimitLeft, positionX);
 
             if (isShowing()) {
                 mPopupWindow.update(positionX, positionY, -1, -1);
@@ -3118,6 +3120,8 @@
         private TextView mAddToDictionaryButton;
         private TextView mDeleteButton;
         private SuggestionSpan mMisspelledSpan;
+        private int mContainerMarginWidth;
+        private int mContainerMarginTop;
 
         private class CustomPopupWindow extends PopupWindow {
             @Override
@@ -3155,10 +3159,20 @@
         protected void initContentView() {
             final LayoutInflater inflater = (LayoutInflater) mTextView.getContext().
                     getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-            final LinearLayout linearLayout = (LinearLayout) inflater.inflate(
+            final ViewGroup relativeLayout = (ViewGroup) inflater.inflate(
                     mTextView.mTextEditSuggestionContainerLayout, null);
 
-            final ListView suggestionListView = (ListView) linearLayout.findViewById(
+            final LinearLayout suggestionWindowContainer =
+                    (LinearLayout) relativeLayout.findViewById(
+                            com.android.internal.R.id.suggestionWindowContainer);
+            ViewGroup.MarginLayoutParams lp =
+                    (ViewGroup.MarginLayoutParams) suggestionWindowContainer.getLayoutParams();
+            mContainerMarginWidth = lp.leftMargin + lp.rightMargin;
+            mContainerMarginTop = lp.topMargin;
+            mClippingLimitLeft = lp.leftMargin;
+            mClippingLimitRight = lp.rightMargin;
+
+            final ListView suggestionListView = (ListView) relativeLayout.findViewById(
                     com.android.internal.R.id.suggestionContainer);
 
             mSuggestionsAdapter = new SuggestionAdapter();
@@ -3171,9 +3185,9 @@
                 mSuggestionInfos[i] = new SuggestionInfo();
             }
 
-            mContentView = linearLayout;
+            mContentView = relativeLayout;
 
-            mAddToDictionaryButton = (TextView) linearLayout.findViewById(
+            mAddToDictionaryButton = (TextView) relativeLayout.findViewById(
                     com.android.internal.R.id.addToDictionaryButton);
             mAddToDictionaryButton.setOnClickListener(new View.OnClickListener() {
                 public void onClick(View v) {
@@ -3197,7 +3211,7 @@
                 }
             });
 
-            mDeleteButton = (TextView) linearLayout.findViewById(
+            mDeleteButton = (TextView) relativeLayout.findViewById(
                     com.android.internal.R.id.deleteButton);
             mDeleteButton.setOnClickListener(new View.OnClickListener() {
                 public void onClick(View v) {
@@ -3306,6 +3320,8 @@
             mDeleteButton.measure(horizontalMeasure, verticalMeasure);
             width = Math.max(width, mDeleteButton.getMeasuredWidth());
 
+            width += mContainerMarginWidth;
+
             // Enforce the width based on actual text widths
             mContentView.measure(
                     View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
@@ -3327,7 +3343,7 @@
 
         @Override
         protected int getVerticalLocalPosition(int line) {
-            return mTextView.getLayout().getLineBottom(line);
+            return mTextView.getLayout().getLineBottom(line) - mContainerMarginTop;
         }
 
         @Override
diff --git a/core/java/com/android/internal/app/LocaleHelper.java b/core/java/com/android/internal/app/LocaleHelper.java
index 71c2c21..c7459d7 100644
--- a/core/java/com/android/internal/app/LocaleHelper.java
+++ b/core/java/com/android/internal/app/LocaleHelper.java
@@ -17,6 +17,7 @@
 package com.android.internal.app;
 
 import android.icu.util.ULocale;
+import android.icu.text.ListFormatter;
 import android.util.LocaleList;
 
 import java.text.Collator;
@@ -145,20 +146,16 @@
      * @return the locale aware list of locale names
      */
     public static String getDisplayLocaleList(LocaleList locales, Locale displayLocale) {
-        final StringBuilder result = new StringBuilder();
-
         final Locale dispLocale = displayLocale == null ? Locale.getDefault() : displayLocale;
+
         int localeCount = locales.size();
+        final String[] localeNames = new String[localeCount];
         for (int i = 0; i < localeCount; i++) {
-            Locale locale = locales.get(i);
-            result.append(LocaleHelper.getDisplayName(locale, dispLocale, false));
-            // TODO: language aware list formatter. ICU has one.
-            if (i < localeCount - 1) {
-                result.append(", ");
-            }
+            localeNames[i] = LocaleHelper.getDisplayName(locales.get(i), dispLocale, false);
         }
 
-        return result.toString();
+        ListFormatter lfn = ListFormatter.getInstance(dispLocale);
+        return lfn.format(localeNames);
     }
 
     /**
diff --git a/core/java/com/android/internal/app/UnlaunchableAppActivity.java b/core/java/com/android/internal/app/UnlaunchableAppActivity.java
index aada6e3..29190f9 100644
--- a/core/java/com/android/internal/app/UnlaunchableAppActivity.java
+++ b/core/java/com/android/internal/app/UnlaunchableAppActivity.java
@@ -32,6 +32,7 @@
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -69,12 +70,11 @@
         }
 
         String dialogTitle;
-        String dialogMessage;
+        String dialogMessage = null;
         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) {
-            PackageManager pm = getPackageManager();
             DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(
                     Context.DEVICE_POLICY_SERVICE);
             String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
@@ -91,12 +91,19 @@
             }
             dialogTitle = String.format(getResources().getString(R.string.suspended_package_title),
                     packageLabel);
-            dialogMessage = dpm.getShortSupportMessageForUser(dpm.getProfileOwnerAsUser(mUserId),
-                    mUserId);
-            if (dialogMessage == null) {
-                dialogMessage = String.format(
-                        getResources().getString(R.string.suspended_package_message),
-                        dpm.getProfileOwnerNameAsUser(mUserId));
+            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);
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index 976ef4b..480d806 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -920,14 +920,14 @@
                     mOverflowPanel.setY(mOverflowButtonSize.getHeight());  // align bottom
                 }
             } else {
-                if (hasOverflow()) {
-                    // overflow not open. Set closed state.
-                    final Size containerSize = mMainPanelSize;
-                    setSize(mContentContainer, containerSize);
-                    mMainPanel.setAlpha(1);
-                    mOverflowPanel.setAlpha(0);
-                    mOverflowButton.setImageDrawable(mOverflow);
+                // Overflow not open. Set closed state.
+                final Size containerSize = mMainPanelSize;
+                setSize(mContentContainer, containerSize);
+                mMainPanel.setAlpha(1);
+                mOverflowPanel.setAlpha(0);
+                mOverflowButton.setImageDrawable(mOverflow);
 
+                if (hasOverflow()) {
                     // Update x-coordinates depending on RTL state.
                     if (isRTL()) {
                         mContentContainer.setX(mMarginHorizontal);  // align left
@@ -960,8 +960,11 @@
                         mOverflowPanel.setY(mOverflowButtonSize.getHeight());  // align bottom
                     }
                 } else {
-                    mContentContainer.setX(mMarginHorizontal);
-                    mContentContainer.setY(mMarginVertical);
+                    // No overflow.
+                    mContentContainer.setX(mMarginHorizontal);  // align left
+                    mContentContainer.setY(mMarginVertical);  // align top
+                    mMainPanel.setX(0);  // align left
+                    mMainPanel.setY(0);  // align top
                 }
             }
         }
@@ -1092,6 +1095,7 @@
             final LinkedList<MenuItem> remainingMenuItems = new LinkedList<MenuItem>(menuItems);
 
             mMainPanel.removeAllViews();
+            mMainPanel.setPaddingRelative(0, 0, 0, 0);
 
             boolean isFirstItem = true;
             while (!remainingMenuItems.isEmpty()) {
@@ -1302,7 +1306,6 @@
             overflowButton.setOnClickListener(new View.OnClickListener() {
                 @Override
                 public void onClick(View v) {
-                    final Drawable drawable = overflowButton.getDrawable();
                     if (mIsOverflowOpen) {
                         overflowButton.setImageDrawable(mToOverflow);
                         mToOverflow.start();
@@ -1599,6 +1602,8 @@
     private static ViewGroup createContentContainer(Context context) {
         ViewGroup contentContainer = (ViewGroup) LayoutInflater.from(context)
                 .inflate(R.layout.floating_popup_container, null);
+        contentContainer.setLayoutParams(new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
         contentContainer.setTag(FLOATING_TOOLBAR_TAG);
         return contentContainer;
     }
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 3f468ac..ba456f9 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -17,7 +17,6 @@
 package com.android.internal.widget;
 
 import android.annotation.IntDef;
-import android.app.ActivityManager;
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.IStrongAuthTracker;
 import android.app.trust.TrustManager;
@@ -503,10 +502,9 @@
         if (userHandle == UserHandle.USER_SYSTEM) {
             // Set the encryption password to default.
             updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
+            setCredentialRequiredToDecrypt(false);
         }
 
-        setCredentialRequiredToDecrypt(false);
-
         getDevicePolicyManager().setActivePasswordState(
                 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0, userHandle);
 
@@ -1340,9 +1338,9 @@
     }
 
     public void setCredentialRequiredToDecrypt(boolean required) {
-        if (ActivityManager.getCurrentUser() != UserHandle.USER_SYSTEM) {
-            Log.w(TAG, "Only device owner may call setCredentialRequiredForDecrypt()");
-            return;
+        if (!(getUserManager().isSystemUser() || getUserManager().isPrimaryUser())) {
+            throw new IllegalStateException(
+                    "Only the system or primary user may call setCredentialRequiredForDecrypt()");
         }
 
         if (isDeviceEncryptionEnabled()){
diff --git a/core/res/res/layout/text_edit_suggestion_container.xml b/core/res/res/layout/text_edit_suggestion_container.xml
index fe02d4e..17e93d0 100644
--- a/core/res/res/layout/text_edit_suggestion_container.xml
+++ b/core/res/res/layout/text_edit_suggestion_container.xml
@@ -14,32 +14,41 @@
      limitations under the License.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
-    android:background="@drawable/text_edit_suggestions_window"
-    android:dropDownSelector="@drawable/list_selector_background"
-    android:divider="@null">
-    <ListView
-        android:id="@+id/suggestionContainer"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:divider="?android:attr/dividerHorizontal">
-        <!-- Suggestions will be added here. -->
-    </ListView>
-
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
     <LinearLayout
-        android:layout_width="match_parent"
+        android:id="@+id/suggestionWindowContainer"
+        android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:orientation="vertical"
-        android:divider="?android:attr/dividerHorizontal"
-        android:showDividers="middle">
-        <TextView
-            style="@android:style/Widget.Holo.SuggestionButton"
-            android:id="@+id/addToDictionaryButton"
-            android:text="@string/addToDictionary" />
-        <TextView
-            style="@android:style/Widget.Holo.SuggestionButton"
-            android:id="@+id/deleteButton"
-            android:text="@string/deleteText" />
+        android:elevation="2dp"
+        android:layout_margin="20dp"
+        android:background="@drawable/text_edit_suggestions_window"
+        android:dropDownSelector="@drawable/list_selector_background"
+        android:divider="@null">
+        <ListView
+            android:id="@+id/suggestionContainer"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:divider="?android:attr/dividerHorizontal">
+            <!-- Suggestions will be added here. -->
+        </ListView>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"
+            android:divider="?android:attr/dividerHorizontal"
+            android:showDividers="middle">
+            <TextView
+                style="@android:style/Widget.Holo.SuggestionButton"
+                android:id="@+id/addToDictionaryButton"
+                android:text="@string/addToDictionary" />
+            <TextView
+                style="@android:style/Widget.Holo.SuggestionButton"
+                android:id="@+id/deleteButton"
+                android:text="@string/deleteText" />
+        </LinearLayout>
     </LinearLayout>
-</LinearLayout>
+</RelativeLayout>
diff --git a/core/res/res/layout/text_edit_suggestion_container_material.xml b/core/res/res/layout/text_edit_suggestion_container_material.xml
index 62e315b4..7826803 100644
--- a/core/res/res/layout/text_edit_suggestion_container_material.xml
+++ b/core/res/res/layout/text_edit_suggestion_container_material.xml
@@ -16,29 +16,38 @@
 
 <!-- Background of the popup window is the same as the one of the floating toolbar.
      Use floating toolbar background style. -->
-<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
-    android:background="?android:attr/floatingToolbarPopupBackgroundDrawable"
-    android:divider="?android:attr/listDivider"
-    android:showDividers="middle" >
-    <ListView
-        android:id="@+id/suggestionContainer"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:paddingTop="8dip"
-        android:paddingBottom="0dip"
-        android:divider="@null" />
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
     <LinearLayout
-        android:layout_width="match_parent"
+        android:id="@+id/suggestionWindowContainer"
+        android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:orientation="vertical">
-          <TextView
-              style="@android:style/Widget.Material.SuggestionButton"
-              android:id="@+id/addToDictionaryButton"
-              android:text="@string/addToDictionary" />
-          <TextView
-              style="@android:style/Widget.Material.SuggestionButton"
-              android:id="@+id/deleteButton"
-              android:text="@string/deleteText" />
+        android:background="?android:attr/floatingToolbarPopupBackgroundDrawable"
+        android:elevation="2dp"
+        android:layout_margin="20dp"
+        android:orientation="vertical"
+        android:divider="?android:attr/listDivider"
+        android:showDividers="middle">
+        <ListView
+            android:id="@+id/suggestionContainer"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingTop="8dp"
+            android:paddingBottom="0dp"
+            android:divider="@null" />
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+            <TextView
+                style="@android:style/Widget.Material.SuggestionButton"
+                android:id="@+id/addToDictionaryButton"
+                android:text="@string/addToDictionary" />
+            <TextView
+                style="@android:style/Widget.Material.SuggestionButton"
+                android:id="@+id/deleteButton"
+                android:text="@string/deleteText" />
+        </LinearLayout>
     </LinearLayout>
-</LinearLayout>
+</RelativeLayout>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1af5059..74ca8a5 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2388,6 +2388,7 @@
   <java-symbol type="color" name="system_bar_background_semi_transparent" />
 
   <!-- EditText suggestion popup. -->
+  <java-symbol type="id" name="suggestionWindowContainer" />
   <java-symbol type="id" name="suggestionContainer" />
   <java-symbol type="id" name="addToDictionaryButton" />
   <java-symbol type="id" name="deleteButton" />
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index 869512d..93e6dac 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -473,8 +473,9 @@
         // the service will be told when we connect.
         if (mState == CONNECT_STATE_CONNECTED) {
             try {
-                // NOTE: In order not to break the behavior of the support library, call
-                // addSubscription instead of addSubscriptionWithOptions when the options are null.
+                // NOTE: Do not call addSubscriptionWithOptions when options are null. Otherwise,
+                // it will break the action of support library which expects addSubscription will
+                // be called when options are null.
                 if (options == null) {
                     mServiceBinder.addSubscription(parentId, mServiceCallbacks);
                 } else {
@@ -500,9 +501,9 @@
         // Tell the service if necessary.
         if (sub != null && sub.remove(options) && mState == CONNECT_STATE_CONNECTED) {
             try {
-                // NOTE: In order not to break the behavior of the support library, call
-                // removeSubscription instead of removeSubscriptionWithOptions when the options
-                // are null.
+                // NOTE: Do not call removeSubscriptionWithOptions when options are null. Otherwise,
+                // it will break the action of support library which expects removeSubscription will
+                // be called when options are null.
                 if (options == null) {
                     mServiceBinder.removeSubscription(parentId, mServiceCallbacks);
                 } else {
@@ -572,9 +573,9 @@
                     Subscription sub = subscriptionEntry.getValue();
                     for (Bundle options : sub.getOptionsList()) {
                         try {
-                            // NOTE: In order not to break the behavior of the support library,
-                            // call addSubscription instead of addSubscriptionWithOptions when
-                            // the options are null.
+                            // NOTE: Do not call addSubscriptionWithOptions when options are null.
+                            // Otherwise, it will break the action of support library which expects
+                            // addSubscription will be called when options are null.
                             if (options == null) {
                                 mServiceBinder.addSubscription(id, mServiceCallbacks);
                             } else {
@@ -1034,7 +1035,7 @@
          * are the initial data as requested.
          */
         @Override
-        public void onConnect(final String root, final MediaSession.Token session,
+        public void onConnect(String root, MediaSession.Token session,
                 final Bundle extras) {
             MediaBrowser mediaBrowser = mMediaBrowser.get();
             if (mediaBrowser != null) {
@@ -1054,7 +1055,12 @@
         }
 
         @Override
-        public void onLoadChildren(final String parentId, final ParceledListSlice list,
+        public void onLoadChildren(String parentId, ParceledListSlice list) {
+            onLoadChildrenWithOptions(parentId, list, null);
+        }
+
+        @Override
+        public void onLoadChildrenWithOptions(String parentId, ParceledListSlice list,
                 final Bundle options) {
             MediaBrowser mediaBrowser = mMediaBrowser.get();
             if (mediaBrowser != null) {
diff --git a/media/java/android/media/tv/ITvInputServiceCallback.aidl b/media/java/android/media/tv/ITvInputServiceCallback.aidl
index 74ab562..4fdc102 100644
--- a/media/java/android/media/tv/ITvInputServiceCallback.aidl
+++ b/media/java/android/media/tv/ITvInputServiceCallback.aidl
@@ -24,7 +24,7 @@
  * @hide
  */
 oneway interface ITvInputServiceCallback {
-    void addHardwareTvInput(in int deviceId, in TvInputInfo inputInfo);
-    void addHdmiTvInput(in int id, in TvInputInfo inputInfo);
-    void removeTvInput(in String inputId);
+    void addHardwareInput(in int deviceId, in TvInputInfo inputInfo);
+    void addHdmiInput(in int id, in TvInputInfo inputInfo);
+    void removeHardwareInput(in String inputId);
 }
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 86bded9..1cd1958 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -719,9 +719,7 @@
          * the media on which a newer version of the package exists becomes available/unavailable.
          *
          * @param inputId The ID of the TV input.
-         * @hide
          */
-        @SystemApi
         public void onInputUpdated(String inputId) {
         }
 
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index a2b6346..d48b2c8 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -150,25 +150,25 @@
 
             @Override
             public void notifyHardwareAdded(TvInputHardwareInfo hardwareInfo) {
-                mServiceHandler.obtainMessage(ServiceHandler.DO_ADD_HARDWARE_TV_INPUT,
+                mServiceHandler.obtainMessage(ServiceHandler.DO_ADD_HARDWARE_INPUT,
                         hardwareInfo).sendToTarget();
             }
 
             @Override
             public void notifyHardwareRemoved(TvInputHardwareInfo hardwareInfo) {
-                mServiceHandler.obtainMessage(ServiceHandler.DO_REMOVE_HARDWARE_TV_INPUT,
+                mServiceHandler.obtainMessage(ServiceHandler.DO_REMOVE_HARDWARE_INPUT,
                         hardwareInfo).sendToTarget();
             }
 
             @Override
             public void notifyHdmiDeviceAdded(HdmiDeviceInfo deviceInfo) {
-                mServiceHandler.obtainMessage(ServiceHandler.DO_ADD_HDMI_TV_INPUT,
+                mServiceHandler.obtainMessage(ServiceHandler.DO_ADD_HDMI_INPUT,
                         deviceInfo).sendToTarget();
             }
 
             @Override
             public void notifyHdmiDeviceRemoved(HdmiDeviceInfo deviceInfo) {
-                mServiceHandler.obtainMessage(ServiceHandler.DO_REMOVE_HDMI_TV_INPUT,
+                mServiceHandler.obtainMessage(ServiceHandler.DO_REMOVE_HDMI_INPUT,
                         deviceInfo).sendToTarget();
             }
         };
@@ -525,7 +525,7 @@
         public void notifyVideoUnavailable(final int reason) {
             if (reason < TvInputManager.VIDEO_UNAVAILABLE_REASON_START
                     || reason > TvInputManager.VIDEO_UNAVAILABLE_REASON_END) {
-                throw new IllegalArgumentException("Unknown reason: " + reason);
+                Log.e(TAG, "notifyVideoUnavailable - unknown reason: " + reason);
             }
             executeOrPostRunnableOnMainThread(new Runnable() {
                 @MainThread
@@ -1934,42 +1934,42 @@
         private static final int DO_CREATE_SESSION = 1;
         private static final int DO_NOTIFY_SESSION_CREATED = 2;
         private static final int DO_CREATE_RECORDING_SESSION = 3;
-        private static final int DO_ADD_HARDWARE_TV_INPUT = 4;
-        private static final int DO_REMOVE_HARDWARE_TV_INPUT = 5;
-        private static final int DO_ADD_HDMI_TV_INPUT = 6;
-        private static final int DO_REMOVE_HDMI_TV_INPUT = 7;
+        private static final int DO_ADD_HARDWARE_INPUT = 4;
+        private static final int DO_REMOVE_HARDWARE_INPUT = 5;
+        private static final int DO_ADD_HDMI_INPUT = 6;
+        private static final int DO_REMOVE_HDMI_INPUT = 7;
 
-        private void broadcastAddHardwareTvInput(int deviceId, TvInputInfo inputInfo) {
+        private void broadcastAddHardwareInput(int deviceId, TvInputInfo inputInfo) {
             int n = mCallbacks.beginBroadcast();
             for (int i = 0; i < n; ++i) {
                 try {
-                    mCallbacks.getBroadcastItem(i).addHardwareTvInput(deviceId, inputInfo);
+                    mCallbacks.getBroadcastItem(i).addHardwareInput(deviceId, inputInfo);
                 } catch (RemoteException e) {
-                    Log.e(TAG, "error in broadcastAddHardwareTvInput", e);
+                    Log.e(TAG, "error in broadcastAddHardwareInput", e);
                 }
             }
             mCallbacks.finishBroadcast();
         }
 
-        private void broadcastAddHdmiTvInput(int id, TvInputInfo inputInfo) {
+        private void broadcastAddHdmiInput(int id, TvInputInfo inputInfo) {
             int n = mCallbacks.beginBroadcast();
             for (int i = 0; i < n; ++i) {
                 try {
-                    mCallbacks.getBroadcastItem(i).addHdmiTvInput(id, inputInfo);
+                    mCallbacks.getBroadcastItem(i).addHdmiInput(id, inputInfo);
                 } catch (RemoteException e) {
-                    Log.e(TAG, "error in broadcastAddHdmiTvInput", e);
+                    Log.e(TAG, "error in broadcastAddHdmiInput", e);
                 }
             }
             mCallbacks.finishBroadcast();
         }
 
-        private void broadcastRemoveTvInput(String inputId) {
+        private void broadcastRemoveHardwareInput(String inputId) {
             int n = mCallbacks.beginBroadcast();
             for (int i = 0; i < n; ++i) {
                 try {
-                    mCallbacks.getBroadcastItem(i).removeTvInput(inputId);
+                    mCallbacks.getBroadcastItem(i).removeHardwareInput(inputId);
                 } catch (RemoteException e) {
-                    Log.e(TAG, "error in broadcastRemoveTvInput", e);
+                    Log.e(TAG, "error in broadcastRemoveHardwareInput", e);
                 }
             }
             mCallbacks.finishBroadcast();
@@ -2075,35 +2075,35 @@
                     recordingSessionImpl.initialize(cb);
                     return;
                 }
-                case DO_ADD_HARDWARE_TV_INPUT: {
+                case DO_ADD_HARDWARE_INPUT: {
                     TvInputHardwareInfo hardwareInfo = (TvInputHardwareInfo) msg.obj;
                     TvInputInfo inputInfo = onHardwareAdded(hardwareInfo);
                     if (inputInfo != null) {
-                        broadcastAddHardwareTvInput(hardwareInfo.getDeviceId(), inputInfo);
+                        broadcastAddHardwareInput(hardwareInfo.getDeviceId(), inputInfo);
                     }
                     return;
                 }
-                case DO_REMOVE_HARDWARE_TV_INPUT: {
+                case DO_REMOVE_HARDWARE_INPUT: {
                     TvInputHardwareInfo hardwareInfo = (TvInputHardwareInfo) msg.obj;
                     String inputId = onHardwareRemoved(hardwareInfo);
                     if (inputId != null) {
-                        broadcastRemoveTvInput(inputId);
+                        broadcastRemoveHardwareInput(inputId);
                     }
                     return;
                 }
-                case DO_ADD_HDMI_TV_INPUT: {
+                case DO_ADD_HDMI_INPUT: {
                     HdmiDeviceInfo deviceInfo = (HdmiDeviceInfo) msg.obj;
                     TvInputInfo inputInfo = onHdmiDeviceAdded(deviceInfo);
                     if (inputInfo != null) {
-                        broadcastAddHdmiTvInput(deviceInfo.getId(), inputInfo);
+                        broadcastAddHdmiInput(deviceInfo.getId(), inputInfo);
                     }
                     return;
                 }
-                case DO_REMOVE_HDMI_TV_INPUT: {
+                case DO_REMOVE_HDMI_INPUT: {
                     HdmiDeviceInfo deviceInfo = (HdmiDeviceInfo) msg.obj;
                     String inputId = onHdmiDeviceRemoved(deviceInfo);
                     if (inputId != null) {
-                        broadcastRemoveTvInput(inputId);
+                        broadcastRemoveHardwareInput(inputId);
                     }
                     return;
                 }
diff --git a/media/java/android/service/media/IMediaBrowserService.aidl b/media/java/android/service/media/IMediaBrowserService.aidl
index fe7ebfa..6ca5ac5 100644
--- a/media/java/android/service/media/IMediaBrowserService.aidl
+++ b/media/java/android/service/media/IMediaBrowserService.aidl
@@ -16,7 +16,7 @@
 oneway interface IMediaBrowserService {
 
     // Warning: DO NOT CHANGE the methods signature and order of methods.
-    // The change of the order or the method signatures could break the support library.
+    // A change of the order or the method signatures could break the support library.
 
     void connect(String pkg, in Bundle rootHints, IMediaBrowserServiceCallbacks callbacks);
     void disconnect(IMediaBrowserServiceCallbacks callbacks);
diff --git a/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl b/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
index dadb025..e6b0e8c 100644
--- a/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
+++ b/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
@@ -13,6 +13,10 @@
  * @hide
  */
 oneway interface IMediaBrowserServiceCallbacks {
+
+    // Warning: DO NOT CHANGE the methods signature and order of methods.
+    // A change of the order or the method signatures could break the support library.
+
     /**
      * Invoked when the connected has been established.
      * @param root The root media id for browsing.
@@ -22,5 +26,6 @@
      */
     void onConnect(String root, in MediaSession.Token session, in Bundle extras);
     void onConnectFailed();
-    void onLoadChildren(String mediaId, in ParceledListSlice list, in Bundle options);
+    void onLoadChildren(String mediaId, in ParceledListSlice list);
+    void onLoadChildrenWithOptions(String mediaId, in ParceledListSlice list, in Bundle options);
 }
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index 6cf90d5..299b770 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -589,7 +589,14 @@
                 final ParceledListSlice<MediaBrowser.MediaItem> pls =
                         filteredList == null ? null : new ParceledListSlice<>(filteredList);
                 try {
-                    connection.callbacks.onLoadChildren(parentId, pls, options);
+                    // NOTE: Do not call onLoadChildrenWithOptions when options are null. Otherwise,
+                    // it will break the action of support library which expects onLoadChildren will
+                    // be called when options are null.
+                    if (options == null) {
+                        connection.callbacks.onLoadChildren(parentId, pls);
+                    } else {
+                        connection.callbacks.onLoadChildrenWithOptions(parentId, pls, options);
+                    }
                 } catch (RemoteException ex) {
                     // The other side is in the process of crashing.
                     Log.w(TAG, "Calling onLoadChildren() failed for id=" + parentId
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
index 112914e..959fac6 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
@@ -165,22 +165,27 @@
                             cursor.close();
                         }
 
-                        long capacityBytes = 0;
-                        long availableBytes = 0;
-                        int capacityIndex = cursor.getColumnIndex(Root.COLUMN_CAPACITY_BYTES);
-                        int availableIndex = cursor.getColumnIndex(Root.COLUMN_AVAILABLE_BYTES);
-                        while (storageCursor.moveToNext()) {
-                            // If requested columnNames does not include COLUMN_XXX_BYTES, we don't
-                            // calculate corresponding values.
-                            if (capacityIndex != -1) {
-                                capacityBytes += cursor.getLong(capacityIndex);
+                        if (storageCursor.getCount() != 0) {
+                            long capacityBytes = 0;
+                            long availableBytes = 0;
+                            int capacityIndex = cursor.getColumnIndex(Root.COLUMN_CAPACITY_BYTES);
+                            int availableIndex = cursor.getColumnIndex(Root.COLUMN_AVAILABLE_BYTES);
+                            while (storageCursor.moveToNext()) {
+                                // If requested columnNames does not include COLUMN_XXX_BYTES, we
+                                // don't calculate corresponding values.
+                                if (capacityIndex != -1) {
+                                    capacityBytes += cursor.getLong(capacityIndex);
+                                }
+                                if (availableIndex != -1) {
+                                    availableBytes += cursor.getLong(availableIndex);
+                                }
                             }
-                            if (availableIndex != -1) {
-                                availableBytes += cursor.getLong(availableIndex);
-                            }
+                            values.put(Root.COLUMN_CAPACITY_BYTES, capacityBytes);
+                            values.put(Root.COLUMN_AVAILABLE_BYTES, availableBytes);
+                        } else {
+                            values.putNull(Root.COLUMN_CAPACITY_BYTES);
+                            values.putNull(Root.COLUMN_AVAILABLE_BYTES);
                         }
-                        values.put(Root.COLUMN_CAPACITY_BYTES, capacityBytes);
-                        values.put(Root.COLUMN_AVAILABLE_BYTES, availableBytes);
                     }
                 } finally {
                     storageCursor.close();
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
index 97ea717..8075999 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
@@ -899,4 +899,24 @@
         mDatabase.getMapper().stopAddingDocuments(null);
         assertEquals("1", mDatabase.getDocumentIdForDevice(100));
     }
+
+    public void testGetClosedDevice() {
+        mDatabase.getMapper().startAddingDocuments(null);
+        mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
+                0, "Device", /* opened is */ false , new MtpRoot[0], null, null));
+        mDatabase.getMapper().stopAddingDocuments(null);
+
+        final String[] columns = new String [] {
+                DocumentsContract.Root.COLUMN_ROOT_ID,
+                DocumentsContract.Root.COLUMN_TITLE,
+                DocumentsContract.Root.COLUMN_AVAILABLE_BYTES
+        };
+        try (final Cursor cursor = mDatabase.queryRoots(columns)) {
+            assertEquals(1, cursor.getCount());
+            assertTrue(cursor.moveToNext());
+            assertEquals(1, cursor.getLong(0));
+            assertEquals("Device", cursor.getString(1));
+            assertTrue(cursor.isNull(2));
+        }
+    }
 }
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 6df31ff..ebe0d97 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -103,7 +103,7 @@
 
     <!-- The default tiles to display in QuickSettings -->
     <string name="quick_settings_tiles_default" translatable="false">
-        wifi,bt,flashlight,dnd,cell,battery,rotation,airplane,location,cast
+        wifi,bt,flashlight,dnd,cell,battery,rotation,airplane,location,cast,work
     </string>
 
     <!-- The tiles to display in QuickSettings -->
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index 8717a15..03dd25e3c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -66,6 +66,9 @@
     }
 
     public boolean hasMultipleUsers() {
+        if (mUserListener == null) {
+            return false;
+        }
         return mUserListener.getCount() != 0;
     }
 
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 2a8672d..53504cc 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -958,7 +958,15 @@
         final UserState state = getCurrentUserStateLocked();
         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
             final Service service = state.mBoundServices.get(i);
-            service.notifyMagnificationChanged(region, scale, centerX, centerY);
+            service.notifyMagnificationChangedLocked(region, scale, centerX, centerY);
+        }
+    }
+
+    private void notifySoftKeyboardShowModeChangedLocked(int showMode) {
+        final UserState state = getCurrentUserStateLocked();
+        for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
+            final Service service = state.mBoundServices.get(i);
+            service.notifySoftKeyboardShowModeChangedLocked(showMode);
         }
     }
 
@@ -1407,6 +1415,7 @@
         updateEnhancedWebAccessibilityLocked(userState);
         updateDisplayColorAdjustmentSettingsLocked(userState);
         updateMagnificationLocked(userState);
+        updateSoftKeyboardShowModeLocked(userState);
         scheduleUpdateInputFilter(userState);
         scheduleUpdateClientsIfNeededLocked(userState);
     }
@@ -1623,6 +1632,18 @@
         return false;
     }
 
+    private boolean readSoftKeyboardShowModeChangedLocked(UserState userState) {
+        final int softKeyboardShowMode = Settings.Secure.getIntForUser(
+                mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0,
+                userState.mUserId);
+        if (softKeyboardShowMode != userState.mSoftKeyboardShowMode) {
+            userState.mSoftKeyboardShowMode = softKeyboardShowMode;
+            return true;
+        }
+        return false;
+    }
+
     private void updateTouchExplorationLocked(UserState userState) {
         boolean enabled = false;
         final int serviceCount = userState.mBoundServices.size();
@@ -1757,6 +1778,25 @@
         return false;
     }
 
+    private void updateSoftKeyboardShowModeLocked(UserState userState) {
+        final int userId = userState.mUserId;
+        if (userId == mCurrentUserId) {
+            // Check whether any Accessibility Services are still enabled and, if not, remove flag
+            // requesting no soft keyboard
+            final boolean accessibilityRequestingNoIme = userState.mSoftKeyboardShowMode == 1;
+            if (accessibilityRequestingNoIme && !userState.mIsAccessibilityEnabled) {
+                // No active Accessibility Services can be requesting the soft keyboard to be hidden
+                Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                        Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
+                        0,
+                        userState.mUserId);
+                userState.mSoftKeyboardShowMode = 0;
+            }
+
+            notifySoftKeyboardShowModeChangedLocked(userState.mSoftKeyboardShowMode);
+        }
+    }
+
     private MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId) {
         IBinder windowToken = mGlobalWindowTokens.get(windowId);
         if (windowToken == null) {
@@ -2102,7 +2142,7 @@
         };
 
         // Handler for scheduling method invocations on the main thread.
-        public InvocationHandler mInvocationHandler = new InvocationHandler(
+        public final InvocationHandler mInvocationHandler = new InvocationHandler(
                 mMainHandler.getLooper());
 
         public Service(int userId, ComponentName componentName,
@@ -2297,17 +2337,20 @@
             }
         }
 
+        private boolean isCalledForCurrentUserLocked() {
+            // We treat calls from a profile as if made by its parent as profiles
+            // share the accessibility state of the parent. The call below
+            // performs the current profile parent resolution.
+            final int resolvedUserId = mSecurityPolicy
+                    .resolveCallingUserIdEnforcingPermissionsLocked(UserHandle.USER_CURRENT);
+            return resolvedUserId == mCurrentUserId;
+        }
+
         @Override
         public List<AccessibilityWindowInfo> getWindows() {
             ensureWindowsAvailableTimed();
             synchronized (mLock) {
-                // We treat calls from a profile as if made by its perent as profiles
-                // share the accessibility state of the parent. The call below
-                // performs the current profile parent resolution.
-                final int resolvedUserId = mSecurityPolicy
-                        .resolveCallingUserIdEnforcingPermissionsLocked(
-                                UserHandle.USER_CURRENT);
-                if (resolvedUserId != mCurrentUserId) {
+                if (!isCalledForCurrentUserLocked()) {
                     return null;
                 }
                 final boolean permissionGranted =
@@ -2335,13 +2378,7 @@
         public AccessibilityWindowInfo getWindow(int windowId) {
             ensureWindowsAvailableTimed();
             synchronized (mLock) {
-                // We treat calls from a profile as if made by its parent as profiles
-                // share the accessibility state of the parent. The call below
-                // performs the current profile parent resolution.
-                final int resolvedUserId = mSecurityPolicy
-                        .resolveCallingUserIdEnforcingPermissionsLocked(
-                                UserHandle.USER_CURRENT);
-                if (resolvedUserId != mCurrentUserId) {
+                if (!isCalledForCurrentUserLocked()) {
                     return null;
                 }
                 final boolean permissionGranted =
@@ -2368,13 +2405,7 @@
             IAccessibilityInteractionConnection connection = null;
             Region partialInteractiveRegion = Region.obtain();
             synchronized (mLock) {
-                // We treat calls from a profile as if made by its parent as profiles
-                // share the accessibility state of the parent. The call below
-                // performs the current profile parent resolution.
-                final int resolvedUserId = mSecurityPolicy
-                        .resolveCallingUserIdEnforcingPermissionsLocked(
-                                UserHandle.USER_CURRENT);
-                if (resolvedUserId != mCurrentUserId) {
+                if (!isCalledForCurrentUserLocked()) {
                     return false;
                 }
                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
@@ -2425,13 +2456,7 @@
             IAccessibilityInteractionConnection connection = null;
             Region partialInteractiveRegion = Region.obtain();
             synchronized (mLock) {
-                // We treat calls from a profile as if made by its parent as profiles
-                // share the accessibility state of the parent. The call below
-                // performs the current profile parent resolution.
-                final int resolvedUserId = mSecurityPolicy
-                        .resolveCallingUserIdEnforcingPermissionsLocked(
-                                UserHandle.USER_CURRENT);
-                if (resolvedUserId != mCurrentUserId) {
+                if (!isCalledForCurrentUserLocked()) {
                     return false;
                 }
                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
@@ -2482,13 +2507,7 @@
             IAccessibilityInteractionConnection connection = null;
             Region partialInteractiveRegion = Region.obtain();
             synchronized (mLock) {
-                // We treat calls from a profile as if made by its parent as profiles
-                // share the accessibility state of the parent. The call below
-                // performs the current profile parent resolution.
-                final int resolvedUserId = mSecurityPolicy
-                        .resolveCallingUserIdEnforcingPermissionsLocked(
-                                UserHandle.USER_CURRENT);
-                if (resolvedUserId != mCurrentUserId) {
+                if (!isCalledForCurrentUserLocked()) {
                     return false;
                 }
                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
@@ -2539,13 +2558,7 @@
             IAccessibilityInteractionConnection connection = null;
             Region partialInteractiveRegion = Region.obtain();
             synchronized (mLock) {
-                // We treat calls from a profile as if made by its parent as profiles
-                // share the accessibility state of the parent. The call below
-                // performs the current profile parent resolution.
-                final int resolvedUserId = mSecurityPolicy
-                        .resolveCallingUserIdEnforcingPermissionsLocked(
-                                UserHandle.USER_CURRENT);
-                if (resolvedUserId != mCurrentUserId) {
+                if (!isCalledForCurrentUserLocked()) {
                     return false;
                 }
                 resolvedWindowId = resolveAccessibilityWindowIdForFindFocusLocked(
@@ -2597,13 +2610,7 @@
             IAccessibilityInteractionConnection connection = null;
             Region partialInteractiveRegion = Region.obtain();
             synchronized (mLock) {
-                // We treat calls from a profile as if made by its parent as profiles
-                // share the accessibility state of the parent. The call below
-                // performs the current profile parent resolution.
-                final int resolvedUserId = mSecurityPolicy
-                        .resolveCallingUserIdEnforcingPermissionsLocked(
-                                UserHandle.USER_CURRENT);
-                if (resolvedUserId != mCurrentUserId) {
+                if (!isCalledForCurrentUserLocked()) {
                     return false;
                 }
                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
@@ -2670,13 +2677,7 @@
             final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
-                // We treat calls from a profile as if made by its parent as profiles
-                // share the accessibility state of the parent. The call below
-                // performs the current profile parent resolution.
-                final int resolvedUserId = mSecurityPolicy
-                        .resolveCallingUserIdEnforcingPermissionsLocked(
-                                UserHandle.USER_CURRENT);
-                if (resolvedUserId != mCurrentUserId) {
+                if (!isCalledForCurrentUserLocked()) {
                     return false;
                 }
                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
@@ -2709,13 +2710,7 @@
         @Override
         public boolean performGlobalAction(int action) {
             synchronized (mLock) {
-                // We treat calls from a profile as if made by its parent as profiles
-                // share the accessibility state of the parent. The call below
-                // performs the current profile parent resolution.
-                final int resolvedUserId = mSecurityPolicy
-                        .resolveCallingUserIdEnforcingPermissionsLocked(
-                                UserHandle.USER_CURRENT);
-                if (resolvedUserId != mCurrentUserId) {
+                if (!isCalledForCurrentUserLocked()) {
                     return false;
                 }
             }
@@ -2750,13 +2745,7 @@
         @Override
         public float getMagnificationScale() {
             synchronized (mLock) {
-                // We treat calls from a profile as if made by its parent as profiles
-                // share the accessibility state of the parent. The call below
-                // performs the current profile parent resolution.
-                final int resolvedUserId = mSecurityPolicy
-                        .resolveCallingUserIdEnforcingPermissionsLocked(
-                                UserHandle.USER_CURRENT);
-                if (resolvedUserId != mCurrentUserId) {
+                if (!isCalledForCurrentUserLocked()) {
                     return 1.0f;
                 }
             }
@@ -2771,13 +2760,7 @@
         @Override
         public Region getMagnifiedRegion() {
             synchronized (mLock) {
-                // We treat calls from a profile as if made by its parent as profiles
-                // share the accessibility state of the parent. The call below
-                // performs the current profile parent resolution.
-                final int resolvedUserId = mSecurityPolicy
-                        .resolveCallingUserIdEnforcingPermissionsLocked(
-                                UserHandle.USER_CURRENT);
-                if (resolvedUserId != mCurrentUserId) {
+                if (!isCalledForCurrentUserLocked()) {
                     return Region.obtain();
                 }
             }
@@ -2794,13 +2777,7 @@
         @Override
         public float getMagnificationCenterX() {
             synchronized (mLock) {
-                // We treat calls from a profile as if made by its parent as profiles
-                // share the accessibility state of the parent. The call below
-                // performs the current profile parent resolution.
-                final int resolvedUserId = mSecurityPolicy
-                        .resolveCallingUserIdEnforcingPermissionsLocked(
-                                UserHandle.USER_CURRENT);
-                if (resolvedUserId != mCurrentUserId) {
+                if (!isCalledForCurrentUserLocked()) {
                     return 0.0f;
                 }
             }
@@ -2815,13 +2792,7 @@
         @Override
         public float getMagnificationCenterY() {
             synchronized (mLock) {
-                // We treat calls from a profile as if made by its parent as profiles
-                // share the accessibility state of the parent. The call below
-                // performs the current profile parent resolution.
-                final int resolvedUserId = mSecurityPolicy
-                        .resolveCallingUserIdEnforcingPermissionsLocked(
-                                UserHandle.USER_CURRENT);
-                if (resolvedUserId != mCurrentUserId) {
+                if (!isCalledForCurrentUserLocked()) {
                     return 0.0f;
                 }
             }
@@ -2836,13 +2807,7 @@
         @Override
         public boolean resetMagnification(boolean animate) {
             synchronized (mLock) {
-                // We treat calls from a profile as if made by its parent as profiles
-                // share the accessibility state of the parent. The call below
-                // performs the current profile parent resolution.
-                final int resolvedUserId = mSecurityPolicy
-                        .resolveCallingUserIdEnforcingPermissionsLocked(
-                                UserHandle.USER_CURRENT);
-                if (resolvedUserId != mCurrentUserId) {
+                if (!isCalledForCurrentUserLocked()) {
                     return false;
                 }
                 final boolean permissionGranted = mSecurityPolicy.canControlMagnification(this);
@@ -2862,13 +2827,7 @@
         public boolean setMagnificationScaleAndCenter(float scale, float centerX, float centerY,
                 boolean animate) {
             synchronized (mLock) {
-                // We treat calls from a profile as if made by its parent as profiles
-                // share the accessibility state of the parent. The call below
-                // performs the current profile parent resolution.
-                final int resolvedUserId = mSecurityPolicy
-                        .resolveCallingUserIdEnforcingPermissionsLocked(
-                                UserHandle.USER_CURRENT);
-                if (resolvedUserId != mCurrentUserId) {
+                if (!isCalledForCurrentUserLocked()) {
                     return false;
                 }
                 final boolean permissionGranted = mSecurityPolicy.canControlMagnification(this);
@@ -2891,6 +2850,33 @@
         }
 
         @Override
+        public boolean setSoftKeyboardShowMode(int showMode) {
+            final UserState userState;
+            synchronized (mLock) {
+                if (!isCalledForCurrentUserLocked()) {
+                    return false;
+                }
+
+                userState = getCurrentUserStateLocked();
+            }
+
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                        Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, showMode,
+                        userState.mUserId);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+            return true;
+        }
+
+        @Override
+        public void setSoftKeyboardCallbackEnabled(boolean enabled) {
+            mInvocationHandler.setSoftKeyboardCallbackEnabled(enabled);
+        }
+
+        @Override
         public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
             mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
             synchronized (mLock) {
@@ -3080,9 +3066,14 @@
                     InvocationHandler.MSG_CLEAR_ACCESSIBILITY_CACHE);
         }
 
-        public void notifyMagnificationChanged(@NonNull Region region,
+        public void notifyMagnificationChangedLocked(@NonNull Region region,
                 float scale, float centerX, float centerY) {
-            mInvocationHandler.notifyMagnificationChanged(region, scale, centerX, centerY);
+            mInvocationHandler
+                    .notifyMagnificationChangedLocked(region, scale, centerX, centerY);
+        }
+
+        public void notifySoftKeyboardShowModeChangedLocked(int showState) {
+            mInvocationHandler.notifySoftKeyboardShowModeChangedLocked(showState);
         }
 
         /**
@@ -3104,6 +3095,25 @@
             }
         }
 
+        /**
+         * Called by the invocation handler to notify the service that the state of the soft
+         * keyboard show mode has changed.
+         */
+        private void notifySoftKeyboardShowModeChangedInternal(int showState) {
+            final IAccessibilityServiceClient listener;
+            synchronized (mLock) {
+                listener = mServiceInterface;
+            }
+            if (listener != null) {
+                try {
+                    listener.onSoftKeyboardShowModeChanged(showState);
+                } catch (RemoteException re) {
+                    Slog.e(LOG_TAG, "Error sending soft keyboard show mode changes to " + mService,
+                            re);
+                }
+            }
+        }
+
         private void notifyGestureInternal(int gestureId) {
             final IAccessibilityServiceClient listener;
             synchronized (mLock) {
@@ -3239,8 +3249,10 @@
             public static final int MSG_CLEAR_ACCESSIBILITY_CACHE = 2;
 
             private static final int MSG_ON_MAGNIFICATION_CHANGED = 5;
+            private static final int MSG_ON_SOFT_KEYBOARD_STATE_CHANGED = 6;
 
             private boolean mIsMagnificationCallbackEnabled = false;
+            private boolean mIsSoftKeyboardCallbackEnabled = false;
 
             public InvocationHandler(Looper looper) {
                 super(looper, null, true);
@@ -3268,13 +3280,18 @@
                         notifyMagnificationChangedInternal(region, scale, centerX, centerY);
                     } break;
 
+                    case MSG_ON_SOFT_KEYBOARD_STATE_CHANGED: {
+                        final int showState = (int) message.arg1;
+                        notifySoftKeyboardShowModeChangedInternal(showState);
+                    } break;
+
                     default: {
                         throw new IllegalArgumentException("Unknown message: " + type);
                     }
                 }
             }
 
-            public void notifyMagnificationChanged(@NonNull Region region, float scale,
+            public void notifyMagnificationChangedLocked(@NonNull Region region, float scale,
                     float centerX, float centerY) {
                 if (!mIsMagnificationCallbackEnabled) {
                     // Callback is disabled, don't bother packing args.
@@ -3294,8 +3311,20 @@
             public void setMagnificationCallbackEnabled(boolean enabled) {
                 mIsMagnificationCallbackEnabled = enabled;
             }
-        }
 
+            public void notifySoftKeyboardShowModeChangedLocked(int showState) {
+                if (!mIsSoftKeyboardCallbackEnabled) {
+                    return;
+                }
+
+                final Message msg = obtainMessage(MSG_ON_SOFT_KEYBOARD_STATE_CHANGED, showState, 0);
+                msg.sendToTarget();
+            }
+
+            public void setSoftKeyboardCallbackEnabled(boolean enabled) {
+                mIsSoftKeyboardCallbackEnabled = enabled;
+            }
+        }
     }
 
     final class WindowsForAccessibilityCallback implements
@@ -3976,6 +4005,8 @@
 
         public int mLastSentClientState = -1;
 
+        public int mSoftKeyboardShowMode = 0;
+
         public boolean mIsAccessibilityEnabled;
         public boolean mIsTouchExplorationEnabled;
         public boolean mIsTextHighContrastEnabled;
@@ -4048,6 +4079,7 @@
             mIsEnhancedWebAccessibilityEnabled = false;
             mIsDisplayMagnificationEnabled = false;
             mIsAutoclickEnabled = false;
+            mSoftKeyboardShowMode = 0;
         }
 
         public void destroyUiAutomationService() {
@@ -4105,6 +4137,9 @@
         private final Uri mHighTextContrastUri = Settings.Secure.getUriFor(
                 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED);
 
+        private final Uri mAccessibilitySoftKeyboardModeUri = Settings.Secure.getUriFor(
+                Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE);
+
         public AccessibilityContentObserver(Handler handler) {
             super(handler);
         }
@@ -4135,6 +4170,8 @@
                     mDisplayColorMatrixUri, false, this, UserHandle.USER_ALL);
             contentResolver.registerContentObserver(
                     mHighTextContrastUri, false, this, UserHandle.USER_ALL);
+            contentResolver.registerContentObserver(
+                    mAccessibilitySoftKeyboardModeUri, false, this, UserHandle.USER_ALL);
         }
 
         @Override
@@ -4189,6 +4226,10 @@
                     if (readHighTextContrastEnabledSettingLocked(userState)) {
                         onUserStateChangedLocked(userState);
                     }
+                } else if (mAccessibilitySoftKeyboardModeUri.equals(uri)) {
+                    if (readSoftKeyboardShowModeChangedLocked(userState)) {
+                        onUserStateChangedLocked(userState);
+                    }
                 }
             }
         }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 2d1f96b..3fd8b40 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -33,7 +33,6 @@
 import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
 
 import android.annotation.Nullable;
-import android.app.AlarmManager;
 import android.app.BroadcastOptions;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -88,7 +87,6 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
-import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -115,7 +113,6 @@
 import com.android.internal.net.VpnConfig;
 import com.android.internal.net.VpnInfo;
 import com.android.internal.net.VpnProfile;
-import com.android.internal.telephony.DctConstants;
 import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.XmlUtils;
@@ -155,11 +152,9 @@
 import java.util.HashSet;
 import java.util.SortedSet;
 import java.util.TreeSet;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * @hide
@@ -2186,7 +2181,7 @@
             if (wasDefault) {
                 mDefaultInetConditionPublished = 0;
             }
-            notifyIfacesChanged();
+            notifyIfacesChangedForNetworkStats();
             // TODO - we shouldn't send CALLBACK_LOST to requests that can be satisfied
             // by other networks that are already connected. Perhaps that can be done by
             // sending all CALLBACK_LOST messages (for requests, not listens) at the end
@@ -4095,7 +4090,7 @@
         }
         // TODO - move this check to cover the whole function
         if (!Objects.equals(newLp, oldLp)) {
-            notifyIfacesChanged();
+            notifyIfacesChangedForNetworkStats();
             notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_IP_CHANGED);
         }
 
@@ -4719,7 +4714,11 @@
         notifyLockdownVpn(networkAgent);
 
         if (oldInfo != null && oldInfo.getState() == state) {
-            if (VDBG) log("ignoring duplicate network state non-change");
+            if (oldInfo.isRoaming() != newInfo.isRoaming()) {
+                if (VDBG) log("roaming status changed, notifying NetworkStatsService");
+                notifyIfacesChangedForNetworkStats();
+            } else if (VDBG) log("ignoring duplicate network state non-change");
+            // In either case, no further work should be needed.
             return;
         }
         if (DBG) {
@@ -4749,7 +4748,7 @@
             }
             networkAgent.created = true;
             updateLinkProperties(networkAgent, null);
-            notifyIfacesChanged();
+            notifyIfacesChangedForNetworkStats();
 
             networkAgent.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED);
             scheduleUnvalidatedPrompt(networkAgent);
@@ -4913,9 +4912,10 @@
     }
 
     /**
-     * Notify other system services that set of active ifaces has changed.
+     * Notify NetworkStatsService that the set of active ifaces has changed, or that one of the
+     * properties tracked by NetworkStatsService on an active iface has changed.
      */
-    private void notifyIfacesChanged() {
+    private void notifyIfacesChangedForNetworkStats() {
         try {
             mStatsService.forceUpdateIfaces();
         } catch (Exception ignored) {
@@ -4949,7 +4949,7 @@
             success = mVpns.get(user).setUnderlyingNetworks(networks);
         }
         if (success) {
-            notifyIfacesChanged();
+            notifyIfacesChangedForNetworkStats();
         }
         return success;
     }
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 4a123df..d77def6 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -448,6 +448,7 @@
     private int[] mSubtypeIds;
     private Locale mLastSystemLocale;
     private boolean mShowImeWithHardKeyboard;
+    private boolean mAccessibilityRequestingNoSoftKeyboard;
     private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor();
     private final IPackageManager mIPackageManager;
     private final String mSlotIme;
@@ -485,15 +486,31 @@
                     Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE), false, this, userId);
             resolver.registerContentObserver(Settings.Secure.getUriFor(
                     Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD), false, this, userId);
+            resolver.registerContentObserver(Settings.Secure.getUriFor(
+                    Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE), false, this, userId);
             mRegistered = true;
         }
 
         @Override public void onChange(boolean selfChange, Uri uri) {
-            final Uri showImeUri =
-                    Settings.Secure.getUriFor(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);
+            final Uri showImeUri = Settings.Secure.getUriFor(
+                    Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);
+            final Uri accessibilityRequestingNoImeUri = Settings.Secure.getUriFor(
+                    Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE);
             synchronized (mMethodMap) {
                 if (showImeUri.equals(uri)) {
                     updateKeyboardFromSettingsLocked();
+                } else if (accessibilityRequestingNoImeUri.equals(uri)) {
+                    mAccessibilityRequestingNoSoftKeyboard = Settings.Secure.getIntForUser(
+                            mContext.getContentResolver(),
+                            Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
+                            0, mUserId) == 1;
+                    if (mAccessibilityRequestingNoSoftKeyboard) {
+                        final boolean showRequested = mShowRequested;
+                        hideCurrentInputLocked(0, null);
+                        mShowRequested = showRequested;
+                    } else if (mShowRequested) {
+                        showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
+                    }
                 } else {
                     boolean enabledChanged = false;
                     String newEnabled = mSettings.getEnabledInputMethodsStr();
@@ -655,7 +672,7 @@
                 boolean changed = false;
 
                 if (curIm != null) {
-                    int change = isPackageDisappearing(curIm.getPackageName()); 
+                    int change = isPackageDisappearing(curIm.getPackageName());
                     if (change == PACKAGE_TEMPORARY_CHANGE
                             || change == PACKAGE_PERMANENT_CHANGE) {
                         ServiceInfo si = null;
@@ -2073,12 +2090,15 @@
 
     boolean showCurrentInputLocked(int flags, ResultReceiver resultReceiver) {
         mShowRequested = true;
-        if ((flags&InputMethodManager.SHOW_IMPLICIT) == 0) {
-            mShowExplicitlyRequested = true;
+        if (mAccessibilityRequestingNoSoftKeyboard) {
+            return false;
         }
+
         if ((flags&InputMethodManager.SHOW_FORCED) != 0) {
             mShowExplicitlyRequested = true;
             mShowForced = true;
+        } else if ((flags&InputMethodManager.SHOW_IMPLICIT) == 0) {
+            mShowExplicitlyRequested = true;
         }
 
         if (!mSystemReady) {
@@ -3265,7 +3285,7 @@
                         "Requires permission "
                         + android.Manifest.permission.WRITE_SECURE_SETTINGS);
             }
-            
+
             long ident = Binder.clearCallingIdentity();
             try {
                 return setInputMethodEnabledLocked(id, enabled);
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index cf876ee..5d97afa 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -189,10 +189,6 @@
         mInstaller.execute("freecache", uuid, freeStorageSize);
     }
 
-    public void moveFiles() throws InstallerException {
-        mInstaller.execute("movefiles");
-    }
-
     /**
      * Links the 32 bit native library directory in an application's data
      * directory to the real location for backward compatibility. Note that no
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 4d66e10..bce7223 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -70,7 +70,8 @@
     }
 
     static boolean canOptimizePackage(PackageParser.Package pkg) {
-        return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0;
+        return pkg.canHaveOatDir() &&
+                ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0);
     }
 
     /**
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c3f20eb..1c4176a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2175,13 +2175,6 @@
             scanDirTracedLI(oemAppDir, PackageParser.PARSE_IS_SYSTEM
                     | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
 
-            if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
-            try {
-                mInstaller.moveFiles();
-            } catch (InstallerException e) {
-                logCriticalInfo(Log.WARN, "Update commands failed: " + e);
-            }
-
             // Prune any system packages that no longer exist.
             final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
             if (!mOnlyCore) {
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 578428b..4e96d71 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -266,7 +266,7 @@
         return (configs.length > 0) ? INPUT_STATE_CONNECTED_STANDBY : INPUT_STATE_DISCONNECTED;
     }
 
-    public void addHardwareTvInput(int deviceId, TvInputInfo info) {
+    public void addHardwareInput(int deviceId, TvInputInfo info) {
         synchronized (mLock) {
             String oldInputId = mHardwareInputIdMap.get(deviceId);
             if (oldInputId != null) {
@@ -325,7 +325,7 @@
         return false;
     }
 
-    public void addHdmiTvInput(int id, TvInputInfo info) {
+    public void addHdmiInput(int id, TvInputInfo info) {
         if (info.getType() != TvInputInfo.TYPE_HDMI) {
             throw new IllegalArgumentException("info (" + info + ") has non-HDMI type.");
         }
@@ -346,7 +346,7 @@
         }
     }
 
-    public void removeTvInput(String inputId) {
+    public void removeHardwareInput(String inputId) {
         synchronized (mLock) {
             mInputMap.remove(inputId);
             int hardwareIndex = indexOfEqualValue(mHardwareInputIdMap, inputId);
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 318f966..b065e85 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -311,7 +311,7 @@
                     userState.serviceStateMap.put(component, serviceState);
                     updateServiceConnectionLocked(component, userId);
                 } else {
-                    inputList.addAll(serviceState.inputList);
+                    inputList.addAll(serviceState.hardwareInputList);
                 }
             } else {
                 try {
@@ -2018,7 +2018,7 @@
         private final ServiceConnection connection;
         private final ComponentName component;
         private final boolean isHardware;
-        private final List<TvInputInfo> inputList = new ArrayList<>();
+        private final List<TvInputInfo> hardwareInputList = new ArrayList<>();
 
         private ITvInputService service;
         private ServiceCallback callback;
@@ -2215,39 +2215,36 @@
             }
         }
 
-        private void addTvInputLocked(TvInputInfo inputInfo) {
+        private void addHardwareInputLocked(TvInputInfo inputInfo) {
             ServiceState serviceState = getServiceStateLocked(mComponent, mUserId);
-            serviceState.inputList.add(inputInfo);
+            serviceState.hardwareInputList.add(inputInfo);
             buildTvInputListLocked(mUserId, null);
         }
 
-        @Override
-        public void addHardwareTvInput(int deviceId, TvInputInfo inputInfo) {
+        public void addHardwareInput(int deviceId, TvInputInfo inputInfo) {
             ensureHardwarePermission();
             ensureValidInput(inputInfo);
             synchronized (mLock) {
-                mTvInputHardwareManager.addHardwareTvInput(deviceId, inputInfo);
-                addTvInputLocked(inputInfo);
+                mTvInputHardwareManager.addHardwareInput(deviceId, inputInfo);
+                addHardwareInputLocked(inputInfo);
             }
         }
 
-        @Override
-        public void addHdmiTvInput(int id, TvInputInfo inputInfo) {
+        public void addHdmiInput(int id, TvInputInfo inputInfo) {
             ensureHardwarePermission();
             ensureValidInput(inputInfo);
             synchronized (mLock) {
-                mTvInputHardwareManager.addHdmiTvInput(id, inputInfo);
-                addTvInputLocked(inputInfo);
+                mTvInputHardwareManager.addHdmiInput(id, inputInfo);
+                addHardwareInputLocked(inputInfo);
             }
         }
 
-        @Override
-        public void removeTvInput(String inputId) {
+        public void removeHardwareInput(String inputId) {
             ensureHardwarePermission();
             synchronized (mLock) {
                 ServiceState serviceState = getServiceStateLocked(mComponent, mUserId);
                 boolean removed = false;
-                for (Iterator<TvInputInfo> it = serviceState.inputList.iterator();
+                for (Iterator<TvInputInfo> it = serviceState.hardwareInputList.iterator();
                         it.hasNext(); ) {
                     if (it.next().getId().equals(inputId)) {
                         it.remove();
@@ -2257,7 +2254,7 @@
                 }
                 if (removed) {
                     buildTvInputListLocked(mUserId, null);
-                    mTvInputHardwareManager.removeTvInput(inputId);
+                    mTvInputHardwareManager.removeHardwareInput(inputId);
                 } else {
                     Slog.e(TAG, "failed to remove input " + inputId);
                 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 1b0660d..ca0b43a 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -509,6 +509,7 @@
         private static final String TAG_LONG_SUPPORT_MESSAGE = "long-support-message";
         private static final String TAG_PARENT_ADMIN = "parent-admin";
         private static final String TAG_ORGANIZATION_COLOR = "organization-color";
+        private static final String TAG_ORGANIZATION_NAME = "organization-name";
 
         final DeviceAdminInfo info;
 
@@ -607,6 +608,9 @@
         static final int DEF_ORGANIZATION_COLOR = Color.GRAY;
         int organizationColor = DEF_ORGANIZATION_COLOR;
 
+        // Default title of confirm credentials screen
+        String organizationName = null;
+
         ActiveAdmin(DeviceAdminInfo _info, boolean parent) {
             info = _info;
             isParent = parent;
@@ -830,6 +834,11 @@
                 out.attribute(null, ATTR_VALUE, Integer.toString(organizationColor));
                 out.endTag(null, TAG_ORGANIZATION_COLOR);
             }
+            if (organizationName != null) {
+                out.startTag(null, TAG_ORGANIZATION_NAME);
+                out.text(organizationName);
+                out.endTag(null, TAG_ORGANIZATION_NAME);
+            }
         }
 
         void writePackageListToXml(XmlSerializer out, String outerTag,
@@ -971,6 +980,13 @@
                 } else if (TAG_ORGANIZATION_COLOR.equals(tag)) {
                     organizationColor = Integer.parseInt(
                             parser.getAttributeValue(null, ATTR_VALUE));
+                } else if (TAG_ORGANIZATION_NAME.equals(tag)) {
+                    type = parser.next();
+                    if (type == XmlPullParser.TEXT) {
+                        organizationName = parser.getText();
+                    } else {
+                        Log.w(LOG_TAG, "Missing text when loading organization name");
+                    }
                 } else {
                     Slog.w(LOG_TAG, "Unknown admin tag: " + tag);
                     XmlUtils.skipCurrentTag(parser);
@@ -1179,6 +1195,12 @@
                 pw.print(prefix); pw.print("keepUninstalledPackages=");
                     pw.println(keepUninstalledPackages);
             }
+            pw.print(prefix); pw.print("organizationColor=");
+                    pw.println(organizationColor);
+            if (organizationName != null) {
+                pw.print(prefix); pw.print("organizationName=");
+                    pw.println(organizationName);
+            }
             pw.print(prefix); pw.println("userRestrictions:");
             UserRestrictionsUtils.dumpRestrictions(pw, prefix + "  ", userRestrictions);
             pw.print(prefix); pw.print("isParent=");
@@ -8096,11 +8118,12 @@
 
     @Override
     public void setOrganizationColor(@NonNull ComponentName who, int color) {
-        final int userHandle = mInjector.userHandleGetCallingUserId();
-        if (!mHasFeature || !isManagedProfile(userHandle)) {
+        if (!mHasFeature) {
             return;
         }
         Preconditions.checkNotNull(who, "ComponentName is null");
+        final int userHandle = mInjector.userHandleGetCallingUserId();
+        enforceManagedProfile(userHandle, "set organization color");
         synchronized (this) {
             ActiveAdmin admin = getActiveAdminForCallerLocked(who,
                     DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -8111,11 +8134,11 @@
 
     @Override
     public int getOrganizationColor(@NonNull ComponentName who) {
-        final int userHandle = mInjector.userHandleGetCallingUserId();
-        if (!mHasFeature || !isManagedProfile(userHandle)) {
+        if (!mHasFeature) {
             return ActiveAdmin.DEF_ORGANIZATION_COLOR;
         }
         Preconditions.checkNotNull(who, "ComponentName is null");
+        enforceManagedProfile(mInjector.userHandleGetCallingUserId(), "get organization color");
         synchronized (this) {
             ActiveAdmin admin = getActiveAdminForCallerLocked(who,
                     DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -8125,10 +8148,11 @@
 
     @Override
     public int getOrganizationColorForUser(int userHandle) {
-        if (!mHasFeature || !isManagedProfile(userHandle)) {
+        if (!mHasFeature) {
             return ActiveAdmin.DEF_ORGANIZATION_COLOR;
         }
-        enforceCrossUsersPermission(userHandle);
+        enforceFullCrossUsersPermission(userHandle);
+        enforceManagedProfile(userHandle, "get organization color");
         synchronized (this) {
             ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userHandle);
             return (profileOwner != null)
@@ -8138,6 +8162,53 @@
     }
 
     @Override
+    public void setOrganizationName(@NonNull ComponentName who, String text) {
+        if (!mHasFeature) {
+            return;
+        }
+        Preconditions.checkNotNull(who, "ComponentName is null");
+        final int userHandle = mInjector.userHandleGetCallingUserId();
+        enforceManagedProfile(userHandle, "set organization name");
+        synchronized (this) {
+            ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+                    DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            if (!TextUtils.equals(admin.organizationName, text)) {
+                admin.organizationName = TextUtils.nullIfEmpty(text);
+                saveSettingsLocked(userHandle);
+            }
+        }
+    }
+
+    @Override
+    public String getOrganizationName(@NonNull ComponentName who) {
+        if (!mHasFeature) {
+            return null;
+        }
+        Preconditions.checkNotNull(who, "ComponentName is null");
+        enforceManagedProfile(mInjector.userHandleGetCallingUserId(), "get organization name");
+        synchronized(this) {
+            ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+                    DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            return admin.organizationName;
+        }
+    }
+
+    @Override
+    public String getOrganizationNameForUser(int userHandle) {
+        if (!mHasFeature) {
+            return null;
+        }
+        enforceFullCrossUsersPermission(userHandle);
+        enforceManagedProfile(userHandle, "get organization name");
+        synchronized (this) {
+            ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userHandle);
+            return (profileOwner != null)
+                    ? profileOwner.organizationName
+                    : null;
+        }
+    }
+
+    @Override
     public void setAffiliationIds(ComponentName admin, List<String> ids) {
         final Set<String> affiliationIds = new ArraySet<String>(ids);
         final int callingUserId = mInjector.userHandleGetCallingUserId();
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index bfdac7e..77740387 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -145,6 +145,8 @@
     private boolean mScreenOn;
     private long mLastAppIdleParoledTime;
 
+    private volatile boolean mPendingOneTimeCheckIdleStates;
+
     long mScreenOnTime;
     long mLastScreenOnEventRealtime;
 
@@ -221,6 +223,10 @@
             synchronized (mLock) {
                 updateDisplayLocked();
             }
+
+            if (mPendingOneTimeCheckIdleStates) {
+                postOneTimeCheckIdleStates();
+            }
         } else if (phase == PHASE_BOOT_COMPLETED) {
             setAppIdleParoled(getContext().getSystemService(BatteryManager.class).isCharging());
         }
@@ -368,7 +374,13 @@
      * scheduling a series of repeating checkIdleStates each time we fired off one.
      */
     void postOneTimeCheckIdleStates() {
-        mHandler.sendEmptyMessage(MSG_ONE_TIME_CHECK_IDLE_STATES);
+        if (mDeviceIdleController == null) {
+            // Not booted yet; wait for it!
+            mPendingOneTimeCheckIdleStates = true;
+        } else {
+            mHandler.sendEmptyMessage(MSG_ONE_TIME_CHECK_IDLE_STATES);
+            mPendingOneTimeCheckIdleStates = false;
+        }
     }
 
     /** Check all running users' or specified user's apps to see if they enter an idle state. */