Merge "Call userActivity when dismissing keyguard" into nyc-mr1-dev
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 83e2678..0ba937a 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -171,4 +171,12 @@
      */
     public abstract int startActivitiesAsPackage(String packageName,
             int userId, Intent[] intents, Bundle bOptions);
+
+    /**
+     * Get the procstate for the UID.  The return value will be between
+     * {@link ActivityManager#MIN_PROCESS_STATE} and {@link ActivityManager#MAX_PROCESS_STATE}.
+     * Note if the UID doesn't exist, it'll return {@link ActivityManager#PROCESS_STATE_NONEXISTENT}
+     * (-1).
+     */
+    public abstract int getUidProcessState(int uid);
 }
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 18b72e2..ff514bd 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -312,8 +312,8 @@
         try {
             service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
                     copy, idOut, user.getIdentifier());
-            if (id != idOut[0]) {
-                Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
+            if (localLOGV && id != idOut[0]) {
+                Log.v(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
             }
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index ce2fa81..a42da85 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -242,21 +242,23 @@
     }
 
     private void releaseSurfaceTexture() {
-        boolean shouldRelease = true;
+        if (mSurface != null) {
+            boolean shouldRelease = true;
 
-        if (mListener != null) {
-            shouldRelease = mListener.onSurfaceTextureDestroyed(mSurface);
-        }
+            if (mListener != null) {
+                shouldRelease = mListener.onSurfaceTextureDestroyed(mSurface);
+            }
 
-        synchronized (mNativeWindowLock) {
-            nDestroyNativeWindow();
-        }
+            synchronized (mNativeWindowLock) {
+                nDestroyNativeWindow();
+            }
 
-        if (shouldRelease) {
-            mSurface.release();
+            if (shouldRelease) {
+                mSurface.release();
+            }
+            mSurface = null;
+            mHadSurface = true;
         }
-        mSurface = null;
-        mHadSurface = true;
     }
 
     /**
diff --git a/docs/html/guide/topics/ui/layout/grid.jd b/docs/html/guide/topics/ui/layout/grid.jd
index 31f9b9c..cc53651 100644
--- a/docs/html/guide/topics/ui/layout/grid.jd
+++ b/docs/html/guide/topics/ui/layout/grid.jd
@@ -23,17 +23,32 @@
 
 <img src="{@docRoot}images/ui/gridlayout.png" alt="" />
 
-<p>{@link android.widget.TableLayout} positions its children into rows
-    and columns. TableLayout containers do not display border lines for their rows, columns,
-    or cells. The table will have as many columns as the row with the most cells. A table can leave
-cells empty, but cells cannot span columns, as they can in HTML.</p>
-<p>{@link android.widget.TableRow} objects are the child views of a TableLayout
-(each TableRow defines a single row in the table).
-Each row has zero or more cells, each of which is defined by any kind of other View. So, the cells of a row may be
-composed of a variety of View objects, like ImageView or TextView objects.
-A cell may also be a ViewGroup object (for example, you can nest another TableLayout as a cell).</p>
-<p>The following sample layout has two rows and two cells in each. The accompanying screenshot shows the
-result, with cell borders displayed as dotted lines (added for visual effect). </p>
+<p>
+  {@link android.widget.TableLayout} positions its children into rows and
+  columns. TableLayout containers do not display border lines for their rows,
+  columns, or cells. The table will have as many columns as the row with the
+  most cells. A table can leave cells empty. Cells can span multiple columns,
+  as they can in HTML. You can span columns by using the <code>span</code>
+  field in the {@link android.widget.TableRow.LayoutParams} class.
+</p>
+
+<p class="note">
+  <strong>Note:</strong> Cells cannot span multiple rows.
+</p>
+
+<p>
+  {@link android.widget.TableRow} objects are the child views of a TableLayout
+  (each TableRow defines a single row in the table). Each row has zero or more
+  cells, each of which is defined by any kind of other View. So, the cells of
+  a row may be composed of a variety of View objects, like ImageView or
+  TextView objects. A cell may also be a ViewGroup object (for example, you
+  can nest another TableLayout as a cell).
+</p>
+<p>
+  The following sample layout has two rows and two cells in each. The
+  accompanying screenshot shows the result, with cell borders displayed as
+  dotted lines (added for visual effect).
+</p>
 
 <table class="columns">
     <tr>
diff --git a/docs/html/wear/preview/api-overview.jd b/docs/html/wear/preview/api-overview.jd
index 4233624..0b3ac6b 100644
--- a/docs/html/wear/preview/api-overview.jd
+++ b/docs/html/wear/preview/api-overview.jd
@@ -45,19 +45,19 @@
 <p>
   The Android Wear Preview API is still in active development, but you can try
   it now as part of the Wear 2.0 Developer Preview. The sections below
-  highlight some of the new features for Wear developers.
+  highlight some of the new features for Android Wear developers.
 </p>
 
 
 <h2 id="ui">User Interface Improvements</h2>
 
-<p>The preview introduces powerful additions to the user interface, opening up
-exciting possibilities to developers.
-A complication is any feature in a watch face that displays more than hours and
-minutes. With the Complications API,
- watch faces can display extra information and separate apps can expose complication
-  data.
-The navigation and action drawers provide users with new ways to interact with apps.
+<p>
+  The preview introduces powerful additions to the user interface, opening up
+  exciting possibilities to developers. A complication
+  is any feature in a watch face that displays more than hours and
+  minutes. With the Complications API, watch faces can display extra information
+  and separate apps can expose complication data. The navigation and action
+  drawers provide users with new ways to interact with apps.
 </p>
 
 
@@ -69,8 +69,8 @@
   A <a href=
   "https://en.wikipedia.org/wiki/Complication_(horology)">complication</a> is a
   feature of a watch face that displays more than hours and minutes, such as a
-  battery indicator or a step counter. The Complications API helps watch face
-  developers create these features visual features and data connections they
+  battery indicator or a step counter. The Complications API thus helps watch face
+  developers create visual features and the data connections they
   require.
 </p>
 
diff --git a/packages/Shell/src/com/android/shell/Screenshooter.java b/packages/Shell/src/com/android/shell/Screenshooter.java
index 3f4895b..ce0fbbc 100644
--- a/packages/Shell/src/com/android/shell/Screenshooter.java
+++ b/packages/Shell/src/com/android/shell/Screenshooter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 The Android Open Source Project
+ * 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.
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 2c8a559..3d70969 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -65,6 +65,14 @@
             layout="@layout/keyguard_status_bar"
             android:visibility="invisible" />
 
+        <Button
+            android:id="@+id/report_rejected_touch"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@dimen/status_bar_header_height_keyguard"
+            android:text="@string/report_rejected_touch"
+            android:visibility="gone" />
+
     </com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer>
 
     <include
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 935894c..6c48b25 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1629,6 +1629,9 @@
     <!-- Accessibility label for the notification icons in the collapsed status bar. Not shown on screen [CHAR LIMIT=NONE] -->
     <string name="accessibility_desc_notification_icon"><xliff:g name="app_name" example="Gmail">%1$s</xliff:g> notification: <xliff:g name="notification_text" example="5 new messages">%2$s</xliff:g></string>
 
+    <!-- Label for button that reports a touch that was wrongly rejected by the lockscreen. For debugging only. [CHAR LIMIT=NONE] -->
+    <string name="report_rejected_touch" translatable="false">Report rejected touch</string>
+
     <!-- Multi-Window strings -->
     <!-- Text that gets shown on top of current activity to inform the user that the system force-resized the current activity and that things might crash/not work properly [CHAR LIMIT=NONE] -->
     <string name="dock_forced_resizable">App may not work with split-screen.</string>
diff --git a/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java b/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java
index 91f6520..b1f454e 100644
--- a/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java
+++ b/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java
@@ -21,6 +21,7 @@
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
+import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Build;
 import android.os.Handler;
@@ -28,6 +29,7 @@
 import android.provider.Settings;
 import android.util.Log;
 import android.view.MotionEvent;
+import android.widget.Toast;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -48,6 +50,8 @@
     private static final String TAG = "DataCollector";
     private static final String COLLECTOR_ENABLE = "data_collector_enable";
     private static final String COLLECT_BAD_TOUCHES = "data_collector_collect_bad_touches";
+    private static final String ALLOW_REJECTED_TOUCH_REPORTS =
+            "data_collector_allow_rejected_touch_reports";
 
     private static final long TIMEOUT_MILLIS = 11000; // 11 seconds.
     public static final boolean DEBUG = false;
@@ -64,6 +68,7 @@
     private boolean mCollectBadTouches = false;
     private boolean mCornerSwiping = false;
     private boolean mTrackingStarted = false;
+    private boolean mAllowReportRejectedTouch = false;
 
     private static DataCollector sInstance = null;
 
@@ -87,6 +92,11 @@
                 mSettingsObserver,
                 UserHandle.USER_ALL);
 
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(ALLOW_REJECTED_TOUCH_REPORTS), false,
+                mSettingsObserver,
+                UserHandle.USER_ALL);
+
         updateConfiguration();
     }
 
@@ -104,10 +114,13 @@
         mCollectBadTouches = mEnableCollector && 0 != Settings.Secure.getInt(
                 mContext.getContentResolver(),
                 COLLECT_BAD_TOUCHES, 0);
+        mAllowReportRejectedTouch = Build.IS_DEBUGGABLE && 0 != Settings.Secure.getInt(
+                mContext.getContentResolver(),
+                ALLOW_REJECTED_TOUCH_REPORTS, 0);
     }
 
     private boolean sessionEntrypoint() {
-        if (mEnableCollector && mCurrentSession == null) {
+        if (isEnabled() && mCurrentSession == null) {
             onSessionStart();
             return true;
         }
@@ -115,7 +128,7 @@
     }
 
     private void sessionExitpoint(int result) {
-        if (mEnableCollector && mCurrentSession != null) {
+        if (mCurrentSession != null) {
             onSessionEnd(result);
         }
     }
@@ -130,8 +143,36 @@
         SensorLoggerSession session = mCurrentSession;
         mCurrentSession = null;
 
-        session.end(System.currentTimeMillis(), result);
-        queueSession(session);
+        if (mEnableCollector) {
+            session.end(System.currentTimeMillis(), result);
+            queueSession(session);
+        }
+    }
+
+    public Uri reportRejectedTouch() {
+        if (mCurrentSession == null) {
+            Toast.makeText(mContext, "Generating rejected touch report failed: session timed out.",
+                    Toast.LENGTH_LONG).show();
+            return null;
+        }
+        SensorLoggerSession currentSession = mCurrentSession;
+
+        currentSession.setType(Session.REJECTED_TOUCH_REPORT);
+        currentSession.end(System.currentTimeMillis(), Session.SUCCESS);
+        Session proto = currentSession.toProto();
+
+        byte[] b = Session.toByteArray(proto);
+        File dir = new File(mContext.getExternalCacheDir(), "rejected_touch_reports");
+        dir.mkdir();
+        File touch = new File(dir, "rejected_touch_report_" + System.currentTimeMillis());
+
+        try {
+            new FileOutputStream(touch).write(b);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+
+        return Uri.fromFile(touch);
     }
 
     private void queueSession(final SensorLoggerSession currentSession) {
@@ -164,7 +205,7 @@
 
     @Override
     public synchronized void onSensorChanged(SensorEvent event) {
-        if (mEnableCollector && mCurrentSession != null) {
+        if (isEnabled() && mCurrentSession != null) {
             mCurrentSession.addSensorEvent(event, System.nanoTime());
             enforceTimeout();
         }
@@ -186,7 +227,19 @@
     public void onAccuracyChanged(Sensor sensor, int accuracy) {
     }
 
+    /**
+     * @return true if data is being collected - either for data gathering or creating a
+     *         rejected touch report.
+     */
     public boolean isEnabled() {
+        return mEnableCollector || mAllowReportRejectedTouch;
+    }
+
+    /**
+     * @return true if the full data set for data gathering should be collected - including
+     *         extensive sensor data, which is is not normally included with rejected touch reports.
+     */
+    public boolean isEnabledFull() {
         return mEnableCollector;
     }
 
@@ -401,8 +454,12 @@
     }
 
     private void addEvent(int eventType) {
-        if (mEnableCollector && mCurrentSession != null) {
+        if (isEnabled() && mCurrentSession != null) {
             mCurrentSession.addPhoneEvent(eventType, System.nanoTime());
         }
     }
+
+    public boolean isReportingEnabled() {
+        return mAllowReportRejectedTouch;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java b/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java
index faaad2b..b39803a 100644
--- a/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java
+++ b/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java
@@ -53,6 +53,10 @@
         mType = Session.REAL;
     }
 
+    public void setType(int type) {
+        mType = type;
+    }
+
     public void end(long endTimestampMillis, int result) {
         mResult = result;
         mEndTimestampMillis = endTimestampMillis;
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
index 1ac5992..664e886 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
@@ -22,6 +22,7 @@
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
+import android.net.Uri;
 import android.os.Handler;
 import android.os.PowerManager;
 import android.os.UserHandle;
@@ -142,7 +143,7 @@
         if (mHumanInteractionClassifier.isEnabled()) {
             registerSensors(CLASSIFIER_SENSORS);
         }
-        if (mDataCollector.isEnabled()) {
+        if (mDataCollector.isEnabledFull()) {
             registerSensors(COLLECTOR_SENSORS);
         }
     }
@@ -400,4 +401,15 @@
         pw.print("mScreenOn="); pw.println(mScreenOn ? 1 : 0);
         pw.println();
     }
+
+    public Uri reportRejectedTouch() {
+        if (mDataCollector.isEnabled()) {
+            return mDataCollector.reportRejectedTouch();
+        }
+        return null;
+    }
+
+    public boolean isReportingEnabled() {
+        return mDataCollector.isReportingEnabled();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index d1e9d9e..7c88307 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1732,6 +1732,7 @@
                 // this to our ViewRootImpl.
                 mStatusBarKeyguardViewManager.getViewRootImpl().setReportNextDraw();
                 notifyDrawn(mDrawnCallback);
+                mDrawnCallback = null;
             }
 
             // only play "unlock" noises if not on a call (since the incall UI
@@ -1740,6 +1741,7 @@
                 playSounds(false);
             }
 
+            mWakeAndUnlocking = false;
             setShowingLocked(false);
             mStatusBarKeyguardViewManager.hide(startTime, fadeoutDuration);
             resetKeyguardDonePendingLocked();
@@ -1866,6 +1868,7 @@
         synchronized (this) {
             if (DEBUG) Log.d(TAG, "handleNotifyScreenTurnedOff");
             mStatusBarKeyguardViewManager.onScreenTurnedOff();
+            mDrawnCallback = null;
             mWakeAndUnlocking = false;
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 0f4d9ed..51ff29e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -65,6 +65,7 @@
 
     boolean mVertical;
     boolean mScreenOn;
+    private int mCurrentRotation = -1;
 
     boolean mShowMenu;
     int mDisabledFlags = 0;
@@ -526,6 +527,10 @@
         updateCurrentView();
     }
 
+    public boolean needsReorient() {
+        return mCurrentRotation != mDisplay.getRotation();
+    }
+
     private void updateCurrentView() {
         final int rot = mDisplay.getRotation();
         for (int i=0; i<4; i++) {
@@ -538,6 +543,7 @@
             mButtonDisatchers.valueAt(i).setCurrentView(mCurrentView);
         }
         updateLayoutTransitionsEnabled();
+        mCurrentRotation = rot;
     }
 
     private void updateRecentsIcon() {
@@ -620,11 +626,12 @@
             if (mCarMode && uiMode != Configuration.UI_MODE_TYPE_CAR) {
                 mCarMode = false;
                 uiCarModeChanged = true;
+                getHomeButton().setCarMode(mCarMode);
             } else if (uiMode == Configuration.UI_MODE_TYPE_CAR) {
                 mCarMode = true;
                 uiCarModeChanged = true;
+                getHomeButton().setCarMode(mCarMode);
             }
-            getHomeButton().setCarMode(mCarMode);
         }
         return uiCarModeChanged;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 4f34ec2..d836c05 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -73,6 +73,7 @@
 import android.media.session.MediaSession;
 import android.media.session.MediaSessionManager;
 import android.media.session.PlaybackState;
+import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Handler;
@@ -85,6 +86,7 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.Trace;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.Vibrator;
@@ -195,6 +197,7 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -365,6 +368,8 @@
     private View mPendingRemoteInputView;
     private View mPendingWorkRemoteInputView;
 
+    private View mReportRejectedTouch;
+
     int mMaxAllowedKeyguardNotifications;
 
     boolean mExpandedVisible;
@@ -929,6 +934,36 @@
                 mBatteryController);
         mKeyguardStatusBar.setBatteryController(mBatteryController);
 
