Merge "Kernel mapping for package scope by user"
diff --git a/api/current.txt b/api/current.txt
index bcc3fb3..decd819 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -9925,6 +9925,15 @@
     method public final int compare(android.content.pm.ApplicationInfo, android.content.pm.ApplicationInfo);
   }
 
+  public final class ChangedPackages implements android.os.Parcelable {
+    ctor public ChangedPackages(int, java.util.List<java.lang.String>);
+    method public int describeContents();
+    method public java.util.List<java.lang.String> getPackageNames();
+    method public int getSequenceNumber();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.content.pm.ChangedPackages> CREATOR;
+  }
+
   public class ComponentInfo extends android.content.pm.PackageItemInfo {
     ctor public ComponentInfo();
     ctor public ComponentInfo(android.content.pm.ComponentInfo);
@@ -10271,6 +10280,7 @@
     method public abstract java.lang.CharSequence getApplicationLabel(android.content.pm.ApplicationInfo);
     method public abstract android.graphics.drawable.Drawable getApplicationLogo(android.content.pm.ApplicationInfo);
     method public abstract android.graphics.drawable.Drawable getApplicationLogo(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract android.content.pm.ChangedPackages getChangedPackages(int);
     method public abstract int getComponentEnabledSetting(android.content.ComponentName);
     method public abstract android.graphics.drawable.Drawable getDefaultActivityIcon();
     method public abstract android.graphics.drawable.Drawable getDrawable(java.lang.String, int, android.content.pm.ApplicationInfo);
@@ -40065,6 +40075,7 @@
     method public java.lang.CharSequence getApplicationLabel(android.content.pm.ApplicationInfo);
     method public android.graphics.drawable.Drawable getApplicationLogo(android.content.pm.ApplicationInfo);
     method public android.graphics.drawable.Drawable getApplicationLogo(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.pm.ChangedPackages getChangedPackages(int);
     method public int getComponentEnabledSetting(android.content.ComponentName);
     method public android.graphics.drawable.Drawable getDefaultActivityIcon();
     method public android.graphics.drawable.Drawable getDrawable(java.lang.String, int, android.content.pm.ApplicationInfo);
@@ -47318,7 +47329,7 @@
 
   public final class TextClassificationManager {
     method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence);
-    method public android.view.textclassifier.TextClassifier getDefaultTextClassifier();
+    method public synchronized android.view.textclassifier.TextClassifier getDefaultTextClassifier();
   }
 
   public final class TextClassificationResult {
diff --git a/api/system-current.txt b/api/system-current.txt
index 5ac97c1..bfb6733 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -10373,6 +10373,15 @@
     method public final int compare(android.content.pm.ApplicationInfo, android.content.pm.ApplicationInfo);
   }
 
+  public final class ChangedPackages implements android.os.Parcelable {
+    ctor public ChangedPackages(int, java.util.List<java.lang.String>);
+    method public int describeContents();
+    method public java.util.List<java.lang.String> getPackageNames();
+    method public int getSequenceNumber();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.content.pm.ChangedPackages> CREATOR;
+  }
+
   public class ComponentInfo extends android.content.pm.PackageItemInfo {
     ctor public ComponentInfo();
     ctor public ComponentInfo(android.content.pm.ComponentInfo);
@@ -10770,6 +10779,7 @@
     method public abstract java.lang.CharSequence getApplicationLabel(android.content.pm.ApplicationInfo);
     method public abstract android.graphics.drawable.Drawable getApplicationLogo(android.content.pm.ApplicationInfo);
     method public abstract android.graphics.drawable.Drawable getApplicationLogo(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract android.content.pm.ChangedPackages getChangedPackages(int);
     method public abstract int getComponentEnabledSetting(android.content.ComponentName);
     method public abstract android.graphics.drawable.Drawable getDefaultActivityIcon();
     method public abstract java.lang.String getDefaultBrowserPackageNameAsUser(int);
@@ -43490,6 +43500,7 @@
     method public java.lang.CharSequence getApplicationLabel(android.content.pm.ApplicationInfo);
     method public android.graphics.drawable.Drawable getApplicationLogo(android.content.pm.ApplicationInfo);
     method public android.graphics.drawable.Drawable getApplicationLogo(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.pm.ChangedPackages getChangedPackages(int);
     method public int getComponentEnabledSetting(android.content.ComponentName);
     method public android.graphics.drawable.Drawable getDefaultActivityIcon();
     method public java.lang.String getDefaultBrowserPackageNameAsUser(int);
@@ -50759,7 +50770,7 @@
 
   public final class TextClassificationManager {
     method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence);
-    method public android.view.textclassifier.TextClassifier getDefaultTextClassifier();
+    method public synchronized android.view.textclassifier.TextClassifier getDefaultTextClassifier();
   }
 
   public final class TextClassificationResult {
diff --git a/api/test-current.txt b/api/test-current.txt
index a5265b0..fbd6b5e 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -9953,6 +9953,15 @@
     method public final int compare(android.content.pm.ApplicationInfo, android.content.pm.ApplicationInfo);
   }
 
+  public final class ChangedPackages implements android.os.Parcelable {
+    ctor public ChangedPackages(int, java.util.List<java.lang.String>);
+    method public int describeContents();
+    method public java.util.List<java.lang.String> getPackageNames();
+    method public int getSequenceNumber();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.content.pm.ChangedPackages> CREATOR;
+  }
+
   public class ComponentInfo extends android.content.pm.PackageItemInfo {
     ctor public ComponentInfo();
     ctor public ComponentInfo(android.content.pm.ComponentInfo);
@@ -10300,6 +10309,7 @@
     method public abstract java.lang.CharSequence getApplicationLabel(android.content.pm.ApplicationInfo);
     method public abstract android.graphics.drawable.Drawable getApplicationLogo(android.content.pm.ApplicationInfo);
     method public abstract android.graphics.drawable.Drawable getApplicationLogo(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract android.content.pm.ChangedPackages getChangedPackages(int);
     method public abstract int getComponentEnabledSetting(android.content.ComponentName);
     method public abstract android.graphics.drawable.Drawable getDefaultActivityIcon();
     method public abstract java.lang.String getDefaultBrowserPackageNameAsUser(int);
@@ -40202,6 +40212,7 @@
     method public java.lang.CharSequence getApplicationLabel(android.content.pm.ApplicationInfo);
     method public android.graphics.drawable.Drawable getApplicationLogo(android.content.pm.ApplicationInfo);
     method public android.graphics.drawable.Drawable getApplicationLogo(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.pm.ChangedPackages getChangedPackages(int);
     method public int getComponentEnabledSetting(android.content.ComponentName);
     method public android.graphics.drawable.Drawable getDefaultActivityIcon();
     method public java.lang.String getDefaultBrowserPackageNameAsUser(int);
@@ -47632,7 +47643,7 @@
 
   public final class TextClassificationManager {
     method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence);
-    method public android.view.textclassifier.TextClassifier getDefaultTextClassifier();
+    method public synchronized android.view.textclassifier.TextClassifier getDefaultTextClassifier();
   }
 
   public final class TextClassificationResult {
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 0c6c4ba..333e412 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -29,6 +29,7 @@
 import android.content.IntentSender;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.ChangedPackages;
 import android.content.pm.ComponentInfo;
 import android.content.pm.InstantAppInfo;
 import android.content.pm.FeatureInfo;
@@ -506,6 +507,15 @@
     }
 
     @Override
+    public ChangedPackages getChangedPackages(int sequenceNumber) {
+        try {
+            return mPM.getChangedPackages(sequenceNumber, mContext.getUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @Override
     @SuppressWarnings("unchecked")
     public FeatureInfo[] getSystemAvailableFeatures() {
         try {
diff --git a/core/java/android/content/pm/ChangedPackages.aidl b/core/java/android/content/pm/ChangedPackages.aidl
new file mode 100644
index 0000000..1a9f5a1
--- /dev/null
+++ b/core/java/android/content/pm/ChangedPackages.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2017, 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.content.pm;
+
+parcelable ChangedPackages;
\ No newline at end of file
diff --git a/core/java/android/content/pm/ChangedPackages.java b/core/java/android/content/pm/ChangedPackages.java
new file mode 100644
index 0000000..94b8a5d
--- /dev/null
+++ b/core/java/android/content/pm/ChangedPackages.java
@@ -0,0 +1,82 @@
+/**
+ * Copyright (c) 2017, 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.content.pm;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Intent;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.List;
+
+/**
+ * Packages that have been changed since the last time they
+ * were requested.
+ */
+public final class ChangedPackages implements Parcelable {
+    /** The last known sequence number for these changes */
+    private final int mSequenceNumber;
+    /** The names of the packages that have changed */
+    private final List<String> mPackageNames;
+
+    public ChangedPackages(int sequenceNumber, @NonNull List<String> packageNames) {
+        this.mSequenceNumber = sequenceNumber;
+        this.mPackageNames = packageNames;
+    }
+
+    /** @hide */
+    protected ChangedPackages(Parcel in) {
+        mSequenceNumber = in.readInt();
+        mPackageNames = in.createStringArrayList();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mSequenceNumber);
+        dest.writeStringList(mPackageNames);
+    }
+
+    /**
+     * Returns the last known sequence number for these changes.
+     */
+    public int getSequenceNumber() {
+        return mSequenceNumber;
+    }
+
+    /**
+     * Returns the names of the packages that have changed.
+     */
+    public @NonNull List<String> getPackageNames() {
+        return mPackageNames;
+    }
+
+    public static final Parcelable.Creator<ChangedPackages> CREATOR =
+            new Parcelable.Creator<ChangedPackages>() {
+        public ChangedPackages createFromParcel(Parcel in) {
+            return new ChangedPackages(in);
+        }
+
+        public ChangedPackages[] newArray(int size) {
+            return new ChangedPackages[size];
+        }
+    };
+}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 3fb46cf..9d36a73 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -23,6 +23,7 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ContainerEncryptionParams;
+import android.content.pm.ChangedPackages;
 import android.content.pm.InstantAppInfo;
 import android.content.pm.FeatureInfo;
 import android.content.pm.IPackageInstallObserver2;
@@ -611,6 +612,8 @@
     String getServicesSystemSharedLibraryPackageName();
     String getSharedSystemSharedLibraryPackageName();
 
+    ChangedPackages getChangedPackages(int sequenceNumber, int userId);
+
     boolean isPackageDeviceAdminOnAnyUser(String packageName);
 
     List<String> getPreviousCodePaths(in String packageName);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index b20b5e2..308153d 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -20,6 +20,7 @@
 import android.annotation.CheckResult;
 import android.annotation.DrawableRes;
 import android.annotation.IntDef;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -3853,6 +3854,17 @@
     public abstract @NonNull String getSharedSystemSharedLibraryPackageName();
 
     /**
+     * Returns the names of the packages that have been changed
+     * [eg. added, removed or updated] since the given sequence
+     * number.
+     * <p>If no packages have been changed, returns <code>null</code>.
+     * <p>The sequence number starts at <code>0</code> and is
+     * reset every boot.
+     */
+    public abstract @Nullable ChangedPackages getChangedPackages(
+            @IntRange(from=0) int sequenceNumber);
+
+    /**
      * Get a list of features that are available on the
      * system.
      *
diff --git a/core/java/com/android/internal/widget/SwipeDismissLayout.java b/core/java/com/android/internal/widget/SwipeDismissLayout.java
index 261fa43..6d814bf 100644
--- a/core/java/com/android/internal/widget/SwipeDismissLayout.java
+++ b/core/java/com/android/internal/widget/SwipeDismissLayout.java
@@ -79,7 +79,6 @@
     private boolean mDismissed;
     private boolean mDiscardIntercept;
     private VelocityTracker mVelocityTracker;
-    private float mTranslationX;
     private boolean mBlockGesture = false;
     private boolean mActivityTranslucencyConverted = false;
 
@@ -166,8 +165,10 @@
             return super.onInterceptTouchEvent(ev);
         }
 
-        // offset because the view is translated during swipe
-        ev.offsetLocation(mTranslationX, 0);
+        // Offset because the view is translated during swipe, match X with raw X. Active touch
+        // coordinates are mostly used by the velocity tracker, so offset it to match the raw
+        // coordinates which is what is primarily used elsewhere.
+        ev.offsetLocation(ev.getRawX() - ev.getX(), 0);
 
         switch (ev.getActionMasked()) {
             case MotionEvent.ACTION_DOWN:
@@ -232,8 +233,12 @@
         if (mVelocityTracker == null || !mDismissable) {
             return super.onTouchEvent(ev);
         }
-        // offset because the view is translated during swipe
-        ev.offsetLocation(mTranslationX, 0);
+
+        // Offset because the view is translated during swipe, match X with raw X. Active touch
+        // coordinates are mostly used by the velocity tracker, so offset it to match the raw
+        // coordinates which is what is primarily used elsewhere.
+        ev.offsetLocation(ev.getRawX() - ev.getX(), 0);
+
         switch (ev.getActionMasked()) {
             case MotionEvent.ACTION_UP:
                 updateDismiss(ev);
@@ -266,7 +271,6 @@
     }
 
     private void setProgress(float deltaX) {
-        mTranslationX = deltaX;
         if (mProgressListener != null && deltaX >= 0)  {
             mProgressListener.onSwipeProgressChanged(
                     this, progressToAlpha(deltaX / getWidth()), deltaX);
@@ -300,7 +304,6 @@
             mVelocityTracker.recycle();
         }
         mVelocityTracker = null;
-        mTranslationX = 0;
         mDownX = 0;
         mLastX = Integer.MIN_VALUE;
         mDownY = 0;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 55491b2..8de4e58 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -130,6 +130,7 @@
                 launchOpts.numVisibleTaskThumbnails = 2;
                 launchOpts.onlyLoadForCache = true;
                 launchOpts.onlyLoadPausedActivities = true;
+                launchOpts.loadThumbnails = !ActivityManager.ENABLE_TASK_SNAPSHOTS;
                 loader.loadTasks(mContext, plan, launchOpts);
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 5366da1..995901b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -164,15 +164,19 @@
         }
     }
 
-    public void disable(int state1, int state2) {
+    public void disable(int state1, int state2, boolean animate) {
         synchronized (mLock) {
             mDisable1 = state1;
             mDisable2 = state2;
             mHandler.removeMessages(MSG_DISABLE);
-            mHandler.obtainMessage(MSG_DISABLE, state1, state2, null).sendToTarget();
+            mHandler.obtainMessage(MSG_DISABLE, state1, state2, animate).sendToTarget();
         }
     }
 
+    public void disable(int state1, int state2) {
+        disable(state1, state2, true);
+    }
+
     public void animateExpandNotificationsPanel() {
         synchronized (mLock) {
             mHandler.removeMessages(MSG_EXPAND_NOTIFICATIONS);
@@ -433,7 +437,7 @@
                 }
                 case MSG_DISABLE:
                     for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).disable(msg.arg1, msg.arg2, true /* animate */);
+                        mCallbacks.get(i).disable(msg.arg1, msg.arg2, (Boolean) msg.obj);
                     }
                     break;
                 case MSG_EXPAND_NOTIFICATIONS:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 2667d84..ac13cf4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -839,7 +839,7 @@
         createAndAddWindows();
 
         mSettingsObserver.onChange(false); // set up
-        disable(switches[0], switches[6], false /* animate */);
+        mCommandQueue.disable(switches[0], switches[6], false /* animate */);
         setSystemUiVisibility(switches[1], switches[7], switches[8], 0xffffffff,
                 fullscreenStackBounds, dockedStackBounds);
         topAppWindowChanged(switches[2] != 0);
@@ -2511,7 +2511,7 @@
      * This needs to be called if state used by {@link #adjustDisableFlags} changes.
      */
     public void recomputeDisableFlags(boolean animate) {
-        disable(mDisabledUnmodified1, mDisabledUnmodified2, animate);
+        mCommandQueue.disable(mDisabledUnmodified1, mDisabledUnmodified2, animate);
     }
 
     protected H createHandler() {
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
index 8d43dfb..85bf5c2 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
@@ -39,6 +39,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
 import android.graphics.Rect;
@@ -181,6 +182,23 @@
         updateLocked();
     }
 
+    CharSequence getServiceName() {
+        if (mInfo == null) {
+            return null;
+        }
+        final ComponentName serviceComponent = mInfo.getServiceInfo().getComponentName();
+        final String packageName = serviceComponent.getPackageName();
+
+        try {
+            final PackageManager pm = mContext.getPackageManager();
+            final ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
+            return pm.getApplicationLabel(info);
+        } catch (Exception e) {
+            Slog.w(TAG, "Could not get label for " + packageName + ": " + e);
+            return packageName;
+        }
+    }
+
     void updateLocked() {
         ComponentName serviceComponent = null;
         ServiceInfo serviceInfo = null;
@@ -438,14 +456,20 @@
 
         final AutoFillId mId;
         private final Listener mListener;
-        // // TODO(b/33197203): does it really need a reference to the session's response?
-        private FillResponse mResponse;
+        // TODO(b/33197203): would not need a reference to response and session if it was an inner
+        // class of Session...
+        private final Session mSession;
+        // TODO(b/33197203): encapsulate access so it's not called by UI
+        FillResponse mResponse;
+        Intent mAuthIntent;
+
         private AutoFillValue mAutoFillValue;
         private Rect mBounds;
 
         private boolean mValueUpdated;
 
-        ViewState(AutoFillId id, Listener listener) {
+        ViewState(Session session, AutoFillId id, Listener listener) {
+            mSession = session;
             mId = id;
             mListener = listener;
         }
@@ -458,6 +482,18 @@
             maybeCallOnFillReady();
         }
 
+        /**
+         * Used when a {@link FillResponse} requires authentication to be unlocked.
+         */
+        void setResponse(FillResponse response, Intent authIntent) {
+            mAuthIntent = authIntent;
+            setResponse(response);
+        }
+
+        CharSequence getServiceName() {
+            return mSession.getServiceName();
+        }
+
         // TODO(b/33197203): need to refactor / rename / document this method to make it clear that
         // it can change  the value and update the UI; similarly, should replace code that
         // directly sets mAutoFilLValue to use encapsulation.
@@ -495,6 +531,7 @@
             pw.print(prefix); pw.print("value:" ); pw.println(mAutoFillValue);
             pw.print(prefix); pw.print("updated:" ); pw.println(mValueUpdated);
             pw.print(prefix); pw.print("bounds:" ); pw.println(mBounds);
+            pw.print(prefix); pw.print("authIntent:" ); pw.println(mAuthIntent);
         }
     }
 
@@ -565,7 +602,6 @@
             }
         }
 
-
         // FillServiceCallbacks
         @Override
         public void onFillRequestSuccess(FillResponse response) {
@@ -763,7 +799,7 @@
 
             ViewState viewState = mViewStates.get(id);
             if (viewState == null) {
-                viewState = new ViewState(id, this);
+                viewState = new ViewState(this, id, this);
                 mViewStates.put(id, viewState);
             }
 
@@ -844,13 +880,19 @@
 
             // TODO(b/33197203): add MetricsLogger calls
 
+            if (mCurrentViewState == null) {
+                // TODO(b/33197203): temporary sanity check; should never happen
+                Slog.w(TAG, "processResponseLocked(): mCurrentResponse is null");
+                return;
+            }
+
             mCurrentResponse = response;
 
             if (mCurrentResponse.getAuthentication() != null) {
                 // Handle authentication.
                 final Intent fillInIntent = createAuthFillInIntent(mStructure);
-                getUiForShowing().showFillResponseAuthRequest(
-                        mCurrentResponse.getAuthentication(), fillInIntent);
+
+                mCurrentViewState.setResponse(mCurrentResponse, fillInIntent);
                 return;
             }
 
@@ -864,10 +906,7 @@
                 return;
             }
 
-            // TODO(b/33197203): Consider using mCurrentResponse, depends on partitioning design
-            if (mCurrentViewState != null) {
-                mCurrentViewState.setResponse(mCurrentResponse);
-            }
+            mCurrentViewState.setResponse(mCurrentResponse);
         }
 
         void autoFill(Dataset dataset) {
@@ -884,6 +923,10 @@
             }
         }
 
+        CharSequence getServiceName() {
+            return AutoFillManagerServiceImpl.this.getServiceName();
+        }
+
         private Intent createAuthFillInIntent(AssistStructure structure) {
             Intent fillInIntent = new Intent();
             fillInIntent.putExtra(AutoFillManager.EXTRA_ASSIST_STRUCTURE, structure);
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/AutoFillUI.java
index 9770040..e83dc1e 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillUI.java
@@ -56,19 +56,15 @@
     private static final long SNACK_BAR_LIFETIME_MS = 30 * DateUtils.SECOND_IN_MILLIS;
     private static final int MSG_HIDE_SNACK_BAR = 1;
 
-    private static final String EXTRA_AUTH_INTENT_SENDER =
-            "com.android.server.autofill.extra.AUTH_INTENT_SENDER";
-    private static final String EXTRA_AUTH_FILL_IN_INTENT =
-            "com.android.server.autofill.extra.AUTH_FILL_IN_INTENT";
-
     private final Context mContext;
     private final WindowManager mWm;
 
     // TODO(b/33197203) Fix locking - some state requires lock and some not - requires refactoring
+    private final Object mLock = new Object();
 
     // Fill UI variables
     private AnchoredWindow mFillWindow;
-    private DatasetPicker mFillView;
+    private View mFillView;
     private ViewState mViewState;
 
     private AutoFillUiCallback mCallback;
@@ -156,63 +152,76 @@
 
         UiThread.getHandler().runWithScissors(() -> {
             hideSnackbarUiThread();
-            hideFillResponseAuthUiUiThread();
         }, 0);
 
-        if (datasets == null) {
+        if (datasets == null && viewState.mAuthIntent == null) {
             // TODO(b/33197203): shouldn't be called, but keeping the WTF for a while just to be
             // safe, otherwise it would crash system server...
             Slog.wtf(TAG, "showFillUI(): no dataset");
             return;
         }
 
+        // TODO(b/33197203): should not display UI after we launched an authentication intent, since
+        // we have no warranty the provider will call onFailure() if the authentication failed or
+        // user dismissed the auth window
+        // because if the service does not handle calling the callback,
+
+
         UiThread.getHandler().runWithScissors(() -> {
+            // The dataset picker is only shown when authentication is not required...
+            DatasetPicker datasetPicker = null;
+
             if (mViewState == null || !mViewState.mId.equals(viewState.mId)) {
                 hideFillUiUiThread();
 
                 mViewState = viewState;
+                if (viewState.mAuthIntent != null) {
+                    final CharSequence serviceName = viewState.getServiceName();
 
-                mFillView = new DatasetPicker(mContext, datasets,
-                        (dataset) -> {
-                            final AutoFillUiCallback callback;
-                            synchronized (mLock) {
-                                callback = mCallback;
-                            }
-                            if (callback != null) {
-                                callback.fill(dataset);
-                            } else {
-                                Slog.w(TAG, "null callback on showFillUi() for " + viewState.mId);
-                            }
-                            hideFillUi();
-                        });
+                    mFillView = new SignInPrompt(mContext, serviceName, (e) -> {
+                        final IntentSender intentSender = viewState.mResponse.getAuthentication();
+                        final AutoFillUiCallback callback;
+                        final Intent authIntent;
+                        synchronized (mLock) {
+                            callback = mCallback;
+                            authIntent = viewState.mAuthIntent;
+                            // Must reset the authentication intent so UI display the datasets after
+                            // the user authenticated.
+                            viewState.mAuthIntent = null;
+                        }
+                        if (callback != null) {
+                            callback.authenticate(intentSender, authIntent);
+                        } else {
+                            // TODO(b/33197203): need to figure out why it's null sometimes
+                            Slog.w(TAG, "no callback on showFillUi().auth for " + viewState.mId);
+                        }
+                    });
 
+                } else {
+                    mFillView = datasetPicker = new DatasetPicker(mContext, datasets,
+                            (dataset) -> {
+                                final AutoFillUiCallback callback;
+                                synchronized (mLock) {
+                                    callback = mCallback;
+                                }
+                                if (callback != null) {
+                                    callback.fill(dataset);
+                                } else {
+                                    // TODO(b/33197203): need to figure out why it's null sometimes
+                                    Slog.w(TAG, "no callback on showFillUi() for " + viewState.mId);
+                                }
+                                hideFillUiUiThread();
+                            });
+                }
                 mFillWindow = new AnchoredWindow(mWm, appToken, mFillView);
 
-                if (DEBUG) Slog.d(TAG, "showFillUi(): view changed");
+                if (DEBUG) Slog.d(TAG, "showFillUi(): view changed for: " + viewState.mId);
             }
-
-            if (DEBUG) Slog.d(TAG, "showFillUi(): bounds=" + bounds + ", filterText=" + filterText);
-            mFillView.update(filterText);
+            if (datasetPicker != null) {
+                datasetPicker.update(filterText);
+            }
             mFillWindow.show(bounds);
-        }, 0);
-    }
 
-    /**
-     * Shows an UI affordance indicating that user action is required before a {@link
-     * android.service.autofill.FillResponse}
-     * can be used.
-     *
-     * <p>It typically replaces the auto-fill bar with a message saying "Press fingerprint or tap to
-     * autofill" or "Tap to autofill", depending on the value of {@code usesFingerprint}.
-     */
-    void showFillResponseAuthRequest(IntentSender intent, Intent fillInIntent) {
-        if (!hasCallback()) {
-            return;
-        }
-        hideAll();
-        UiThread.getHandler().runWithScissors(() -> {
-            // TODO(b/33197203): proper implementation
-            showFillResponseAuthUiUiThread(intent, fillInIntent);
         }, 0);
     }
 
@@ -250,14 +259,12 @@
         UiThread.getHandler().runWithScissors(() -> {
             hideSnackbarUiThread();
             hideFillUiUiThread();
-            hideFillResponseAuthUiUiThread();
         }, 0);
     }
 
     void dump(PrintWriter pw) {
         pw.println("AufoFill UI");
         final String prefix = "  ";
-        pw.print(prefix); pw.print("sResultCode: "); pw.println(sResultCode);
         pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken);
         pw.print(prefix); pw.print("mSnackBar: "); pw.println(mSnackbar);
         pw.print(prefix); pw.print("mViewState: "); pw.println(mViewState);
@@ -310,103 +317,4 @@
         void fill(Dataset dataset);
         void save();
     }
-
-    /////////////////////////////////////////////////////////////////////////////////
-    // TODO(b/33197203): 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(b/33197203): remove from frameworks/base/core/res/AndroidManifest.xml once not used
-    private static final String NOTIFICATION_AUTO_FILL_INTENT =
-            "com.android.internal.autofill.action.REQUEST_AUTOFILL";
-
-    private BroadcastReceiver mNotificationReceiver;
-    private final Object mLock = new Object();
-
-    // Hack used to generate unique pending intents
-    static int sResultCode = 0;
-
-    private void ensureNotificationListener() {
-        synchronized (mLock) {
-            if (mNotificationReceiver == null) {
-                mNotificationReceiver = new NotificationReceiver();
-                mContext.registerReceiver(mNotificationReceiver,
-                        new IntentFilter(NOTIFICATION_AUTO_FILL_INTENT));
-            }
-        }
-    }
-
-    final class NotificationReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            final AutoFillUiCallback callback;
-            synchronized (mLock) {
-                callback = mCallback;
-            }
-            if (callback != null) {
-                IntentSender intentSender = intent.getParcelableExtra(EXTRA_AUTH_INTENT_SENDER);
-                Intent fillInIntent = intent.getParcelableExtra(EXTRA_AUTH_FILL_IN_INTENT);
-                callback.authenticate(intentSender, fillInIntent);
-            }
-            collapseStatusBar();
-        }
-    }
-
-    @android.annotation.UiThread
-    private void showFillResponseAuthUiUiThread(IntentSender intent, Intent fillInIntent) {
-        final String title = "AutoFill Authentication";
-        final StringBuilder subTitle = new StringBuilder("Provider require user authentication.\n");
-
-        final Intent authIntent = new Intent(NOTIFICATION_AUTO_FILL_INTENT);
-        authIntent.putExtra(EXTRA_AUTH_INTENT_SENDER, intent);
-        authIntent.putExtra(EXTRA_AUTH_FILL_IN_INTENT, fillInIntent);
-
-        final PendingIntent authPendingIntent = PendingIntent.getBroadcast(
-                mContext, ++sResultCode, authIntent, PendingIntent.FLAG_ONE_SHOT);
-
-        subTitle.append("Tap notification to launch its authentication UI.");
-
-        final Notification.Builder notification = newNotificationBuilder()
-                .setAutoCancel(true)
-                .setOngoing(false)
-                .setContentTitle(title)
-                .setStyle(new Notification.BigTextStyle().bigText(subTitle.toString()))
-                .setContentIntent(authPendingIntent);
-
-        ensureNotificationListener();
-
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            NotificationManager.from(mContext).notify(0, notification.build());
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-    }
-
-    @android.annotation.UiThread
-    private void hideFillResponseAuthUiUiThread() {
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            NotificationManager.from(mContext).cancel(0);
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-    }
-
-    private Notification.Builder newNotificationBuilder() {
-        return new Notification.Builder(mContext)
-                .setCategory(Notification.CATEGORY_SYSTEM)
-                .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
-                .setLocalOnly(true)
-                .setColor(mContext.getColor(
-                        com.android.internal.R.color.system_notification_accent_color));
-    }
-
-    private void collapseStatusBar() {
-        final StatusBarManager sbm = (StatusBarManager) mContext.getSystemService("statusbar");
-        sbm.collapsePanels();
-    }
-    /////////////////////////////////////////
-    // End of temporary notification code. //
-    /////////////////////////////////////////
 }
