Merge "Switch to libsigchain.a" into lmp-mr1-dev
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index 820bf78..54c4505 100644
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -329,7 +329,6 @@
             String fullDateText = DateUtils.formatDateTime(mContext, millis, flags);
             mAnimator.announceForAccessibility(fullDateText);
         }
-        updatePickers();
     }
 
     private void setCurrentView(final int viewIndex) {
@@ -369,11 +368,14 @@
     @Override
     public void init(int year, int monthOfYear, int dayOfMonth,
             DatePicker.OnDateChangedListener callBack) {
-        mDateChangedListener = callBack;
         mCurrentDate.set(Calendar.YEAR, year);
         mCurrentDate.set(Calendar.MONTH, monthOfYear);
         mCurrentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
-        updateDisplay(false);
+
+        onDateChanged(false);
+
+        // Set the listener last so that we don't call it.
+        mDateChangedListener = callBack;
     }
 
     @Override
@@ -381,10 +383,29 @@
         mCurrentDate.set(Calendar.YEAR, year);
         mCurrentDate.set(Calendar.MONTH, month);
         mCurrentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
+
+        onDateChanged(false);
+    }
+
+    private void onDateChanged(boolean fromUser) {
         if (mDateChangedListener != null) {
-            mDateChangedListener.onDateChanged(mDelegator, year, month, dayOfMonth);
+            final int year = mCurrentDate.get(Calendar.YEAR);
+            final int monthOfYear = mCurrentDate.get(Calendar.MONTH);
+            final int dayOfMonth = mCurrentDate.get(Calendar.DAY_OF_MONTH);
+            mDateChangedListener.onDateChanged(mDelegator, year, monthOfYear, dayOfMonth);
         }
-        updateDisplay(false);
+
+        for (OnDateChangedListener listener : mListeners) {
+            listener.onDateChanged();
+        }
+
+        mDayPickerView.setDate(getSelectedDay().getTimeInMillis());
+
+        updateDisplay(fromUser);
+
+        if (fromUser) {
+            tryVibrate();
+        }
     }
 
     @Override
@@ -411,8 +432,7 @@
         }
         if (mCurrentDate.before(mTempDate)) {
             mCurrentDate.setTimeInMillis(minDate);
-            updatePickers();
-            updateDisplay(false);
+            onDateChanged(false);
         }
         mMinDate.setTimeInMillis(minDate);
         mDayPickerView.setMinDate(minDate);
@@ -433,8 +453,7 @@
         }
         if (mCurrentDate.after(mTempDate)) {
             mCurrentDate.setTimeInMillis(maxDate);
-            updatePickers();
-            updateDisplay(false);
+            onDateChanged(false);
         }
         mMaxDate.setTimeInMillis(maxDate);
         mDayPickerView.setMaxDate(maxDate);
@@ -573,9 +592,10 @@
     public void onYearSelected(int year) {
         adjustDayInMonthIfNeeded(mCurrentDate.get(Calendar.MONTH), year);
         mCurrentDate.set(Calendar.YEAR, year);
-        updatePickers();
+        onDateChanged(true);
+
+        // Auto-advance to month and day view.
         setCurrentView(MONTH_AND_DAY_VIEW);
-        updateDisplay(true);
     }
 
     // If the newly selected month / year does not contain the currently selected day number,
@@ -612,14 +632,6 @@
         }
     }
 
-    private void updatePickers() {
-        for (OnDateChangedListener listener : mListeners) {
-            listener.onDateChanged();
-        }
-
-        mDayPickerView.setDate(getSelectedDay().getTimeInMillis());
-    }
-
     @Override
     public void registerOnDateChangedListener(OnDateChangedListener listener) {
         mListeners.add(listener);
@@ -653,11 +665,7 @@
         @Override
         public void onDaySelected(DayPickerView view, Calendar day) {
             mCurrentDate.setTimeInMillis(day.getTimeInMillis());
-
-            updatePickers();
-            updateDisplay(true);
-
-            tryVibrate();
+            onDateChanged(true);
         }
     };
 
diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml
index bdb0324..e1e1ffed 100644
--- a/core/res/res/values/dimens_material.xml
+++ b/core/res/res/values/dimens_material.xml
@@ -56,6 +56,7 @@
     <dimen name="action_bar_overflow_padding_start_material">6dp</dimen>
     <!-- Padding to add to the end of the overflow action button. -->
     <dimen name="action_bar_overflow_padding_end_material">10dp</dimen>
+    <dimen name="action_bar_elevation_material">4dp</dimen>
 
     <dimen name="action_button_min_width_overflow_material">36dp</dimen>
     <dimen name="action_button_min_width_material">48dp</dimen>
@@ -87,9 +88,9 @@
     <dimen name="floating_window_margin_bottom">32dp</dimen>
 
     <!-- Elevation when button is pressed -->
-    <dimen name="button_elevation_material">4dp</dimen>
+    <dimen name="button_elevation_material">2dp</dimen>
     <!-- Z translation to apply when button is pressed -->
-    <dimen name="button_pressed_z_material">2dp</dimen>
+    <dimen name="button_pressed_z_material">4dp</dimen>
     <!-- Default insets (outer padding) around buttons -->
     <dimen name="button_inset_vertical_material">6dp</dimen>
     <dimen name="button_inset_horizontal_material">@dimen/control_inset_material</dimen>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index d3d6d70..6220a1b 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -917,7 +917,7 @@
         <item name="gravity">center_vertical</item>
         <item name="contentInsetStart">@dimen/action_bar_content_inset_material</item>
         <item name="contentInsetEnd">@dimen/action_bar_content_inset_material</item>
-        <item name="elevation">8dp</item>
+        <item name="elevation">@dimen/action_bar_elevation_material</item>
         <item name="popupTheme">?attr/actionBarPopupTheme</item>
     </style>
 
diff --git a/docs/html/distribute/googleplay/wear.jd b/docs/html/distribute/googleplay/wear.jd
index b6fc6b6..c0a0017 100644
--- a/docs/html/distribute/googleplay/wear.jd
+++ b/docs/html/distribute/googleplay/wear.jd
@@ -210,7 +210,7 @@
   and the opt-in checkbox.
   </li>
 
-  <li>Click the checkbox next to <em>Distribute your app to Android Wear</em>.
+  <li>Click the checkbox next to <em>Distribute your app on Android Wear</em>.
   </li>
 
   <li>Click <strong>Save</strong> to save your Pricing and Distribution changes.
diff --git a/docs/html/tools/studio/index.jd b/docs/html/tools/studio/index.jd
index d1888fa..258fedb 100644
--- a/docs/html/tools/studio/index.jd
+++ b/docs/html/tools/studio/index.jd
@@ -114,8 +114,9 @@
     <p>  <img src="{@docRoot}images/tools/studio-project-layout.png" alt="" /></p>
     <p>  <class="img-caption"><strong>Figure 3.</strong> Android Studio project structure</p>
 
-<p>For more information, see <a href="http://confluence.jetbrains.com/display/IntelliJIDEA/Project +Organization"class="external-link">IntelliJ project organization</a> and
-<a href="{@docRoot}tools/workflow/project/index.html">Managing Projects</a>.</p>
+<p>For more information, see
+<a href="http://confluence.jetbrains.com/display/IntelliJIDEA/Project+Organization"class="external-link">IntelliJ project organization</a> and
+<a href="{@docRoot}tools/projects/index.html">Managing Projects</a>.</p>
 
 
 <h3>Creating new files</h3>
diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs
index cb6a1de..9437c1b 100644
--- a/docs/html/tools/tools_toc.cs
+++ b/docs/html/tools/tools_toc.cs
@@ -122,7 +122,7 @@
   <li class="nav-section">
     <div class="nav-section-header"><a href="<?cs var:toroot ?>tools/debugging/index.html"><span class="en">Debugging</span></a></div>
     <ul>
-      <li><a href="<?cs var:toroot ?>tools/debugging/debugging-projects.html"><span class="en">From Eclipse with ADT</span></a></li>
+      <li><a href="<?cs var:toroot ?>tools/debugging/debugging-studio.html"><span class="en">From Android Studio</span></a></li>
       <li><a href="<?cs var:toroot ?>tools/debugging/debugging-projects-cmdline.html"><span class="en">From Other IDEs</span></a></li>
       <li><a href="<?cs var:toroot ?>tools/debugging/ddms.html"><span class="en">Using DDMS</span></a></li>
       <li><a href="<?cs var:toroot ?>tools/debugging/debugging-log.html"><span class="en">Reading and Writing Logs</span></a></li>
@@ -145,14 +145,6 @@
     </ul>
   </li>
 
-  <li class="nav-section">
-    <div class="nav-section-header"><a href="<?cs var:toroot ?>tools/support-library/index.html"><span
-class="en">Support Library</span></a></div>
-    <ul>
-      <li><a href="<?cs var:toroot ?>tools/support-library/features.html">Features</a></li>
-      <li><a href="<?cs var:toroot ?>tools/support-library/setup.html">Setup</a></li>
-    </ul>
-  </li>
 
   <li class="nav-section">
     <div class="nav-section-header"><a href="<?cs var:toroot ?>tools/help/index.html"><span
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 1e360d3..3fe408a 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -714,10 +714,17 @@
                     mDrawableFutures = new SparseArray<ConstantStateFuture>(mNumChildren);
                 }
 
+                // Create futures for drawables with constant states. If a
+                // drawable doesn't have a constant state, then we can't clone
+                // it and we'll have to reference the original.
                 final int N = mNumChildren;
                 for (int i = 0; i < N; i++) {
                     if (origDr[i] != null) {
-                        mDrawableFutures.put(i, new ConstantStateFuture(origDr[i]));
+                        if (origDr[i].getConstantState() != null) {
+                            mDrawableFutures.put(i, new ConstantStateFuture(origDr[i]));
+                        } else {
+                            mDrawables[i] = origDr[i];
+                        }
                     }
                 }
             } else {
diff --git a/include/androidfw/AttributeFinder.h b/include/androidfw/AttributeFinder.h
index a0ffeb3..acf7056 100644
--- a/include/androidfw/AttributeFinder.h
+++ b/include/androidfw/AttributeFinder.h
@@ -64,6 +64,7 @@
     void jumpToClosestAttribute(uint32_t packageId);
     void markCurrentPackageId(uint32_t packageId);
 
+    bool mFirstTime;
     Iterator mBegin;
     Iterator mEnd;
     Iterator mCurrent;
@@ -81,7 +82,8 @@
 
 template <typename Derived, typename Iterator> inline
 BackTrackingAttributeFinder<Derived, Iterator>::BackTrackingAttributeFinder(const Iterator& begin, const Iterator& end)
-    : mBegin(begin)
+    : mFirstTime(true)
+    , mBegin(begin)
     , mEnd(end)
     , mCurrent(begin)
     , mLargest(begin)
@@ -145,8 +147,11 @@
         return mEnd;
     }
 
-    if (mCurrentAttr == 0) {
-        // One-time initialization.
+    if (mFirstTime) {
+        // One-time initialization. We do this here instead of the constructor
+        // because the derived class we access in getAttribute() may not be
+        // fully constructed.
+        mFirstTime = false;
         mCurrentAttr = static_cast<const Derived*>(this)->getAttribute(mBegin);
         mLastPackageId = getPackage(mCurrentAttr);
         markCurrentPackageId(mLastPackageId);
diff --git a/libs/androidfw/tests/AttributeFinder_test.cpp b/libs/androidfw/tests/AttributeFinder_test.cpp
index 664709c..5054624 100644
--- a/libs/androidfw/tests/AttributeFinder_test.cpp
+++ b/libs/androidfw/tests/AttributeFinder_test.cpp
@@ -50,6 +50,10 @@
         0x01010002, 0x01010004, 0x7f010001
 };
 
+static const uint32_t singlePackageAttributes[] = {
+        0x7f010007, 0x7f01000a, 0x7f01000d, 0x00000000
+};
+
 TEST(AttributeFinderTest, IteratesSequentially) {
     const int end = sizeof(sortedAttributes) / sizeof(*sortedAttributes);
     MockAttributeFinder finder(sortedAttributes, end);
@@ -109,3 +113,16 @@
     EXPECT_EQ(1, finder.find(0x02010010));
     EXPECT_EQ(6, finder.find(0x7f010001));
 }
+
+TEST(AttributeFinderTest, FindAttributesInSinglePackageAttributeList) {
+    const int end = sizeof(singlePackageAttributes) / sizeof(*singlePackageAttributes);
+    MockAttributeFinder finder(singlePackageAttributes, end);
+
+    EXPECT_EQ(end, finder.find(0x010100f4));
+    EXPECT_EQ(end, finder.find(0x010100f5));
+    EXPECT_EQ(end, finder.find(0x010100f6));
+    EXPECT_EQ(end, finder.find(0x010100f7));
+    EXPECT_EQ(end, finder.find(0x010100f8));
+    EXPECT_EQ(end, finder.find(0x010100fa));
+    EXPECT_EQ(0, finder.find(0x7f010007));
+}
diff --git a/libs/hwui/AmbientShadow.cpp b/libs/hwui/AmbientShadow.cpp
index 21c869b..b2dba00 100644
--- a/libs/hwui/AmbientShadow.cpp
+++ b/libs/hwui/AmbientShadow.cpp
@@ -325,6 +325,7 @@
     // At the end, update the real index and vertex buffer size.
     shadowVertexBuffer.updateVertexCount(vertexBufferIndex);
     shadowVertexBuffer.updateIndexCount(indexBufferIndex);
+    shadowVertexBuffer.computeBounds<AlphaVertex>();
 
     ShadowTessellator::checkOverflow(vertexBufferIndex, totalVertexCount, "Ambient Vertex Buffer");
     ShadowTessellator::checkOverflow(indexBufferIndex, totalIndexCount, "Ambient Index Buffer");
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index cb8a8d1..7a43a2a 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -77,18 +77,14 @@
     OpenGLRenderer& mRenderer;
     const int mReplayFlags;
 
-    // Allocator with the lifetime of a single frame.
-    // replay uses an Allocator owned by the struct, while defer shares the DeferredDisplayList's Allocator
+    // Allocator with the lifetime of a single frame. replay uses an Allocator owned by the struct,
+    // while defer shares the DeferredDisplayList's Allocator
+    // TODO: move this allocator to be owned by object with clear frame lifecycle
     LinearAllocator * const mAllocator;
 
     SkPath* allocPathForFrame() {
-        mTempPaths.push_back();
-        return &mTempPaths.back();
+        return mRenderer.allocPathForFrame();
     }
-
-private:
-    // Paths kept alive for the duration of the frame
-    std::vector<SkPath> mTempPaths;
 };
 
 class DeferStateStruct : public PlaybackStateStruct {
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 075f2c5..96257e4 100755
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -311,6 +311,11 @@
     renderOverdraw();
     endTiling();
 
+    for (size_t i = 0; i < mTempPaths.size(); i++) {
+        delete mTempPaths[i];
+    }
+    mTempPaths.clear();
+
     // When finish() is invoked on FBO 0 we've reached the end
     // of the current frame
     if (getTargetFbo() == 0) {
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index e1c3d10..5eee2e2 100755
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -342,6 +342,12 @@
     uint8_t getAmbientShadowAlpha() const { return mAmbientShadowAlpha; }
     uint8_t getSpotShadowAlpha() const { return mSpotShadowAlpha; }
 
+    SkPath* allocPathForFrame() {
+        SkPath* path = new SkPath();
+        mTempPaths.push_back(path);
+        return path;
+    }
+
 protected:
     /**
      * Perform the setup specific to a frame. This method does not
@@ -1014,6 +1020,9 @@
     uint8_t mAmbientShadowAlpha;
     uint8_t mSpotShadowAlpha;
 
+    // Paths kept alive for the duration of the frame
+    std::vector<SkPath*> mTempPaths;
+
     friend class Layer;
     friend class TextSetupFunctor;
     friend class DrawBitmapOp;
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 89aebe8..63a0cf6 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -3421,7 +3421,7 @@
                 return false;
             }
 
-            // Windows are ordered in z order so start from the botton and find
+            // Windows are ordered in z order so start from the bottom and find
             // the window of interest. After that all windows that cover it should
             // be subtracted from the resulting region. Note that for accessibility
             // we are returning only interactive windows.
@@ -3439,7 +3439,8 @@
                         windowInteractiveRegion = outRegion;
                         continue;
                     }
-                } else {
+                } else if (currentWindow.getType()
+                        != AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY) {
                     Rect currentWindowBounds = mTempRect;
                     currentWindow.getBoundsInScreen(currentWindowBounds);
                     if (windowInteractiveRegion.op(currentWindowBounds, Region.Op.DIFFERENCE)) {
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 3117a17..ca376fd 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -535,15 +535,14 @@
                     Log.d(TAG, "Creating new ProfileServiceConnections object for"
                             + " profile: " + bluetoothProfile);
                 }
-                Intent intent = null;
-                if (bluetoothProfile == BluetoothProfile.HEADSET) {
-                    intent = new Intent(IBluetoothHeadset.class.getName());
-                } else {
-                    return false;
-                }
+
+                if (bluetoothProfile != BluetoothProfile.HEADSET) return false;
+
+                Intent intent = new Intent(IBluetoothHeadset.class.getName());
                 psc = new ProfileServiceConnections(intent);
+                if (!psc.bindService()) return false;
+
                 mProfileServices.put(new Integer(bluetoothProfile), psc);
-                psc.bindService();
             }
         }
 
@@ -571,7 +570,11 @@
         synchronized (mProfileServices) {
             for (Integer i : mProfileServices.keySet()) {
                 ProfileServiceConnections psc = mProfileServices.get(i);
-                mContext.unbindService(psc);
+                try {
+                    mContext.unbindService(psc);
+                } catch (IllegalArgumentException e) {
+                    Log.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
+                }
                 psc.removeAllProxies();
             }
             mProfileServices.clear();
@@ -596,16 +599,16 @@
             mIntent = intent;
         }
 
-        private void bindService() {
-            if (mIntent != null && mService == null) {
-                if (!doBind(mIntent, this, 0, UserHandle.CURRENT_OR_SELF)) {
-                    Log.w(TAG, "Unable to bind with intent: " + mIntent
-                            + ". Triggering retry.");
-                }
+        private boolean bindService() {
+            if (mIntent != null && mService == null &&
+                    doBind(mIntent, this, 0, UserHandle.CURRENT_OR_SELF)) {
                 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
                 msg.obj = this;
                 mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
+                return true;
             }
+            Log.w(TAG, "Unable to bind with intent: " + mIntent);
+            return false;
         }
 
         private void addProxy(IBluetoothProfileServiceConnection proxy) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 1227148..82afeed 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1841,7 +1841,9 @@
                         proc = mPendingPssProcesses.remove(0);
                         procState = proc.pssProcState;
                         lastPssTime = proc.lastPssTime;
-                        if (proc.thread != null && procState == proc.setProcState) {
+                        if (proc.thread != null && procState == proc.setProcState
+                                && (lastPssTime+ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE)
+                                        < SystemClock.uptimeMillis()) {
                             pid = proc.pid;
                         } else {
                             proc = null;
@@ -17746,7 +17748,8 @@
                     + (app.nextPssTime-now) + ": " + app);
         } else {
             if (now > app.nextPssTime || (now > (app.lastPssTime+ProcessList.PSS_MAX_INTERVAL)
-                    && now > (app.lastStateTime+ProcessList.PSS_MIN_TIME_FROM_STATE_CHANGE))) {
+                    && now > (app.lastStateTime+ProcessList.minTimeFromStateChange(
+                    mTestPssMode)))) {
                 requestPssLocked(app, app.setProcState);
                 app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, false,
                         mTestPssMode, isSleeping(), now);
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index aa86786..ae4af5f 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -238,7 +238,7 @@
         if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
             // Increase the high min-free levels for cached processes for 64-bit
             mOomMinFreeHigh[4] = (mOomMinFreeHigh[4]*3)/2;
-            mOomMinFreeHigh[5] = (mOomMinFreeHigh[5]*7)/8;
+            mOomMinFreeHigh[5] = (mOomMinFreeHigh[5]*7)/4;
         }
 
         for (int i=0; i<mOomAdj.length; i++) {
@@ -411,7 +411,10 @@
         sb.append(ramKb);
     }
 
-    // The minimum amount of time after a state change it is safe ro collect PSS.
+    // How long after a state change that it is safe to collect PSS without it being dirty.
+    public static final int PSS_SAFE_TIME_FROM_STATE_CHANGE = 1000;
+
+    // The minimum time interval after a state change it is safe to collect PSS.
     public static final int PSS_MIN_TIME_FROM_STATE_CHANGE = 15*1000;
 
     // The maximum amount of time we want to go between PSS collections.
@@ -441,6 +444,9 @@
     // The amount of time until PSS when a cached process stays in the same state.
     private static final int PSS_SAME_CACHED_INTERVAL = 30*60*1000;
 
+    // The minimum time interval after a state change it is safe to collect PSS.
+    public static final int PSS_TEST_MIN_TIME_FROM_STATE_CHANGE = 10*1000;
+
     // The amount of time during testing until PSS when a process first becomes top.
     private static final int PSS_TEST_FIRST_TOP_INTERVAL = 3*1000;
 
@@ -548,6 +554,10 @@
         return sProcStateToProcMem[procState1] != sProcStateToProcMem[procState2];
     }
 
+    public static long minTimeFromStateChange(boolean test) {
+        return test ? PSS_TEST_MIN_TIME_FROM_STATE_CHANGE : PSS_MIN_TIME_FROM_STATE_CHANGE;
+    }
+
     public static long computeNextPssTime(int procState, boolean first, boolean test,
             boolean sleeping, long now) {
         final long[] table = test
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index bb99916..650f0e2 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1028,6 +1028,7 @@
                 ? mListenersDisablingEffects.valueAt(0).component : null;
         if (Objects.equals(suppressor, mEffectsSuppressor)) return;
         mEffectsSuppressor = suppressor;
+        mZenModeHelper.setEffectsSuppressed(suppressor != null);
         getContext().sendBroadcast(new Intent(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED)
                 .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY));
     }
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 012e22f..31d5cd7 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -17,6 +17,7 @@
 package com.android.server.notification;
 
 import static android.media.AudioAttributes.USAGE_ALARM;
+import static android.media.AudioAttributes.USAGE_NOTIFICATION;
 import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
 
 import android.app.AppOpsManager;
@@ -77,6 +78,7 @@
     private ZenModeConfig mConfig;
     private AudioManagerInternal mAudioManager;
     private int mPreviousRingerMode = -1;
+    private boolean mEffectsSuppressed;
 
     public ZenModeHelper(Context context, Looper looper) {
         mContext = context;
@@ -153,6 +155,12 @@
         }
     }
 
+    public void setEffectsSuppressed(boolean effectsSuppressed) {
+        if (mEffectsSuppressed == effectsSuppressed) return;
+        mEffectsSuppressed = effectsSuppressed;
+        applyRestrictions();
+    }
+
     public boolean shouldIntercept(NotificationRecord record) {
         if (isSystem(record)) {
             return false;
@@ -225,29 +233,35 @@
             ZenLog.traceUpdateZenMode(oldMode, newMode);
         }
         mZenMode = newMode;
+        applyRestrictions();
+        onZenUpdated(oldMode, newMode);
+        dispatchOnZenModeChanged();
+    }
+
+    private void applyRestrictions() {
         final boolean zen = mZenMode != Global.ZEN_MODE_OFF;
-        final String[] exceptionPackages = null; // none (for now)
+
+        // notification restrictions
+        final boolean muteNotifications = mEffectsSuppressed;
+        applyRestrictions(muteNotifications, USAGE_NOTIFICATION);
 
         // call restrictions
-        final boolean muteCalls = zen && !mConfig.allowCalls;
-        mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, USAGE_NOTIFICATION_RINGTONE,
-                muteCalls ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
-                exceptionPackages);
-        mAppOps.setRestriction(AppOpsManager.OP_PLAY_AUDIO, USAGE_NOTIFICATION_RINGTONE,
-                muteCalls ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
-                exceptionPackages);
+        final boolean muteCalls = zen && !mConfig.allowCalls || mEffectsSuppressed;
+        applyRestrictions(muteCalls, USAGE_NOTIFICATION_RINGTONE);
 
         // alarm restrictions
         final boolean muteAlarms = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
-        mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, USAGE_ALARM,
-                muteAlarms ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
-                exceptionPackages);
-        mAppOps.setRestriction(AppOpsManager.OP_PLAY_AUDIO, USAGE_ALARM,
-                muteAlarms ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
-                exceptionPackages);
+        applyRestrictions(muteAlarms, USAGE_ALARM);
+    }
 
-        onZenUpdated(oldMode, newMode);
-        dispatchOnZenModeChanged();
+    private void applyRestrictions(boolean mute, int usage) {
+        final String[] exceptionPackages = null; // none (for now)
+        mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, usage,
+                mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
+                exceptionPackages);
+        mAppOps.setRestriction(AppOpsManager.OP_PLAY_AUDIO, usage,
+                mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
+                exceptionPackages);
     }
 
     public void dump(PrintWriter pw, String prefix) {
@@ -257,6 +271,7 @@
         pw.print(prefix); pw.print("mDefaultConfig="); pw.println(mDefaultConfig);
         pw.print(prefix); pw.print("mPreviousRingerMode="); pw.println(mPreviousRingerMode);
         pw.print(prefix); pw.print("mDefaultPhoneApp="); pw.println(mDefaultPhoneApp);
+        pw.print(prefix); pw.print("mEffectsSuppressed="); pw.println(mEffectsSuppressed);
     }
 
     public void readXml(XmlPullParser parser) throws XmlPullParserException, IOException {
diff --git a/services/core/java/com/android/server/wm/KeyguardDisableHandler.java b/services/core/java/com/android/server/wm/KeyguardDisableHandler.java
index c1420a8..37d811f 100644
--- a/services/core/java/com/android/server/wm/KeyguardDisableHandler.java
+++ b/services/core/java/com/android/server/wm/KeyguardDisableHandler.java
@@ -68,9 +68,18 @@
                 break;
 
             case KEYGUARD_POLICY_CHANGED:
-                mPolicy.enableKeyguard(true);
-                // lazily evaluate this next time we're asked to disable keyguard
                 mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN;
+                if (mKeyguardTokenWatcher.isAcquired()) {
+                    // If we are currently disabled we need to know if the keyguard
+                    // should be re-enabled, so determine the allow state immediately.
+                    mKeyguardTokenWatcher.updateAllowState();
+                    if (mAllowDisableKeyguard != ALLOW_DISABLE_YES) {
+                        mPolicy.enableKeyguard(true);
+                    }
+                } else {
+                    // lazily evaluate this next time we're asked to disable keyguard
+                    mPolicy.enableKeyguard(true);
+                }
                 break;
         }
     }
@@ -81,24 +90,28 @@
             super(handler, TAG);
         }
 
-        @Override
-        public void acquired() {
+        public void updateAllowState() {
             // We fail safe and prevent disabling keyguard in the unlikely event this gets
             // called before DevicePolicyManagerService has started.
-            if (mAllowDisableKeyguard == ALLOW_DISABLE_UNKNOWN) {
-                DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
-                        Context.DEVICE_POLICY_SERVICE);
-                if (dpm != null) {
-                    try {
-                        mAllowDisableKeyguard = dpm.getPasswordQuality(null, 
-                                ActivityManagerNative.getDefault().getCurrentUser().id)
-                                == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED ?
-                                        ALLOW_DISABLE_YES : ALLOW_DISABLE_NO;
-                    } catch (RemoteException re) {
-                        // Nothing much we can do
-                    }
+            DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
+                    Context.DEVICE_POLICY_SERVICE);
+            if (dpm != null) {
+                try {
+                    mAllowDisableKeyguard = dpm.getPasswordQuality(null,
+                            ActivityManagerNative.getDefault().getCurrentUser().id)
+                            == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED ?
+                                    ALLOW_DISABLE_YES : ALLOW_DISABLE_NO;
+                } catch (RemoteException re) {
+                    // Nothing much we can do
                 }
             }
+        }
+
+        @Override
+        public void acquired() {
+            if (mAllowDisableKeyguard == ALLOW_DISABLE_UNKNOWN) {
+                updateAllowState();
+            }
             if (mAllowDisableKeyguard == ALLOW_DISABLE_YES) {
                 mPolicy.enableKeyguard(false);
             } else {