+        mReportRejectedTouch = mStatusBarWindow.findViewById(R.id.report_rejected_touch);
+        if (mReportRejectedTouch != null) {
+            updateReportRejectedTouchVisibility();
+            mReportRejectedTouch.setOnClickListener(v -> {
+                Uri session = mFalsingManager.reportRejectedTouch();
+                if (session == null) { return; }
+
+                StringWriter message = new StringWriter();
+                message.write("Build info: ");
+                message.write(SystemProperties.get("ro.build.description"));
+                message.write("\nSerial number: ");
+                message.write(SystemProperties.get("ro.serialno"));
+                message.write("\n");
+
+                PrintWriter falsingPw = new PrintWriter(message);
+                FalsingLog.dump(falsingPw);
+                falsingPw.flush();
+
+                startActivityDismissingKeyguard(Intent.createChooser(new Intent(Intent.ACTION_SEND)
+                                .setType("*/*")
+                                .putExtra(Intent.EXTRA_SUBJECT, "Rejected touch report")
+                                .putExtra(Intent.EXTRA_STREAM, session)
+                                .putExtra(Intent.EXTRA_TEXT, message.toString()),
+                        "Share rejected touch report")
+                                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
+                        true /* onlyProvisioned */, true /* dismissShade */);
+            });
+        }
+
+
         PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mBroadcastReceiver.onReceive(mContext,
                 new Intent(pm.isScreenOn() ? Intent.ACTION_SCREEN_ON : Intent.ACTION_SCREEN_OFF));