diff --git a/services/autofill/java/com/android/server/autofill/SignInPrompt.java b/services/autofill/java/com/android/server/autofill/SignInPrompt.java
new file mode 100644
index 0000000..6d17acd
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/SignInPrompt.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.autofill;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.Button;
+
+/**
+ * A view displaying the sign-in prompt for an auto-fill service.
+ */
+final class SignInPrompt extends Button {
+
+    SignInPrompt(Context context, CharSequence serviceName, View.OnClickListener listener) {
+        super(context);
+        // TODO(b/33197203): use strings.xml
+        final String text = serviceName != null
+                ? "Sign in to " + serviceName + " to autofill"
+                : "Sign in to autofill";
+
+        // TODO(b/33197203): polish UI / use better altenative than a button...
+        setText(text);
+        setOnClickListener(listener);
+    }
+}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 9ec27b3..0d63f72 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -126,6 +126,7 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.AppsQueryHelper;
+import android.content.pm.ChangedPackages;
 import android.content.pm.ComponentInfo;
 import android.content.pm.InstantAppInfo;
 import android.content.pm.EphemeralRequest;
@@ -720,6 +721,21 @@
 
     private final InstantAppRegistry mInstantAppRegistry;
 
+    @GuardedBy("mPackages")
+    int mChangedPackagesSequenceNumber;
+    /**
+     * List of changed [installed, removed or updated] packages.
+     * mapping from user id -> sequence number -> package name
+     */
+    @GuardedBy("mPackages")
+    final SparseArray<SparseArray<String>> mChangedPackages = new SparseArray<>();
+    /**
+     * The sequence number of the last change to a package.
+     * mapping from user id -> package name -> sequence number
+     */
+    @GuardedBy("mPackages")
+    final SparseArray<Map<String, Integer>> mChangedPackagesSequenceNumbers = new SparseArray<>();
+
     public static final class SharedLibraryEntry {
         public final String path;
         public final String apk;
@@ -4221,6 +4237,52 @@
         }
     }
 
