Merge "Update usage of ActivityManagerNative."
diff --git a/api/current.txt b/api/current.txt
index 9c19fd7..fede9cf 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -34643,9 +34643,9 @@
   public abstract class AutoFillService extends android.app.Service {
     ctor public AutoFillService();
     method public final android.os.IBinder onBind(android.content.Intent);
+    method public void onConnected();
+    method public void onDisconnected();
     method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.CancellationSignal, android.service.autofill.FillCallback);
-    method public void onReady();
-    method public void onShutdown();
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
   }
 
diff --git a/api/system-current.txt b/api/system-current.txt
index e2924b3..b5b7441 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -37436,9 +37436,9 @@
   public abstract class AutoFillService extends android.app.Service {
     ctor public AutoFillService();
     method public final android.os.IBinder onBind(android.content.Intent);
+    method public void onConnected();
+    method public void onDisconnected();
     method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.CancellationSignal, android.service.autofill.FillCallback);
-    method public void onReady();
-    method public void onShutdown();
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
   }
 
diff --git a/api/test-current.txt b/api/test-current.txt
index 7eeb6c1..918400e 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -34733,9 +34733,9 @@
   public abstract class AutoFillService extends android.app.Service {
     ctor public AutoFillService();
     method public final android.os.IBinder onBind(android.content.Intent);
+    method public void onConnected();
+    method public void onDisconnected();
     method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.CancellationSignal, android.service.autofill.FillCallback);
-    method public void onReady();
-    method public void onShutdown();
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
   }
 
diff --git a/core/java/android/annotation/HalfFloat.java b/core/java/android/annotation/HalfFloat.java
new file mode 100644
index 0000000..d3e9f08
--- /dev/null
+++ b/core/java/android/annotation/HalfFloat.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+/**
+ * <p>Denotes that the annotated element represents a half-precision floating point
+ * value. Such values are stored in short data types and can be manipulated with
+ * the {@link android.util.Half} class. If applied to an array of short, every
+ * element in the array represents a half-precision float.</p>
+ *
+ * <p>Example:</p>
+ *
+ * <pre>{@code
+ * public abstract void setPosition(@HalfFloat short x, @HalfFloat short y, @HalfFloat short z);
+ * }</pre>
+ *
+ * @see android.util.Half
+ * @see android.util.Half#valueOf(float)
+ * @see android.util.Half#toFloat(short)
+ *
+ * @hide
+ */
+@Retention(SOURCE)
+@Target({PARAMETER, METHOD, LOCAL_VARIABLE, FIELD})
+public @interface HalfFloat {
+}
diff --git a/core/java/android/service/autofill/AutoFillService.java b/core/java/android/service/autofill/AutoFillService.java
index 83b2065..3734831 100644
--- a/core/java/android/service/autofill/AutoFillService.java
+++ b/core/java/android/service/autofill/AutoFillService.java
@@ -15,7 +15,6 @@
  */
 package android.service.autofill;
 
-import android.annotation.IntDef;
 import android.annotation.SdkConstant;
 import android.app.Activity;
 import android.app.Service;
@@ -34,9 +33,6 @@
 import com.android.internal.os.IResultReceiver;
 import com.android.internal.os.SomeArgs;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
 /**
  * Top-level service of the current auto-fill service for a given user.
  *
@@ -56,9 +52,9 @@
     @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
     public static final String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
 
-    private static final int MSG_READY = 1;
-    private static final int MSG_AUTO_FILL = 2;
-    private static final int MSG_SHUTDOWN = 3;
+    private static final int MSG_CONNECT = 1;
+    private static final int MSG_AUTO_FILL_ACTIVITY = 2;
+    private static final int MSG_DISCONNECT = 3;
 
     private final IResultReceiver mAssistReceiver = new IResultReceiver.Stub() {
         @Override
@@ -70,15 +66,15 @@
                     .getBinder(VoiceInteractionSession.KEY_AUTO_FILL_CALLBACK);
 
             mHandlerCaller
-                .obtainMessageOO(MSG_AUTO_FILL, structure, binder).sendToTarget();
+                .obtainMessageOO(MSG_AUTO_FILL_ACTIVITY, structure, binder).sendToTarget();
         }
 
     };
 
     private final IAutoFillService mInterface = new IAutoFillService.Stub() {
         @Override
-        public void ready() {
-            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_READY));
+        public void onConnected() {
+            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_CONNECT));
         }
 
         @Override
@@ -87,8 +83,8 @@
         }
 
         @Override
-        public void shutdown() {
-            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_SHUTDOWN));
+        public void onDisconnected() {
+            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_DISCONNECT));
         }
     };
 
@@ -97,17 +93,17 @@
         @Override
         public void executeMessage(Message msg) {
             switch (msg.what) {
-                case MSG_READY: {
-                    onReady();
+                case MSG_CONNECT: {
+                    onConnected();
                     break;
-                } case MSG_AUTO_FILL: {
+                } case MSG_AUTO_FILL_ACTIVITY: {
                     final SomeArgs args = (SomeArgs) msg.obj;
                     final AssistStructure structure = (AssistStructure) args.arg1;
                     final IBinder binder = (IBinder) args.arg2;
-                    autoFillActivity(structure, binder);
+                    requestAutoFill(structure, binder);
                     break;
-                } case MSG_SHUTDOWN: {
-                    onShutdown();
+                } case MSG_DISCONNECT: {
+                    onDisconnected();
                     break;
                 } default: {
                     Log.w(TAG, "MyCallbacks received invalid message type: " + msg);
@@ -135,14 +131,12 @@
     }
 
     /**
-     * Called during service initialization to tell you when the system is ready
-     * to receive interaction from it.
+     * Called when the Android System connects to service.
      *
      * <p>You should generally do initialization here rather than in {@link #onCreate}.
      */
-    // TODO: rename to onConnect() / update javadoc
-    public void onReady() {
-        if (DEBUG) Log.d(TAG, "onReady()");
+    public void onConnected() {
+        if (DEBUG) Log.d(TAG, "onConnected()");
     }
 
     /**
@@ -155,21 +149,18 @@
     public abstract void onFillRequest(AssistStructure structure,
             CancellationSignal cancellationSignal, FillCallback callback);
 
-    private void autoFillActivity(AssistStructure structure, IBinder binder) {
+    private void requestAutoFill(AssistStructure structure, IBinder binder) {
         final FillCallback callback = new FillCallback(binder);
         // TODO: hook up the cancelationSignal
         onFillRequest(structure, new CancellationSignal(), callback);
     }
 
     /**
-     * Called during service de-initialization to tell you when the system is shutting the
-     * service down.
+     * Called when the Android System disconnects from the service.
      *
      * <p> At this point this service may no longer be an active {@link AutoFillService}.
      */
-    // TODO: rename to onDisconnected() / update javadoc
-    public void onShutdown() {
-        if (DEBUG) Log.d(TAG, "onShutdown()");
+    public void onDisconnected() {
+        if (DEBUG) Log.d(TAG, "onDisconnected()");
     }
-
 }
diff --git a/core/java/android/service/autofill/FillCallback.java b/core/java/android/service/autofill/FillCallback.java
index bdcc93b..2308440 100644
--- a/core/java/android/service/autofill/FillCallback.java
+++ b/core/java/android/service/autofill/FillCallback.java
@@ -62,9 +62,6 @@
         }
     }
 