@@ -2260,6 +2295,14 @@
         Trace.endSection();
     }
 
+    private void updateReportRejectedTouchVisibility() {
+        if (mReportRejectedTouch == null) {
+            return;
+        }
+        mReportRejectedTouch.setVisibility(mState == StatusBarState.KEYGUARD
+                && mFalsingManager.isReportingEnabled() ? View.VISIBLE : View.INVISIBLE);
+    }
+
     protected int adjustDisableFlags(int state) {
         if (!mLaunchTransitionFadingAway && !mKeyguardFadingAway
                 && (mExpandedVisible || mBouncerShowing || mWaitingForKeyguardExit)) {
@@ -3553,7 +3596,8 @@
 
     @Override
     public void onDisplayChanged(int displayId) {
-        if (displayId == Display.DEFAULT_DISPLAY) {
+        if (displayId == Display.DEFAULT_DISPLAY
+                && mNavigationBarView != null && mNavigationBarView.needsReorient()) {
             repositionNavigationBar();
         }
     }
@@ -4393,6 +4437,7 @@
         mGroupManager.setStatusBarState(state);
         mFalsingManager.setStatusBarState(state);
         mStatusBarWindowManager.setStatusBarState(state);
+        updateReportRejectedTouchVisibility();
         updateDozing();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/touch_analytics.proto b/packages/SystemUI/src/com/android/systemui/statusbar/phone/touch_analytics.proto
index afc8f77..50fd52a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/touch_analytics.proto
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/touch_analytics.proto
@@ -120,6 +120,7 @@
         RESERVED_2 = 1;
         RANDOM_WAKEUP = 2;
         REAL = 3;
+        REJECTED_TOUCH_REPORT = 4;
     }
 
     optional uint64 startTimestampMillis = 1;
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index d9f2bac..5099db7 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -2203,6 +2203,10 @@
     // System navigation key down.
     ACTION_SYSTEM_NAVIGATION_KEY_DOWN = 494;
 
+    // OPEN: Settings > Display -> Ambient Display
+    // CATEGORY: SETTINGS
+    ACTION_AMBIENT_DISPLAY = 495;
+
     // ---- End N-MR1 Constants, all N-MR1 constants go above this line ----
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 2a7d945..fd93865 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -77,6 +77,9 @@
      */
     static final int FLAG_FEATURE_INJECT_MOTION_EVENTS = 0x00000010;
 
+    static final int FEATURES_AFFECTING_MOTION_EVENTS = FLAG_FEATURE_INJECT_MOTION_EVENTS
+            | FLAG_FEATURE_AUTOCLICK | FLAG_FEATURE_TOUCH_EXPLORATION
+            | FLAG_FEATURE_SCREEN_MAGNIFIER;
     /**
      * Flag for enabling the feature to control the screen magnifier. If
      * {@link #FLAG_FEATURE_SCREEN_MAGNIFIER} is set this flag is ignored
@@ -203,8 +206,13 @@
         }
 
         if (event instanceof MotionEvent) {
-            MotionEvent motionEvent = (MotionEvent) event;
-            processMotionEvent(state, motionEvent, policyFlags);
+            if ((mEnabledFeatures & FEATURES_AFFECTING_MOTION_EVENTS) != 0) {
+                MotionEvent motionEvent = (MotionEvent) event;
+                processMotionEvent(state, motionEvent, policyFlags);
+                return;
+            } else {
+                super.onInputEvent(event, policyFlags);
+            }
         } else if (event instanceof KeyEvent) {
             KeyEvent keyEvent = (KeyEvent) event;
             processKeyEvent(state, keyEvent, policyFlags);
diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java
index 7ea8f1f..356ccb3 100644
--- a/services/core/java/com/android/server/PinnerService.java
+++ b/services/core/java/com/android/server/PinnerService.java
@@ -17,26 +17,23 @@
 package com.android.server;
 
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
-import android.content.Intent;
-import android.util.EventLog;
-import android.util.Slog;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.os.Process;
+import android.os.UserHandle;
 import android.provider.MediaStore;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.OsConstants;
 import android.system.StructStat;
+import android.util.Slog;
 
 import com.android.internal.app.ResolverActivity;
 import com.android.internal.os.BackgroundThread;
@@ -44,12 +41,10 @@
 import dalvik.system.DexFile;
 import dalvik.system.VMRuntime;
 
-import java.util.ArrayList;
-import java.util.List;
 import java.io.FileDescriptor;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.util.ArrayList;
 
 /**
  * <p>PinnerService pins important files for key processes in memory.</p>
@@ -89,20 +84,10 @@
         }
         mBinderService = new BinderService();
         publishBinderService("pinner", mBinderService);
-        mPinnerHandler.sendMessage(
-                mPinnerHandler.obtainMessage(PinnerHandler.PIN_ONSTART_MSG));
-    }
 
-    /**
-     * Pin camera on unlock.
-     * We have to wait for unlock because the user's
-     * preference for camera is not available from PackageManager until after
-     * unlock
-     */
-    @Override
-    public void onUnlockUser(int userHandle) {
-        mPinnerHandler.sendMessage(
-                mPinnerHandler.obtainMessage(PinnerHandler.PIN_CAMERA_MSG, userHandle, 0));
+        mPinnerHandler.obtainMessage(PinnerHandler.PIN_ONSTART_MSG).sendToTarget();
+        mPinnerHandler.obtainMessage(PinnerHandler.PIN_CAMERA_MSG, UserHandle.USER_SYSTEM, 0)
+                .sendToTarget();
     }
 
     /**
@@ -113,8 +98,7 @@
      */
     @Override
     public void onSwitchUser(int userHandle) {
-        mPinnerHandler.sendMessage(
-                mPinnerHandler.obtainMessage(PinnerHandler.PIN_CAMERA_MSG, userHandle, 0));
+        mPinnerHandler.obtainMessage(PinnerHandler.PIN_CAMERA_MSG, userHandle, 0).sendToTarget();
     }
 
     /**
@@ -194,8 +178,10 @@
         //  device without a fbe enabled, the _SECURE intent will never get set.
         Intent cameraIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
         PackageManager pm = mContext.getPackageManager();
-        ResolveInfo cameraResolveInfo = pm.resolveActivityAsUser(
-                cameraIntent, PackageManager.MATCH_DEFAULT_ONLY, userHandle);
+        ResolveInfo cameraResolveInfo = pm.resolveActivityAsUser(cameraIntent,
+                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.MATCH_DIRECT_BOOT_AWARE
+                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                userHandle);
         if (cameraResolveInfo == null ) {
             //this is not necessarily an error
             if (DEBUG) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index a3d2ebb..1bcff1a 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -748,7 +748,7 @@
             if (sm != null) {
                 for (int i = sm.mServicesByName.size()-1; i >= 0; i--) {
                     ServiceRecord other = sm.mServicesByName.valueAt(i);
-                    if (other.foregroundId == r.foregroundId
+                    if (other != r && other.foregroundId == r.foregroundId
                             && other.packageName.equals(r.packageName)) {
                         // Found one!  Abort the cancel.
                         return;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 87036cf..e336ed5 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2328,12 +2328,17 @@
                             ProcessRecord proc = r.app;
                             if (proc.vrThreadTid > 0) {
                                 if (proc.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) {
-                                    if (mInVrMode == true) {
-                                        Process.setThreadScheduler(proc.vrThreadTid,
-                                            Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
-                                    } else {
-                                        Process.setThreadScheduler(proc.vrThreadTid,
-                                            Process.SCHED_OTHER, 0);
+                                    try {
+                                        if (mInVrMode == true) {
+                                            Process.setThreadScheduler(proc.vrThreadTid,
+                                                Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+                                        } else {
+                                            Process.setThreadScheduler(proc.vrThreadTid,
+                                                Process.SCHED_OTHER, 0);
+                                        }
+                                    } catch (IllegalArgumentException e) {
+                                        Slog.e(TAG, "Failed to set scheduling policy, thread does"
+                                                + " not exist:\n" + e);
                                     }
                                 }
                             }
@@ -21942,6 +21947,11 @@
                         /*resultTo*/ null, bOptions, userId);
             }
         }