+    private void updateSequenceNumberLP(String packageName, int[] userList) {
+        for (int i = userList.length - 1; i >= 0; --i) {
+            final int userId = userList[i];
+            SparseArray<String> changedPackages = mChangedPackages.get(userId);
+            if (changedPackages == null) {
+                changedPackages = new SparseArray<>();
+                mChangedPackages.put(userId, changedPackages);
+            }
+            Map<String, Integer> sequenceNumbers = mChangedPackagesSequenceNumbers.get(userId);
+            if (sequenceNumbers == null) {
+                sequenceNumbers = new HashMap<>();
+                mChangedPackagesSequenceNumbers.put(userId, sequenceNumbers);
+            }
+            final Integer sequenceNumber = sequenceNumbers.get(packageName);
+            if (sequenceNumber != null) {
+                changedPackages.remove(sequenceNumber);
+            }
+            changedPackages.put(mChangedPackagesSequenceNumber, packageName);
+            sequenceNumbers.put(packageName, mChangedPackagesSequenceNumber);
+        }
+        mChangedPackagesSequenceNumber++;
+    }
+
+    @Override
+    public ChangedPackages getChangedPackages(int sequenceNumber, int userId) {
+        synchronized (mPackages) {
+            if (sequenceNumber >= mChangedPackagesSequenceNumber) {
+                return null;
+            }
+            final SparseArray<String> changedPackages = mChangedPackages.get(userId);
+            if (changedPackages == null) {
+                return null;
+            }
+            final List<String> packageNames =
+                    new ArrayList<>(mChangedPackagesSequenceNumber - sequenceNumber);
+            for (int i = sequenceNumber; i < mChangedPackagesSequenceNumber; i++) {
+                final String packageName = changedPackages.get(i);
+                if (packageName != null) {
+                    packageNames.add(packageName);
+                }
+            }
+            return packageNames.isEmpty()
+                    ? null : new ChangedPackages(mChangedPackagesSequenceNumber, packageNames);
+        }
+    }
+
     @Override
     public @NonNull ParceledListSlice<FeatureInfo> getSystemAvailableFeatures() {
         ArrayList<FeatureInfo> res;
@@ -13265,6 +13327,9 @@
                     }
                 }
                 sendPackageAddedForUser(packageName, pkgSetting, userId);
