Merge "Ensure we pass correct values into the next transition start bounds." into nyc-mr1-dev
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index 8692336..9fa8a5d 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -345,7 +345,7 @@
             PrintWriter pw = new FastPrintWriter(sw, false, 256);
             tr.printStackTrace(pw);
             pw.flush();
-            stackTrace = sw.toString();
+            stackTrace = sanitizeString(sw.toString());
             exceptionMessage = tr.getMessage();
 
             // Populate fields with the "root cause" exception
@@ -374,6 +374,29 @@
                 throwMethodName = "unknown";
                 throwLineNumber = 0;
             }
+
+            exceptionMessage = sanitizeString(exceptionMessage);
+        }
+
+        /**
+         * Ensure that the string is of reasonable size, truncating from the middle if needed.
+         */
+        private String sanitizeString(String s) {
+            int prefixLength = 10 * 1024;
+            int suffixLength = 10 * 1024;
+            int acceptableLength = prefixLength + suffixLength;
+
+            if (s != null && s.length() > acceptableLength) {
+                String replacement =
+                        "\n[TRUNCATED " + (s.length() - acceptableLength) + " CHARS]\n";
+
+                StringBuilder sb = new StringBuilder(acceptableLength + replacement.length());
+                sb.append(s.substring(0, prefixLength));
+                sb.append(replacement);
+                sb.append(s.substring(s.length() - suffixLength));
+                return sb.toString();
+            }
+            return s;
         }
 
         /**
diff --git a/docs/html/_redirects.yaml b/docs/html/_redirects.yaml
index d4732f8..48aca28 100644
--- a/docs/html/_redirects.yaml
+++ b/docs/html/_redirects.yaml
@@ -1193,3 +1193,5 @@
   to: http://tools.android.com/tech-docs/new-build-system/gradle-experimental/experimental-to-stable-gradle
 - from: /r/studio-ui/sdk-manager.html
   to: https://developer.android.com/studio/intro/update.html#sdk-manager
+- from: /r/studio-ui/newjclass.html
+  to: /studio/write/index.html
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 8d4a151..31c7a32 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -3498,7 +3498,7 @@
          * @param extra an extra code, specific to the info. Typically
          * implementation dependent.
          * @return True if the method handled the info, false if it didn't.
-         * Returning false, or not having an OnErrorListener at all, will
+         * Returning false, or not having an OnInfoListener at all, will
          * cause the info to be discarded.
          */
         boolean onInfo(MediaPlayer mp, int what, int extra);
diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java
index 0f7dc9a..b262d97 100644
--- a/media/java/android/media/PlayerBase.java
+++ b/media/java/android/media/PlayerBase.java
@@ -181,10 +181,15 @@
      * @return
      */
     boolean isRestricted_sync() {
+        // check app ops
+        if (mHasAppOpsPlayAudio) {
+            return false;
+        }
+        // check bypass flag
         if ((mAttributes.getAllFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) {
             return false;
         }
-        return !mHasAppOpsPlayAudio;
+        return true;
     }
 
     // Abstract methods a subclass needs to implement
diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java
index 5ede1d5..9fafda4 100644
--- a/media/java/android/media/SoundPool.java
+++ b/media/java/android/media/SoundPool.java
@@ -505,27 +505,31 @@
     }
 
     private boolean isRestricted() {
-        IAudioService service = getService();
-        boolean cameraSoundForced = false;
-
-        try {
-            cameraSoundForced = service.isCameraSoundForced();
-        } catch (RemoteException e) {
-            Log.e(TAG, "Cannot access AudioService in isRestricted()");
-        }
-
-        if (cameraSoundForced &&
-                ((mAttributes.getAllFlags() & AudioAttributes.FLAG_AUDIBILITY_ENFORCED) != 0)
-// FIXME: should also check usage when set properly by camera app
-//                && (mAttributes.getUsage() == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
-                ) {
+        // check app ops
+        if (mHasAppOpsPlayAudio) {
             return false;
         }
-
+        // check bypass flag
         if ((mAttributes.getAllFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) {
             return false;
         }
-        return !mHasAppOpsPlayAudio;
+        // check force audibility flag and camera restriction
+        if ((mAttributes.getAllFlags() & AudioAttributes.FLAG_AUDIBILITY_ENFORCED) != 0) {
+// FIXME: should also check usage when set properly by camera app
+//          && (mAttributes.getUsage() == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
+            boolean cameraSoundForced = false;
+            try {
+                cameraSoundForced = getService().isCameraSoundForced();
+            } catch (RemoteException e) {
+                Log.e(TAG, "Cannot access AudioService in isRestricted()");
+            } catch (NullPointerException e) {
+                Log.e(TAG, "Null AudioService in isRestricted()");
+            }
+            if (cameraSoundForced) {
+                return false;
+            }
+        }
+        return true;
     }
 
     private void updateAppOpsPlayAudio() {
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 9bc5426..fb7afc5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -883,9 +883,9 @@
         mLightStatusBarController = new LightStatusBarController(mIconController,
                 mBatteryController);
         mKeyguardMonitor = new KeyguardMonitor(mContext);
+        mUserSwitcherController = new UserSwitcherController(mContext, mKeyguardMonitor,
+                mHandler, this);
         if (UserManager.get(mContext).isUserSwitcherEnabled()) {
-            mUserSwitcherController = new UserSwitcherController(mContext, mKeyguardMonitor,
-                    mHandler, this);
             createUserSwitcher();
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index 0d22d02..21db64f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -318,7 +318,8 @@
     public void onClick(View v) {
         if (v == mSettingsButton) {
             MetricsLogger.action(mContext,
-                    MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH);
+                    mExpanded ? MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH
+                            : MetricsProto.MetricsEvent.ACTION_QS_COLLAPSED_SETTINGS_LAUNCH);
             if (mSettingsButton.isTunerClick()) {
                 if (TunerService.isTunerEnabled(mContext)) {
                     TunerService.showResetRequest(mContext, new Runnable() {
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 6d401e8..966d0ec 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -2185,6 +2185,9 @@
         //   SUBTYPE: false is off, true is on
     ACTION_TOGGLE_STORAGE_MANAGER = 489;
 
+    // Settings launched from collapsed quick settings.
+    ACTION_QS_COLLAPSED_SETTINGS_LAUNCH = 490;
+
     // ---- 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/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index a3cf9c8..6a56fa6 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -182,6 +182,10 @@
      */
     private final Random mRandom = new SecureRandom();
 
+    /** All sessions allocated */
+    @GuardedBy("mSessions")
+    private final SparseBooleanArray mAllocatedSessions = new SparseBooleanArray();
+
     @GuardedBy("mSessions")
     private final SparseArray<PackageInstallerSession> mSessions = new SparseArray<>();
 
@@ -365,6 +369,7 @@
                             // keep details around for dumpsys.
                             mHistoricalSessions.put(session.sessionId, session);
                         }
+                        mAllocatedSessions.put(session.sessionId, true);
                     }
                 }
             }
@@ -768,8 +773,8 @@
         int sessionId;
         do {
             sessionId = mRandom.nextInt(Integer.MAX_VALUE - 1) + 1;
-            if (mSessions.get(sessionId) == null && mHistoricalSessions.get(sessionId) == null
-                    && !mLegacySessions.get(sessionId, false)) {
+            if (!mAllocatedSessions.get(sessionId, false)) {
+                mAllocatedSessions.put(sessionId, true);
                 return sessionId;
             }
         } while (n++ < 32);
diff --git a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
index 23ffb18..fe1986f 100644
--- a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
+++ b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
@@ -321,8 +321,6 @@
     private void setupDemoUser(UserInfo userInfo) {
         UserManager um = getUserManager();
         UserHandle user = UserHandle.of(userInfo.id);
-        LockPatternUtils lockPatternUtils = new LockPatternUtils(getContext());
-        lockPatternUtils.setLockScreenDisabled(true, userInfo.id);
         um.setUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, true, user);
         um.setUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true, user);
         um.setUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, true, user);
@@ -497,6 +495,9 @@
         mAmi.updatePersistentConfigurationForUser(getSystemUsersConfiguration(), userId);
         turnOffAllFlashLights();
         muteVolumeStreams();
+        // Disable lock screen for demo users.
+        LockPatternUtils lockPatternUtils = new LockPatternUtils(getContext());
+        lockPatternUtils.setLockScreenDisabled(true, userId);
         mNm.notifyAsUser(TAG, 1, createResetNotification(), UserHandle.of(userId));
 
         synchronized (mActivityLock) {