+
+        @Override
+        public int getUidProcessState(int uid) {
+            return getUidState(uid);
+        }
     }
 
     private final class SleepTokenImpl extends SleepToken {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 8b5942c..2dbbc88 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -180,7 +180,7 @@
             = SystemProperties.getBoolean("debug.child_notifs", true);
 
     static final int MAX_PACKAGE_NOTIFICATIONS = 50;
-    static final float DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE = 50f;
+    static final float DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE = 10f;
 
     // message codes
     static final int MESSAGE_TIMEOUT = 2;
@@ -2538,20 +2538,32 @@
 
         mUsageStats.registerEnqueuedByApp(pkg);
 
+
+        if (pkg == null || notification == null) {
+            throw new IllegalArgumentException("null not allowed: pkg=" + pkg
+                    + " id=" + id + " notification=" + notification);
+        }
+        final StatusBarNotification n = new StatusBarNotification(
+                pkg, opPkg, id, tag, callingUid, callingPid, 0, notification,
+                user);
+
         // Limit the number of notifications that any given package except the android
         // package or a registered listener can enqueue.  Prevents DOS attacks and deals with leaks.
         if (!isSystemNotification && !isNotificationFromListener) {
             synchronized (mNotificationList) {
-                final float appEnqueueRate = mUsageStats.getAppEnqueueRate(pkg);
-                if (appEnqueueRate > mMaxPackageEnqueueRate) {
-                    mUsageStats.registerOverRateQuota(pkg);
-                    final long now = SystemClock.elapsedRealtime();
-                    if ((now - mLastOverRateLogTime) > MIN_PACKAGE_OVERRATE_LOG_INTERVAL) {
-                        Slog.e(TAG, "Package enqueue rate is " + appEnqueueRate
-                                + ". Shedding events. package=" + pkg);
-                        mLastOverRateLogTime = now;
+                if(mNotificationsByKey.get(n.getKey()) != null) {
+                    // this is an update, rate limit updates only
+                    final float appEnqueueRate = mUsageStats.getAppEnqueueRate(pkg);
+                    if (appEnqueueRate > mMaxPackageEnqueueRate) {
+                        mUsageStats.registerOverRateQuota(pkg);
+                        final long now = SystemClock.elapsedRealtime();
+                        if ((now - mLastOverRateLogTime) > MIN_PACKAGE_OVERRATE_LOG_INTERVAL) {
+                            Slog.e(TAG, "Package enqueue rate is " + appEnqueueRate
+                                    + ". Shedding events. package=" + pkg);
+                            mLastOverRateLogTime = now;
+                        }
+                        return;
                     }
-                    return;
                 }
 
                 int count = 0;
@@ -2574,11 +2586,6 @@
             }
         }
 
-        if (pkg == null || notification == null) {
-            throw new IllegalArgumentException("null not allowed: pkg=" + pkg
-                    + " id=" + id + " notification=" + notification);
-        }
-
         // Whitelist pending intents.
         if (notification.allPendingIntents != null) {
             final int intentCount = notification.allPendingIntents.size();
@@ -2601,9 +2608,6 @@
                 Notification.PRIORITY_MAX);
 
         // setup local book-keeping
-        final StatusBarNotification n = new StatusBarNotification(
-                pkg, opPkg, id, tag, callingUid, callingPid, 0, notification,
-                user);
         final NotificationRecord r = new NotificationRecord(getContext(), n);
         mHandler.post(new EnqueueNotificationRunnable(userId, r));
 
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 8d400b5..558467b 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -20,6 +20,7 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
 import android.app.ActivityManagerNative;
 import android.app.AppGlobals;
 import android.app.IUidObserver;
@@ -284,6 +285,7 @@
     private final PackageManagerInternal mPackageManagerInternal;
     private final UserManager mUserManager;
     private final UsageStatsManagerInternal mUsageStatsManagerInternal;
+    private final ActivityManagerInternal mActivityManagerInternal;
 
     @GuardedBy("mLock")
     final SparseIntArray mUidState = new SparseIntArray();
@@ -372,6 +374,8 @@
         mUserManager = Preconditions.checkNotNull(context.getSystemService(UserManager.class));
         mUsageStatsManagerInternal = Preconditions.checkNotNull(
                 LocalServices.getService(UsageStatsManagerInternal.class));
+        mActivityManagerInternal = Preconditions.checkNotNull(
+                LocalServices.getService(ActivityManagerInternal.class));
 
         if (onlyForPackageManagerApis) {
             return; // Don't do anything further.  For unit tests only.
@@ -456,7 +460,8 @@
     }
 
     private boolean isProcessStateForeground(int processState) {
-        return processState <= PROCESS_STATE_FOREGROUND_THRESHOLD;
+        return (processState != ActivityManager.PROCESS_STATE_NONEXISTENT)
+                && (processState <= PROCESS_STATE_FOREGROUND_THRESHOLD);
     }
 
     boolean isUidForegroundLocked(int uid) {
@@ -465,7 +470,13 @@
             // so it's foreground anyway.
             return true;
         }
-        return isProcessStateForeground(mUidState.get(uid, ActivityManager.MAX_PROCESS_STATE));
+        // First, check with the local cache.
+        if (isProcessStateForeground(mUidState.get(uid, ActivityManager.MAX_PROCESS_STATE))) {
+            return true;
+        }
+        // If the cache says background, reach out to AM.  Since it'll internally need to hold
+        // the AM lock, we use it as a last resort.
+        return isProcessStateForeground(mActivityManagerInternal.getUidProcessState(uid));
     }
 
     long getUidLastForegroundElapsedTimeLocked(int uid) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 6451c74..b4085f5 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -11445,8 +11445,9 @@
                 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
                     final WindowState win = windows.get(winNdx);
                     final boolean isForceHiding = mPolicy.isForceHiding(win.mAttrs);
+                    final boolean keyguard = mPolicy.isKeyguardHostWindow(win.mAttrs);
                     if (win.isVisibleLw()
-                            && (win.mAppToken != null || isForceHiding)) {
+                            && (win.mAppToken != null || isForceHiding || keyguard)) {
                         win.mWinAnimator.mDrawState = DRAW_PENDING;
                         // Force add to mResizingWindows.
                         win.mLastContentInsets.set(-1, -1, -1, -1);
diff --git a/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java b/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java
index 7a3b461..daaa4f5 100644
--- a/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java
+++ b/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java
@@ -67,10 +67,11 @@
 
     void installApps(int userId) {
         File[] files = preloadsAppsDirectory.listFiles();
+        AppInstallCounter counter = new AppInstallCounter(mContext, userId);
         if (ArrayUtils.isEmpty(files)) {
+            counter.setExpectedAppsCount(0);
             return;
         }
-        AppInstallCounter counter = new AppInstallCounter(mContext, userId);
         int expectedCount = 0;
         for (File file : files) {
             String apkName = file.getName();
diff --git a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
index 8d5971f..7525e87 100644
--- a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
+++ b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
@@ -340,9 +340,8 @@
                 UserHandle.SYSTEM);
         Settings.Secure.putIntForUser(getContext().getContentResolver(),
                 Settings.Secure.SKIP_FIRST_USE_HINTS, 1, userInfo.id);
-        Settings.Secure.putIntForUser(getContext().getContentResolver(),
-                Settings.Global.PACKAGE_VERIFIER_ENABLE, 0, userInfo.id);
-
+        Settings.Global.putInt(getContext().getContentResolver(),
+                Settings.Global.PACKAGE_VERIFIER_ENABLE, 0);
         grantRuntimePermissionToCamera(user);
         clearPrimaryCallLog();
     }
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index d003e56..e7f3345 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -36,6 +36,7 @@
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
 import android.app.Activity;
+import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
 import android.app.IUidObserver;
 import android.app.usage.UsageStatsManagerInternal;
@@ -715,6 +716,9 @@
                     return b(mRunningUsers.get(userId)) && b(mUnlockedUsers.get(userId));
                 }));
 