+                synchronized (mPackages) {
+                    updateSequenceNumberLP(packageName, new int[]{ userId });
+                }
             }
         } finally {
             Binder.restoreCallingIdentity(callingId);
@@ -16851,6 +16916,10 @@
                             sUserManager.getUserIds(), true);
                 }
             }
+
+            if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
+                updateSequenceNumberLP(pkgName, res.newUsers);
+            }
         }
     }
 
@@ -17433,6 +17502,7 @@
                 if (res) {
                     mInstantAppRegistry.onPackageUninstalledLPw(uninstalledPs.pkg,
                             info.removedUsers);
+                    updateSequenceNumberLP(packageName, info.removedUsers);
                 }
             }
         }
@@ -19745,6 +19815,7 @@
                 }
             }
             scheduleWritePackageRestrictionsLocked(userId);
+            updateSequenceNumberLP(packageName, new int[] { userId });
             components = mPendingBroadcasts.get(userId, packageName);
             final boolean newPackage = components == null;
             if (newPackage) {
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index 7e7de21..4814a74 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -75,6 +75,9 @@
     // Append targetSdkVersion=n to existing seinfo label where n is the app's targetSdkVersion
     private static final String TARGETSDKVERSION_STR = ":targetSdkVersion=";
 
+    // Append targetSdkVersion=n to existing seinfo label where n is the app's targetSdkVersion
+    private static final String TARGETSDKVERSION_STR = ":targetSdkVersion=";
+
     /**
      * Load the mac_permissions.xml file containing all seinfo assignments used to
      * label apps. The loaded mac_permissions.xml file is determined by the
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 0dcd0f1..d51d75e 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -24,6 +24,7 @@
 import android.content.IntentSender;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.ChangedPackages;
 import android.content.pm.InstantAppInfo;
 import android.content.pm.FeatureInfo;
 import android.content.pm.IPackageDataObserver;
@@ -374,6 +375,12 @@
         throw new UnsupportedOperationException();
     }
 
+    /** @hide */
+    @Override
+    public ChangedPackages getChangedPackages(int sequenceNumber) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public ResolveInfo resolveActivity(Intent intent, int flags) {
         throw new UnsupportedOperationException();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
index 00799a1..0039476 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
@@ -24,6 +24,7 @@
 import android.content.IntentSender;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.ChangedPackages;
 import android.content.pm.InstantAppInfo;
 import android.content.pm.FeatureInfo;
 import android.content.pm.IPackageDataObserver;
@@ -859,6 +860,11 @@
     }
 
     @Override
+    public ChangedPackages getChangedPackages(int sequenceNumber) {
+        return null;
+    }
+
+    @Override
     public boolean isUpgrade() {
         return false;
     }