-    /**
-     * Notifies the activity that the auto-fill request failed.
-     */
     public void onFailure(CharSequence message) {
         if (DEBUG) Log.d(TAG, "onFailure(): message=" + message);
 
diff --git a/core/java/android/service/autofill/IAutoFillManagerService.aidl b/core/java/android/service/autofill/IAutoFillManagerService.aidl
index a91841b..cab073f 100644
--- a/core/java/android/service/autofill/IAutoFillManagerService.aidl
+++ b/core/java/android/service/autofill/IAutoFillManagerService.aidl
@@ -30,9 +30,6 @@
      *
      * @param userId user handle.
      * @param activityToken optional token of activity that needs to be on top.
-     *
-     * @return whether the request succeeded  (for example, if the activity's
-     *         user does not have an auto-fill service associated with, it will return false).
      */
-    boolean requestAutoFill(int userId, IBinder activityToken);
+    void requestAutoFill(int userId, IBinder activityToken);
 }
diff --git a/core/java/android/service/autofill/IAutoFillService.aidl b/core/java/android/service/autofill/IAutoFillService.aidl
index dca3c70..e3e911c 100644
--- a/core/java/android/service/autofill/IAutoFillService.aidl
+++ b/core/java/android/service/autofill/IAutoFillService.aidl
@@ -25,8 +25,7 @@
  * @hide
  */
 interface IAutoFillService {
-    // TODO: rename to onConnected() / onDisconnected()
-    void ready();
-    void shutdown();
+    void onConnected();
+    void onDisconnected();
     IResultReceiver getAssistReceiver();
 }
diff --git a/core/java/android/util/Half.java b/core/java/android/util/Half.java
index 08fb948..1abc10d 100644
--- a/core/java/android/util/Half.java
+++ b/core/java/android/util/Half.java
@@ -16,12 +16,15 @@
 
 package android.util;
 
+import android.annotation.HalfFloat;
+
 /**
  * <p>Half is a utility class to manipulate half-precision 16-bit
  * <a href="https://en.wikipedia.org/wiki/Half-precision_floating-point_format">IEEE 754</a>
- * floating point data types (also called fp16 or binary16). A half-precision
- * float is stored in a short data type. A half-precision float can be
- * created from or converted to single-precision floats.</p>
+ * floating point data types (also called fp16 or binary16). A half-precision float can be
+ * created from or converted to single-precision floats, and is stored in a short data type.
+ * To distinguish short values holding half-precision floats from regular short values,
+ * it is recommended to use the <code>@HalfFloat</code> annotation.</p>
  *
  * <p>The IEEE 754 standard specifies an fp16 as having the following format:</p>
  * <ul>
@@ -95,51 +98,53 @@
      * Epsilon is the difference between 1.0 and the next value representable
      * by a half-precision floating-point.
      */
-    public static final short EPSILON            = (short) 0x1400;
-    /**
-     * Smallest negative value a half-precision float may have.
-     */
-    public static final short LOWEST_VALUE       = (short) 0xfbff;
+    public static final @HalfFloat short EPSILON = (short) 0x1400;
+
     /**
      * Maximum exponent a finite half-precision float may have.
      */
-    public static final int MAX_EXPONENT         = 15;
-    /**
-     * Maximum positive finite value a half-precision float may have.
-     */
-    public static final short MAX_VALUE          = (short) 0x7bff;
+    public static final int MAX_EXPONENT = 15;
     /**
      * Minimum exponent a normalized half-precision float may have.
      */
-    public static final int MIN_EXPONENT         = -14;
+    public static final int MIN_EXPONENT = -14;
+
+    /**
+     * Smallest negative value a half-precision float may have.
+     */
+    public static final @HalfFloat short LOWEST_VALUE = (short) 0xfbff;
+    /**
+     * Maximum positive finite value a half-precision float may have.
+     */
+    public static final @HalfFloat short MAX_VALUE = (short) 0x7bff;
     /**
      * Smallest positive normal value a half-precision float may have.
      */
-    public static final short MIN_NORMAL         = (short) 0x0400;
+    public static final @HalfFloat short MIN_NORMAL = (short) 0x0400;
     /**
      * Smallest positive non-zero value a half-precision float may have.
      */
-    public static final short MIN_VALUE          = (short) 0x0001;
+    public static final @HalfFloat short MIN_VALUE = (short) 0x0001;
     /**
      * A Not-a-Number representation of a half-precision float.
      */
-    public static final short NaN                = (short) 0x7e00;
+    public static final @HalfFloat short NaN = (short) 0x7e00;
     /**
      * Negative infinity of type half-precision float.
      */
-    public static final short NEGATIVE_INFINITY  = (short) 0xfc00;
+    public static final @HalfFloat short NEGATIVE_INFINITY = (short) 0xfc00;
     /**
      * Negative 0 of type half-precision float.
      */
-    public static final short NEGATIVE_ZERO      = (short) 0x8000;
+    public static final @HalfFloat short NEGATIVE_ZERO = (short) 0x8000;
     /**
      * Positive infinity of type half-precision float.
      */
-    public static final short POSITIVE_INFINITY  = (short) 0x7c00;
+    public static final @HalfFloat short POSITIVE_INFINITY = (short) 0x7c00;
     /**
      * Positive 0 of type half-precision float.
      */
-    public static final short POSITIVE_ZERO      = (short) 0x0000;
+    public static final @HalfFloat short POSITIVE_ZERO = (short) 0x0000;
 
     private static final int FP16_SIGN_SHIFT        = 15;
     private static final int FP16_SIGN_MASK         = 0x8000;
@@ -171,7 +176,7 @@
      * @return A value with the magnitude of the first parameter and the sign
      *         of the second parameter
      */
-    public static short copySign(short magnitude, short sign) {
+    public static @HalfFloat short copySign(@HalfFloat short magnitude, @HalfFloat short sign) {
         return (short) ((sign & FP16_SIGN_MASK) | (magnitude & FP16_COMBINED));
     }
 
@@ -189,7 +194,7 @@
      * @param h A half-precision float value
      * @return The absolute value of the specified half-precision float
      */
-    public static short abs(short h) {
+    public static @HalfFloat short abs(@HalfFloat short h) {
         return (short) (h & FP16_COMBINED);
     }
 
@@ -209,7 +214,7 @@
      * @return The value of the specified half-precision float rounded to the nearest
      *         half-precision float value
      */
-    public static short round(short h) {
+    public static @HalfFloat short round(@HalfFloat short h) {
         int bits = h & 0xffff;
         int e = bits & 0x7fff;
         int result = bits;
@@ -243,7 +248,7 @@
      * @return The smallest half-precision float value toward negative infinity
      *         greater than or equal to the specified half-precision float value
      */
-    public static short ceil(short h) {
+    public static @HalfFloat short ceil(@HalfFloat short h) {
         int bits = h & 0xffff;
         int e = bits & 0x7fff;
         int result = bits;
@@ -277,7 +282,7 @@
      * @return The largest half-precision float value toward positive infinity
      *         less than or equal to the specified half-precision float value
      */
-    public static short floor(short h) {
+    public static @HalfFloat short floor(@HalfFloat short h) {
         int bits = h & 0xffff;
         int e = bits & 0x7fff;
         int result = bits;
@@ -310,7 +315,7 @@
      * @return The truncated half-precision float value of the specified
      *         half-precision float value
      */
-    public static short trunc(short h) {
+    public static @HalfFloat short trunc(@HalfFloat short h) {
         int bits = h & 0xffff;
         int e = bits & 0x7fff;
         int result = bits;
@@ -338,7 +343,7 @@
      * @param y The second half-precision value
      * @return The smaller of the two specified half-precision values
      */
-    public static short min(short x, short y) {
+    public static @HalfFloat short min(@HalfFloat short x, @HalfFloat short y) {
         if ((x & FP16_COMBINED) > FP16_EXPONENT_MAX) return NaN;
         if ((y & FP16_COMBINED) > FP16_EXPONENT_MAX) return NaN;
 
@@ -363,7 +368,7 @@
      *
      * @return The larger of the two specified half-precision values
      */
-    public static short max(short x, short y) {
+    public static @HalfFloat short max(@HalfFloat short x, @HalfFloat short y) {
         if ((x & FP16_COMBINED) > FP16_EXPONENT_MAX) return NaN;
         if ((y & FP16_COMBINED) > FP16_EXPONENT_MAX) return NaN;
 
@@ -385,7 +390,7 @@
      *
      * @return True if x is less than y, false otherwise
      */
-    public static boolean less(short x, short y) {
+    public static boolean less(@HalfFloat short x, @HalfFloat short y) {
         if ((x & FP16_COMBINED) > FP16_EXPONENT_MAX) return false;
         if ((y & FP16_COMBINED) > FP16_EXPONENT_MAX) return false;
 
@@ -403,7 +408,7 @@
      *
      * @return True if x is less than or equal to y, false otherwise
      */
-    public static boolean lessEquals(short x, short y) {
+    public static boolean lessEquals(@HalfFloat short x, @HalfFloat short y) {
         if ((x & FP16_COMBINED) > FP16_EXPONENT_MAX) return false;
         if ((y & FP16_COMBINED) > FP16_EXPONENT_MAX) return false;
 
@@ -421,7 +426,7 @@
      *
      * @return True if x is greater than y, false otherwise
      */
-    public static boolean greater(short x, short y) {
+    public static boolean greater(@HalfFloat short x, @HalfFloat short y) {
         if ((x & FP16_COMBINED) > FP16_EXPONENT_MAX) return false;
         if ((y & FP16_COMBINED) > FP16_EXPONENT_MAX) return false;
 
@@ -439,7 +444,7 @@
      *
      * @return True if x is greater than y, false otherwise
      */
-    public static boolean greaterEquals(short x, short y) {
+    public static boolean greaterEquals(@HalfFloat short x, @HalfFloat short y) {
         if ((x & FP16_COMBINED) > FP16_EXPONENT_MAX) return false;
         if ((y & FP16_COMBINED) > FP16_EXPONENT_MAX) return false;
 
@@ -457,7 +462,7 @@
      *
      * @return True if x is equal to y, false otherwise
      */
-    public static boolean equals(short x, short y) {
+    public static boolean equals(@HalfFloat short x, @HalfFloat short y) {
         if ((x & FP16_COMBINED) > FP16_EXPONENT_MAX) return false;
         if ((y & FP16_COMBINED) > FP16_EXPONENT_MAX) return false;
 
@@ -470,7 +475,7 @@
      * @param h A half-precision float value
      * @return 1 if the value is positive, -1 if the value is negative
      */
-    public static int getSign(short h) {
+    public static int getSign(@HalfFloat short h) {
         return (h & FP16_SIGN_MASK) == 0 ? 1 : -1;
     }
 
@@ -484,7 +489,7 @@
      * @param h A half-precision float value
      * @return The unbiased exponent of the specified value
      */
-    public static int getExponent(short h) {
+    public static int getExponent(@HalfFloat short h) {
         return ((h >>> FP16_EXPONENT_SHIFT) & FP16_EXPONENT_MASK) - FP16_EXPONENT_BIAS;
     }
 
@@ -495,7 +500,7 @@
      * @param h A half-precision float value
      * @return The significand, or significand, of the specified vlaue
      */
-    public static int getSignificand(short h) {
+    public static int getSignificand(@HalfFloat short h) {
         return h & FP16_SIGNIFICAND_MASK;
     }
 
@@ -507,7 +512,7 @@
      * @return true if the value is positive infinity or negative infinity,
      *         false otherwise
      */
-    public static boolean isInfinite(short h) {
+    public static boolean isInfinite(@HalfFloat short h) {
         return (h & FP16_COMBINED) == FP16_EXPONENT_MAX;
     }
 
@@ -518,7 +523,7 @@
      * @param h A half-precision float value
      * @return true if the value is a NaN, false otherwise
      */
-    public static boolean isNaN(short h) {
+    public static boolean isNaN(@HalfFloat short h) {
         return (h & FP16_COMBINED) > FP16_EXPONENT_MAX;
     }
 
@@ -532,7 +537,7 @@
      * @param h A half-precision float value
      * @return true if the value is normalized, false otherwise
      */
-    public static boolean isNormalized(short h) {
+    public static boolean isNormalized(@HalfFloat short h) {
         return (h & FP16_EXPONENT_MAX) != 0 && (h & FP16_EXPONENT_MAX) != FP16_EXPONENT_MAX;
     }
 
@@ -551,7 +556,7 @@
      * @param h The half-precision float value to convert to single-precision
      * @return A normalized single-precision float value
      */
-    public static float toFloat(short h) {
+    public static float toFloat(@HalfFloat short h) {
         int bits = h & 0xffff;
         int s = bits & FP16_SIGN_MASK;
         int e = (bits >>> FP16_EXPONENT_SHIFT) & FP16_EXPONENT_MASK;
@@ -603,7 +608,7 @@
      * @return A half-precision float value
      */
     @SuppressWarnings("StatementWithEmptyBody")
-    public static short valueOf(float f) {
+    public static @HalfFloat short valueOf(float f) {
         int bits = Float.floatToRawIntBits(f);
         int s = (bits >>> FP32_SIGN_SHIFT    );
         int e = (bits >>> FP32_EXPONENT_SHIFT) & FP32_EXPONENT_MASK;
@@ -653,7 +658,7 @@
      * @param h A half-precision float value
      * @return A string representation of the specified value
      */
-    public static String toString(short h) {
+    public static String toString(@HalfFloat short h) {
         return Float.toString(toFloat(h));
     }
 
@@ -683,7 +688,7 @@
      * @param h A half-precision float value
      * @return A hexadecimal string representation of the specified value
      */
-    public static String toHexString(short h) {
+    public static String toHexString(@HalfFloat short h) {
         StringBuilder o = new StringBuilder();
 
         int bits = h & 0xffff;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0f7b5a5..765a326 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -501,6 +501,10 @@
 
     <protected-broadcast android:name="android.intent.action.DEVICE_LOCKED_CHANGED" />
 
+    <!-- Added in O -->
+    <!-- TODO: temporary broadcast used by AutoFillManagerServiceImpl; will be removed -->
+    <protected-broadcast android:name="com.android.internal.autofill.action.REQUEST_AUTOFILL" />
+
     <!-- ====================================================================== -->
     <!--                          RUNTIME PERMISSIONS                           -->
     <!-- ====================================================================== -->
diff --git a/packages/SystemUI/res/layout-sw600dp/recents_grid.xml b/packages/SystemUI/res/layout-sw600dp/recents_grid.xml
index c8b4fd0..cff770a 100644
--- a/packages/SystemUI/res/layout-sw600dp/recents_grid.xml
+++ b/packages/SystemUI/res/layout-sw600dp/recents_grid.xml
@@ -16,8 +16,11 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
+    android:paddingTop="24dp"
+    android:paddingBottom="54dp"
     android:orientation="vertical"
-    android:id="@+id/recents_container">
+    android:id="@+id/recents_container"
+    android:background="#99000000">
     <include layout="@layout/recents_stack_action_button" />
     <FrameLayout
         android:layout_width="match_parent"
@@ -26,7 +29,6 @@
         android:layout_marginLeft="12dp"
         android:layout_marginTop="10dp"
         android:layout_marginRight="12dp"
-        android:layout_marginBottom="5dp"
         android:gravity="center">
     </FrameLayout>
 </LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/grid/RecentsGridActivity.java b/packages/SystemUI/src/com/android/systemui/recents/grid/RecentsGridActivity.java
index e804b52..e1e654d5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/grid/RecentsGridActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/grid/RecentsGridActivity.java
@@ -27,6 +27,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
+import android.view.WindowManager;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -94,6 +95,11 @@
         mTouchExplorationEnabled = ssp.isTouchExplorationEnabled();
 
         mRecentsView = (FrameLayout) findViewById(R.id.recents_view);
+        mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
+                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
+                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
+        getWindow().getAttributes().privateFlags |=
+                WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
         LinearLayout recentsContainer = (LinearLayout) findViewById(R.id.recents_container);
         mEmptyView = (TextView) mInflater.inflate(R.layout.recents_empty, recentsContainer, false);
         mClearAllButton = findViewById(R.id.button);
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
index 8b37756..d70c439 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
@@ -20,29 +20,40 @@
 import static android.content.Context.AUTO_FILL_MANAGER_SERVICE;
 
 import android.Manifest;
-import android.app.ActivityManager;
 import android.app.AppGlobals;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
+import android.content.pm.UserInfo;
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.Binder;
-import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.Parcel;
+import android.os.Message;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
+import android.os.SystemClock;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.Settings;
 import android.service.autofill.IAutoFillManagerService;
 import android.text.TextUtils;
+import android.text.format.DateUtils;
+import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.TimeUtils;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.BackgroundThread;
@@ -51,6 +62,7 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.List;
 
 /**
  * Entry point service for auto-fill management.
@@ -62,7 +74,13 @@
 public final class AutoFillManagerService extends SystemService {
 
     private static final String TAG = "AutoFillManagerService";
-    private static final boolean DEBUG = true; // TODO: change to false once stable
+    static final boolean DEBUG = true; // TODO: change to false once stable
+
+    private static final long SERVICE_BINDING_LIFETIME_MS = 5 * DateUtils.MINUTE_IN_MILLIS;
+
+    private static final int ARG_NOT_USED = 0;
+
+    protected static final int MSG_UNBIND = 1;
 
     private final AutoFillManagerServiceStub mServiceStub;
     private final Context mContext;
@@ -70,30 +88,39 @@
 
     private final Object mLock = new Object();
 
-    @GuardedBy("mLock")
-    private boolean mSafeMode;
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_UNBIND:
+                    removeStaleServiceForUser(msg.arg1);
+                    return;
+                case MSG_SHOW_ALL_NOTIFICATIONS:
+                    showAllNotifications();
+                    return;
+                default:
+                    Slog.w(TAG, "Invalid message: " + msg);
+            }
+        }
+
+    };
 
     /**
-     * Map of {@link AutoFillManagerServiceImpl} per user id.
+     * Cache of {@link AutoFillManagerServiceImpl} per user id.
      * <p>
      * It has to be mapped by user id because the same current user could have simultaneous sessions
-     * associated to different user profiles (for example, in a multi-window environment).
+     * associated to different user profiles (for example, in a multi-window environment or when
+     * device has work profiles).
      * <p>
-     * This map is filled on demand in the following scenarios:
+     * Entries on this cache are added on demand and removed when:
      * <ol>
-     *   <li>On start, it sets the value for the default user.
-     *   <li>When an auto-fill service app is removed, its entries are removed.
-     *   <li>When the current user changes.
-     *   <li>When the {@link android.provider.Settings.Secure#AUTO_FILL_SERVICE} changes.
+     *   <li>An auto-fill service app is removed.
+     *   <li>The {@link android.provider.Settings.Secure#AUTO_FILL_SERVICE} for an user change.
+     *   <li>It has not been interacted with for {@link #SERVICE_BINDING_LIFETIME_MS} ms.
      * </ol>
      */
-    // TODO: make sure all cases listed above are handled
-    // TODO: should entries be removed when there is no section and have not be used for a while?
     @GuardedBy("mLock")
-    private SparseArray<AutoFillManagerServiceImpl> mImplByUser = new SparseArray<>();
-
-    // TODO: should disable it on low-memory devices? if not, this attribute should be removed...
-    private final boolean mEnableService = true;
+    private SparseArray<AutoFillManagerServiceImpl> mServicesCache = new SparseArray<>();
 
     public AutoFillManagerService(Context context) {
         super(context);
@@ -105,124 +132,130 @@
 
     @Override
     public void onStart() {
-        if (DEBUG)
-            Slog.d(TAG, "onStart(): binding as " + AUTO_FILL_MANAGER_SERVICE);
+        if (DEBUG) Slog.d(TAG, "onStart(): binding as " + AUTO_FILL_MANAGER_SERVICE);
         publishBinderService(AUTO_FILL_MANAGER_SERVICE, mServiceStub);
     }
 
-    // TODO: refactor so it's bound on demand, in which case it can use isSafeMode() from PM.
     @Override
     public void onBootPhase(int phase) {
         if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
-            systemRunning(isSafeMode());
+            new SettingsObserver(BackgroundThread.getHandler());
+        }
+        if (phase == PHASE_BOOT_COMPLETED) {
+            // TODO: if sent right away, the notification is not displayed. Since the notification
+            // mechanism is a temporary approach anyways, just delay it..
+            if (DEBUG)
+                Slog.d(TAG, "Showing notifications in " + SHOW_ALL_NOTIFICATIONS_DELAY_MS + "ms");
+            mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SHOW_ALL_NOTIFICATIONS),
+                    SHOW_ALL_NOTIFICATIONS_DELAY_MS);
         }
     }
 
-    // TODO: refactor so it's bound on demand, in which case it can use isSafeMode() from PM.
-    @Override
-    public void onStartUser(int userHandle) {
-        if (DEBUG) Slog.d(TAG, "onStartUser(): userHandle=" + userHandle);
-
-        updateImplementationIfNeeded(userHandle, false);
-    }
-
-    @Override
-    public void onUnlockUser(int userHandle) {
-        if (DEBUG) Slog.d(TAG, "onUnlockUser(): userHandle=" + userHandle);
-
-        updateImplementationIfNeeded(userHandle, false);
-    }
-
-    @Override
-    public void onSwitchUser(int userHandle) {
-        if (DEBUG) Slog.d(TAG, "onSwitchUser(): userHandle=" + userHandle);
-
-        updateImplementationIfNeeded(userHandle, false);
-    }
-
-    private void systemRunning(boolean safeMode) {
-        if (DEBUG) Slog.d(TAG, "systemRunning(): safeMode=" + safeMode);
-
-        // TODO: register a PackageMonitor
-        new SettingsObserver(BackgroundThread.getHandler());
-
-        synchronized (mLock) {
-            mSafeMode = safeMode;
-            updateImplementationIfNeededLocked(ActivityManager.getCurrentUser(), false);
-        }
-    }
-
-    private void updateImplementationIfNeeded(int user, boolean force) {
-        synchronized (mLock) {
-            updateImplementationIfNeededLocked(user, force);
-        }
-    }
-
-    private void updateImplementationIfNeededLocked(int user, boolean force) {
-        if (DEBUG)
-            Slog.d(TAG, "updateImplementationIfNeededLocked(" + user + ", " + force + ")");
-
-        if (mSafeMode) {
-            if (DEBUG) Slog.d(TAG, "skipping on safe mode");
-            return;
-        }
-
-        final String curService = Settings.Secure.getStringForUser(
-                mResolver, Settings.Secure.AUTO_FILL_SERVICE, user);
-        if (DEBUG)
-            Slog.d(TAG, "Current service settings for user " + user + ": " + curService);
+    private AutoFillManagerServiceImpl newServiceForUser(int userId) {
         ComponentName serviceComponent = null;
         ServiceInfo serviceInfo = null;
-        if (!TextUtils.isEmpty(curService)) {
+        final String componentName = Settings.Secure.getStringForUser(
+                mResolver, Settings.Secure.AUTO_FILL_SERVICE, userId);
+        if (!TextUtils.isEmpty(componentName)) {
             try {
-                serviceComponent = ComponentName.unflattenFromString(curService);
+                serviceComponent = ComponentName.unflattenFromString(componentName);
                 serviceInfo =
-                        AppGlobals.getPackageManager().getServiceInfo(serviceComponent, 0, user);
+                        AppGlobals.getPackageManager().getServiceInfo(serviceComponent, 0, userId);
             } catch (RuntimeException | RemoteException e) {
-                Slog.wtf(TAG, "Bad auto-fill service name " + curService, e);
-                serviceComponent = null;
-                serviceInfo = null;
+                Slog.wtf(TAG, "Bad auto-fill service name " + componentName, e);
+                return null;
             }
         }
 
-        final AutoFillManagerServiceImpl impl = mImplByUser.get(user);
-        if (DEBUG) Slog.d(TAG, "Current impl: " + impl + " component: " + serviceComponent
-                + " info: " + serviceInfo);
+        if (DEBUG) Slog.d(TAG, "getServiceComponentForUser(" + userId + "): component="
+                + serviceComponent + ", info: " + serviceInfo);
+        if (serviceInfo == null) {
+            Slog.w(TAG, "no service info for " + serviceComponent);
+            return null;
+        }
+        return new AutoFillManagerServiceImpl(this, mContext, mLock, FgThread.getHandler(), userId,
+                serviceInfo.applicationInfo.uid, serviceComponent, SERVICE_BINDING_LIFETIME_MS);
+    }
 
-        if (force || impl == null || !impl.mComponent.equals(serviceComponent)) {
-            if (impl != null) {
-                impl.shutdownLocked();
+    /**
+     * Gets the service instance for an user.
+     *
+     * <p>First it tries to return the existing instance from the cache; if it's not cached, it
+     * creates a new instance and caches it.
+     */
+    private AutoFillManagerServiceImpl getServiceForUserLocked(int userId) {
+        AutoFillManagerServiceImpl service = mServicesCache.get(userId);
+        if (service != null) {
+            if (DEBUG) Log.d(TAG, "reusing cached service for userId " + userId);
+            service.setLifeExpectancy(SERVICE_BINDING_LIFETIME_MS);
+        } else {
+            service = newServiceForUser(userId);
+            if (service == null) {
+                // Already logged
+                return null;
             }
-            if (serviceInfo != null) {
-                final AutoFillManagerServiceImpl newImpl = new AutoFillManagerServiceImpl(mContext,
-                        mLock, mServiceStub, FgThread.getHandler(), user, serviceComponent);
-                if (DEBUG) Slog.d(TAG, "Setting impl for user " + user + " as: " + newImpl);
-                mImplByUser.put(user, newImpl);
-                newImpl.startLocked();
-            } else {
-                if (DEBUG) Slog.d(TAG, "Removing impl for user " + user + ": " + impl);
-                mImplByUser.remove(user);
-            }
+            if (DEBUG) Log.d(TAG, "creating new cached service for userId " + userId);
+            service.startLocked();
+            mServicesCache.put(userId, service);
+        }
+        // Keep service connection alive for a while, in case user needs to interact with it
+        // (for example, to save the data that was inputted in)
+        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_UNBIND, userId, ARG_NOT_USED),
+                SERVICE_BINDING_LIFETIME_MS);
+        return service;
+    }
+
+    /**
+     * Removes a cached service, but respecting its TTL.
+     */
+    private void removeStaleServiceForUser(int userId) {
+        synchronized (mLock) {
+            removeCachedService(userId, false);
         }
     }
 
-    // TODO: might need to return null instead of throw exception
-    private AutoFillManagerServiceImpl getImplOrThrowLocked(int userId) {
-        final AutoFillManagerServiceImpl impl = mImplByUser.get(userId);
-        if (impl == null) {
-            throw new IllegalStateException("no auto-fill service for user " + userId);
+    /**
+     * Removes a cached service, even if it has TTL.
+     */
+    void removeCachedServiceForUserLocked(int userId) {
+        removeCachedService(userId, true);
+    }
+
+    private void removeCachedService(int userId, boolean force) {
+        if (DEBUG) Log.d(TAG, "removing cached service for userId " + userId);
+        final AutoFillManagerServiceImpl service = mServicesCache.get(userId);
+        if (service == null) {
+            Log.w(TAG, "removeCachedServiceForUser(): no cached service for userId " + userId);
+            return;
         }
-        return impl;
+        if (!force) {
+            // Check TTL first.
+            final long now = SystemClock.uptimeMillis();
+            if (service.mEstimateTimeOfDeath > now) {
+                if (DEBUG) {
+                    final StringBuilder msg = new StringBuilder("service has some TTL left: ");
+                    TimeUtils.formatDuration(service.mEstimateTimeOfDeath - now, msg);
+                    Log.d(TAG, msg.toString());
+                }
+                return;
+            }
+        }
+        mServicesCache.delete(userId);
+        service.stopLocked();
+
     }
 
     final class AutoFillManagerServiceStub extends IAutoFillManagerService.Stub {
 
         @Override
-        public boolean requestAutoFill(int userId, IBinder activityToken) {
+        public void requestAutoFill(int userId, IBinder activityToken) {
             mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
 
             synchronized (mLock) {
-                return getImplOrThrowLocked(userId).requestAutoFill(activityToken);
+                final AutoFillManagerServiceImpl service = getServiceForUserLocked(userId);
+                if (service != null) {
+                    service.requestAutoFill(activityToken);
+                }
             }
         }
 
@@ -236,17 +269,15 @@
                 return;
             }
             synchronized (mLock) {
-                pw.print("mEnableService: "); pw.println(mEnableService);
-                pw.print("mSafeMode: "); pw.println(mSafeMode);
-                final int size = mImplByUser.size();
-                pw.print("Number of implementations: ");
+                final int size = mServicesCache.size();
+                pw.print("Cached services: ");
                 if (size == 0) {
                     pw.println("none");
                 } else {
                     pw.println(size);
                     for (int i = 0; i < size; i++) {
-                        pw.print("\nImplementation at index "); pw.println(i);
-                        final AutoFillManagerServiceImpl impl = mImplByUser.valueAt(i);
+                        pw.print("\nService at index "); pw.println(i);
+                        final AutoFillManagerServiceImpl impl = mServicesCache.valueAt(i);
                         impl.dumpLocked("  ", pw);
                     }
                 }
@@ -267,15 +298,144 @@
             super(handler);
             ContentResolver resolver = mContext.getContentResolver();
             resolver.registerContentObserver(Settings.Secure.getUriFor(
-                    Settings.Secure.AUTO_FILL_SERVICE), false, this,
-                    UserHandle.USER_ALL);
+                    Settings.Secure.AUTO_FILL_SERVICE), false, this, UserHandle.USER_ALL);
         }
 
         @Override
         public void onChange(boolean selfChange, Uri uri, int userId) {
+            if (DEBUG) Slog.d(TAG, "settings (" + uri + " changed for " + userId);
             synchronized (mLock) {
-                updateImplementationIfNeededLocked(userId, false);
+                removeCachedServiceForUserLocked(userId);
+                final ComponentName serviceComponent = getProviderForUser(userId);
+                if (serviceComponent== null) {
+                    cancelNotificationLocked(userId);
+                } else {
+                    showNotification(serviceComponent, userId);
+                }
             }
         }
     }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // TODO: temporary code using a notification to request auto-fill.        //
+    // Will be removed once UX decide the right way to present it to the user //
+    ////////////////////////////////////////////////////////////////////////////
+
+    // TODO: remove from frameworks/base/core/res/AndroidManifest.xml once it's not used anymore
+    private static final String NOTIFICATION_INTENT =
+            "com.android.internal.autofill.action.REQUEST_AUTOFILL";
+    private static final String EXTRA_USER_ID = "user_id";
+
+    private static final int MSG_SHOW_ALL_NOTIFICATIONS = 42;
+    private static final int SHOW_ALL_NOTIFICATIONS_DELAY_MS = 5000;
+
+    private BroadcastReceiver mNotificationReceiver;
+
+    final class NotificationReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final int userId = intent.getIntExtra(EXTRA_USER_ID, -1);
+            if (DEBUG) Slog.d(TAG, "Requesting autofill by notification for user " + userId);
+            synchronized (mLock) {
+                final AutoFillManagerServiceImpl service = getServiceForUserLocked(userId);
+                if (service == null) {
+                    Slog.w(TAG, "no auto-fill service for user " + userId);
+                } else {
+                    service.requestAutoFill(null);
+                }
+            }
+        }
+    }
+
+    private ComponentName getProviderForUser(int userId) {
+        ComponentName serviceComponent = null;
+        ServiceInfo serviceInfo = null;
+        final String componentName = Settings.Secure.getStringForUser(
+                mResolver, Settings.Secure.AUTO_FILL_SERVICE, userId);
+        if (!TextUtils.isEmpty(componentName)) {
+            try {
+                serviceComponent = ComponentName.unflattenFromString(componentName);
+                serviceInfo =
+                        AppGlobals.getPackageManager().getServiceInfo(serviceComponent, 0, userId);
+            } catch (RuntimeException | RemoteException e) {
+                Slog.wtf(TAG, "Bad auto-fill service name " + componentName, e);
+                return null;
+            }
+        }
+
+        if (DEBUG) Slog.d(TAG, "getServiceComponentForUser(" + userId + "): component="
+                + serviceComponent + ", info: " + serviceInfo);
+        if (serviceInfo == null) {
+            Slog.w(TAG, "no service info for " + serviceComponent);
+            return null;
+        }
+        return serviceComponent;
+    }
+
+    private void showAllNotifications() {
+        final UserManager userManager =
+                (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+
+        final List<UserInfo> allUsers = userManager.getUsers(true);
+
+        for (UserInfo user : allUsers) {
+            final ComponentName serviceComponent = getProviderForUser(user.id);
+            if (serviceComponent != null) {
+                showNotification(serviceComponent, user.id);
+            }
+        }
+    }
+
+    private void showNotification(ComponentName serviceComponent, int userId) {
+        if (DEBUG) Log.d(TAG, "showNotification() for " + userId + ": " + serviceComponent);
+
+        synchronized (mLock) {
+            if (mNotificationReceiver == null) {
+                mNotificationReceiver = new NotificationReceiver();
+                mContext.registerReceiver(mNotificationReceiver,
+                        new IntentFilter(NOTIFICATION_INTENT));
+            }
+        }
+
+        final Intent intent = new Intent(NOTIFICATION_INTENT);
+        intent.putExtra(EXTRA_USER_ID, userId);
+        final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, intent,
+                PendingIntent.FLAG_UPDATE_CURRENT);
+
+        final String packageName = serviceComponent.getPackageName();
+        String providerName = null;
+        final PackageManager pm = mContext.getPackageManager();
+        try {
+            final ApplicationInfo info = pm.getApplicationInfoAsUser(packageName, 0, userId);
+            if (info != null) {
+                providerName = pm.getApplicationLabel(info).toString();
+            }
+        } catch (Exception e) {
+            providerName = packageName;
+        }
+        final String title = "AutoFill by '" + providerName + "'";
+        final String subTitle = "Tap notification to auto-fill top activity for user " + userId;
+
+        final Notification notification = new Notification.Builder(mContext)
+                .setCategory(Notification.CATEGORY_SYSTEM)
+                .setOngoing(true)
+                .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
+                .setLocalOnly(true)
+                .setColor(mContext.getColor(
+                        com.android.internal.R.color.system_notification_accent_color))
+                .setContentTitle(title)
+                .setStyle(new Notification.BigTextStyle().bigText(subTitle))
+                .setContentIntent(pi)
+                .build();
+        NotificationManager.from(mContext).notify(userId, notification);
+    }
+
+    private void cancelNotificationLocked(int userId) {
+        if (DEBUG) Log.d(TAG, "cancelNotificationLocked(): " + userId);
+        NotificationManager.from(mContext).cancel(userId);
+    }
+
+    /////////////////////////////////////////
+    // End of temporary notification code. //
+    /////////////////////////////////////////
 }
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
index ae687da4..e409cb0 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
@@ -16,6 +16,8 @@
 
 package com.android.server.autofill;
 
+import static com.android.server.autofill.AutoFillManagerService.DEBUG;
+
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
 import android.app.IActivityManager;
@@ -27,10 +29,11 @@
 import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
 import android.icu.text.DateFormat;
-import android.os.Bundle;
+import android.os.DeadObjectException;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.service.autofill.AutoFillService;
 import android.service.autofill.AutoFillServiceInfo;
@@ -38,14 +41,15 @@
 import android.util.Log;
 import android.util.PrintWriterPrinter;
 import android.util.Slog;
+import android.util.TimeUtils;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.server.LocalServices;
-import com.android.server.autofill.AutoFillManagerService.AutoFillManagerServiceStub;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Date;
+import java.util.LinkedList;
 import java.util.List;
 
 /**
@@ -56,21 +60,23 @@
 final class AutoFillManagerServiceImpl {
 
     private static final String TAG = "AutoFillManagerServiceImpl";
-    private static final boolean DEBUG = true; // TODO: change to false once stable
 
-    final int mUser;
-    final ComponentName mComponent;
-
+    private final int mUserId;
+    private final int mUid;
+    private final ComponentName mComponent;
     private final Context mContext;
     private final IActivityManager mAm;
     private final Object mLock;
-    private final AutoFillManagerServiceStub mServiceStub;
     private final AutoFillServiceInfo mInfo;
+    private final AutoFillManagerService mManagerService;
 
     // TODO: improve its usage
     // - set maximum number of entries
     // - disable on low-memory devices.
-    private final List<String> mRequestHistory = new ArrayList<>();
+    private final List<String> mRequestHistory = new LinkedList<>();
+
+    @GuardedBy("mLock")
+    private final List<IBinder> mQueuedRequests = new LinkedList<>();
 
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
@@ -90,9 +96,16 @@
             synchronized (mLock) {
                 mService = IAutoFillService.Stub.asInterface(service);
                 try {
-                    mService.ready();
+                    mService.onConnected();
                 } catch (RemoteException e) {
-                    Slog.w(TAG, "Exception on service.ready(): " + e);
+                    Slog.w(TAG, "Exception on service.onConnected(): " + e);
+                    return;
+                }
+                if (!mQueuedRequests.isEmpty()) {
+                    if (DEBUG) Log.d(TAG, "queued requests:" + mQueuedRequests.size());
+                }
+                for (IBinder activityToken : mQueuedRequests) {
+                    requestAutoFillLocked(activityToken, false);
                 }
             }
         }
@@ -100,7 +113,10 @@
         @Override
         public void onServiceDisconnected(ComponentName name) {
             if (DEBUG) Log.d(TAG, name + " disconnected");
-            mService = null;
+            synchronized (mLock) {
+                mService = null;
+                mManagerService.removeCachedServiceForUserLocked(mUserId);
+            }
         }
     };
 
@@ -109,18 +125,23 @@
     private boolean mBound;
     private boolean mValid;
 
-    AutoFillManagerServiceImpl(Context context, Object lock, AutoFillManagerServiceStub stub,
-            Handler handler, int user, ComponentName component) {
+    // Estimated time when the service will be evicted from the cache.
+    long mEstimateTimeOfDeath;
+
+    AutoFillManagerServiceImpl(AutoFillManagerService managerService, Context context, Object lock,
+            Handler handler, int userId, int uid,ComponentName component, long ttl) {
+        mManagerService = managerService;
         mContext = context;
         mLock = lock;
-        mServiceStub = stub;
-        mUser = user;
+        mUserId = userId;
+        mUid = uid;
         mComponent = component;
         mAm = ActivityManager.getService();
+        setLifeExpectancy(ttl);
 
         final AutoFillServiceInfo info;
         try {
-            info = new AutoFillServiceInfo(component, mUser);
+            info = new AutoFillServiceInfo(component, mUserId);
         } catch (PackageManager.NameNotFoundException e) {
             Slog.w(TAG, "Auto-fill service not found: " + component, e);
             mInfo = null;
@@ -140,13 +161,18 @@
         mContext.registerReceiver(mBroadcastReceiver, filter, null, handler);
     }
 
+    void setLifeExpectancy(long ttl) {
+        mEstimateTimeOfDeath = SystemClock.uptimeMillis() + ttl;
+    }
+
     void startLocked() {
         if (DEBUG) Slog.d(TAG, "startLocked()");
 
         final Intent intent = new Intent(AutoFillService.SERVICE_INTERFACE);
         intent.setComponent(mComponent);
         mBound = mContext.bindServiceAsUser(intent, mConnection,
-                Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, new UserHandle(mUser));
+                Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, new UserHandle(mUserId));
+
         if (!mBound) {
             Slog.w(TAG, "Failed binding to auto-fill service " + mComponent);
             return;
@@ -154,11 +180,12 @@
         if (DEBUG) Slog.d(TAG, "Bound to " + mComponent);
     }
 
-    boolean requestAutoFill(IBinder activityToken) {
-        if (!mBound) {
-            // TODO: should it bind on demand? Or perhaps always run when on on low-memory?
-            Slog.w(TAG, "requestAutoFill() failed because it's not bound to service");
-            return false;
+    void requestAutoFill(IBinder activityToken) {
+        synchronized (mLock) {
+            if (!mBound) {
+                Slog.w(TAG, "requestAutoFill() failed because it's not bound to service");
+                return;
+            }
         }
 
         // TODO: activityToken should probably not be null, but we need to wait until the UI is
@@ -175,25 +202,28 @@
                 Slog.d(TAG, "Top activities (" + topActivities.size() + "): " + topActivities);
             if (topActivities.isEmpty()) {
                 Slog.w(TAG, "Could not get top activity");
-                return false;
+                return;
             }
             activityToken = topActivities.get(0);
         }
 
+        final String historyItem =
+                DateFormat.getDateTimeInstance().format(new Date()) + " - " + activityToken;
         synchronized (mLock) {
-            return requestAutoFillLocked(activityToken);
+            mRequestHistory.add(historyItem);
+            requestAutoFillLocked(activityToken, true);
         }
     }
 
-    private boolean requestAutoFillLocked(IBinder activityToken) {
-        mRequestHistory.add(
-                DateFormat.getDateTimeInstance().format(new Date()) + " - " + activityToken);
-        if (DEBUG) Slog.d(TAG, "Requesting for user " + mUser + " and activity " + activityToken);
-
-        // Sanity check
+    private void requestAutoFillLocked(IBinder activityToken, boolean queueIfNecessary) {
         if (mService == null) {
-            Slog.w(TAG, "requestAutoFillLocked(: service is null");
-            return false;
+            if (!queueIfNecessary) {
+                Slog.w(TAG, "requestAutoFillLocked(): service is null");
+                return;
+            }
+            if (DEBUG) Slog.d(TAG, "requestAutoFill(): service not set yet, queuing it");
+            mQueuedRequests.add(activityToken);
+            return;
         }
 
         /*
@@ -206,23 +236,30 @@
         try {
             // TODO: add MetricsLogger call
             if (!mAm.requestAutoFillData(mService.getAssistReceiver(), null, activityToken)) {
-                return false;
+                // TODO: might need a way to warn user (perhaps a new method on AutoFillService).
+                Slog.w(TAG, "failed to request auto-fill data for " + activityToken);
             }
         } catch (RemoteException e) {
             // Should happen, it's a local call.
         }
-        return true;
     }
 
-    void shutdownLocked() {
-        if (DEBUG) Slog.d(TAG, "shutdownLocked()");
+    void stopLocked() {
+        if (DEBUG) Slog.d(TAG, "stopLocked()");
 
+        // Sanity check.
+        if (mService == null) {
+            Log.w(TAG, "service already null on shutdown");
+            return;
+        }
         try {
-            if (mService != null) {
-                mService.shutdown();
-            }
+            mService.onDisconnected();
         } catch (RemoteException e) {
-            Slog.w(TAG, "RemoteException in shutdown", e);
+            if (! (e instanceof DeadObjectException)) {
+                Slog.w(TAG, "Exception calling service.onDisconnected(): " + e);
+            }
+        } finally {
+            mService = null;
         }
 
         if (mBound) {
@@ -245,10 +282,14 @@
             return;
         }
 
-        pw.print(prefix); pw.print("mUser="); pw.println(mUser);
+        pw.print(prefix); pw.print("mUserId="); pw.println(mUserId);
+        pw.print(prefix); pw.print("mUid="); pw.println(mUid);
         pw.print(prefix); pw.print("mComponent="); pw.println(mComponent.flattenToShortString());
         pw.print(prefix); pw.print("mBound="); pw.println(mBound);
         pw.print(prefix); pw.print("mService="); pw.println(mService);
+        pw.print(prefix); pw.print("mEstimateTimeOfDeath=");
+            TimeUtils.formatDuration(mEstimateTimeOfDeath, SystemClock.uptimeMillis(), pw);
+        pw.println();
 
         if (DEBUG) {
             // ServiceInfo dump is too noisy and redundant (it can be obtained through other dumps)
@@ -265,11 +306,20 @@
                 pw.print(prefix2); pw.print(i); pw.print(": "); pw.println(mRequestHistory.get(i));
             }
         }
+        if (mQueuedRequests.isEmpty()) {
+            pw.print(prefix); pw.println("No queued requests");
+        } else {
+            pw.print(prefix); pw.println("Queued requests:");
+            final String prefix2 = prefix + prefix;
+            for (int i = 0; i < mQueuedRequests.size(); i++) {
+                pw.print(prefix2); pw.print(i); pw.print(": "); pw.println(mQueuedRequests.get(i));
+            }
+        }
     }
 
     @Override
     public String toString() {
-        return "[AutoFillManagerServiceImpl: user=" + mUser
+        return "[AutoFillManagerServiceImpl: userId=" + mUserId + ", uid=" + mUid
                 + ", component=" + mComponent.flattenToShortString() + "]";
     }
 }
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java
index c9037fc..6406b8a 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java
@@ -66,8 +66,8 @@
 
     private int requestAutoFill() throws RemoteException {
         final int userId = getUserIdFromArgs();
-        final boolean ok = mService.requestAutoFill(userId, null);
-        return ok ? 0 : 1;
+        mService.requestAutoFill(userId, null);
+        return 0;
     }
 
     private int getUserIdFromArgs() {