+        when(mMockActivityManagerInternal.getUidProcessState(anyInt())).thenReturn(
+                ActivityManager.PROCESS_STATE_CACHED_EMPTY);
+
         // User 0 and P0 are always running
         mRunningUsers.put(USER_0, true);
         mRunningUsers.put(USER_10, false);
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index df9242d..8560651 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -49,6 +49,7 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.SomeArgs;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.FgThread;
 
@@ -320,6 +321,7 @@
         private boolean mConnected;
         private boolean mHostConnected;
         private boolean mSourcePower;
+        private boolean mSinkPower;
         private boolean mConfigured;
         private boolean mUsbDataUnlocked;
         private String mCurrentFunctions;
@@ -401,7 +403,18 @@
         public void updateHostState(UsbPort port, UsbPortStatus status) {
             boolean hostConnected = status.getCurrentDataRole() == UsbPort.DATA_ROLE_HOST;
             boolean sourcePower = status.getCurrentPowerRole() == UsbPort.POWER_ROLE_SOURCE;
-            obtainMessage(MSG_UPDATE_HOST_STATE, hostConnected ? 1 :0, sourcePower ? 1 :0).sendToTarget();
+            boolean sinkPower = status.getCurrentPowerRole() == UsbPort.POWER_ROLE_SINK;
+
+            if (DEBUG) {
+                Slog.i(TAG, "updateHostState " + port + " status=" + status);
+            }
+
+            SomeArgs args = SomeArgs.obtain();
+            args.argi1 = hostConnected ? 1 :0;
+            args.argi2 = sourcePower ? 1 :0;
+            args.argi3 = sinkPower ? 1 :0;
+
+            obtainMessage(MSG_UPDATE_HOST_STATE, args).sendToTarget();
         }
 
         private boolean waitForState(String state) {
@@ -718,8 +731,11 @@
                     }
                     break;
                 case MSG_UPDATE_HOST_STATE:
-                    mHostConnected = (msg.arg1 == 1);
-                    mSourcePower = (msg.arg2 == 1);
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    mHostConnected = (args.argi1 == 1);
+                    mSourcePower = (args.argi2 == 1);
+                    mSinkPower = (args.argi3 == 1);
+                    args.recycle();
                     updateUsbNotification();
                     if (mBootCompleted) {
                         updateUsbStateBroadcastIfNeeded();
@@ -809,6 +825,8 @@
                 }
             } else if (mSourcePower) {
                 id = com.android.internal.R.string.usb_supplying_notification_title;
+            } else if (mHostConnected && mSinkPower) {
+                id = com.android.internal.R.string.usb_charging_notification_title;
             }
             if (id != mUsbNotificationId) {
                 // clear notification if title needs changing
@@ -908,6 +926,9 @@
             pw.println("  mConfigured: " + mConfigured);
             pw.println("  mUsbDataUnlocked: " + mUsbDataUnlocked);
             pw.println("  mCurrentAccessory: " + mCurrentAccessory);
+            pw.println("  mHostConnected: " + mHostConnected);
+            pw.println("  mSourcePower: " + mSourcePower);
+            pw.println("  mSinkPower: " + mSinkPower);
             try {
                 pw.println("  Kernel state: "
                         + FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim());