Merge "Add privapp permissions permission for com.android.cellbroadcastreceiver package." into rvc-dev
diff --git a/cmds/statsd/src/anomaly/AlarmTracker.cpp b/cmds/statsd/src/anomaly/AlarmTracker.cpp
index 5722f92..6d9beb8 100644
--- a/cmds/statsd/src/anomaly/AlarmTracker.cpp
+++ b/cmds/statsd/src/anomaly/AlarmTracker.cpp
@@ -60,11 +60,11 @@
 }
 
 int64_t AlarmTracker::findNextAlarmSec(int64_t currentTimeSec) {
-    if (currentTimeSec <= mAlarmSec) {
+    if (currentTimeSec < mAlarmSec) {
         return mAlarmSec;
     }
     int64_t periodsForward =
-        ((currentTimeSec - mAlarmSec) * MS_PER_SEC - 1) / mAlarmConfig.period_millis() + 1;
+        ((currentTimeSec - mAlarmSec) * MS_PER_SEC) / mAlarmConfig.period_millis() + 1;
     return mAlarmSec + periodsForward * mAlarmConfig.period_millis() / MS_PER_SEC;
 }
 
diff --git a/cmds/statsd/tests/anomaly/AlarmTracker_test.cpp b/cmds/statsd/tests/anomaly/AlarmTracker_test.cpp
index 322cfaf..64ea219 100644
--- a/cmds/statsd/tests/anomaly/AlarmTracker_test.cpp
+++ b/cmds/statsd/tests/anomaly/AlarmTracker_test.cpp
@@ -43,23 +43,47 @@
     alarm.set_offset_millis(15 * MS_PER_SEC);
     alarm.set_period_millis(60 * 60 * MS_PER_SEC);  // 1hr
     int64_t startMillis = 100000000 * MS_PER_SEC;
+    int64_t nextAlarmTime = startMillis / MS_PER_SEC + 15;
     AlarmTracker tracker(startMillis, startMillis, alarm, kConfigKey, subscriberAlarmMonitor);
 
-    EXPECT_EQ(tracker.mAlarmSec, (int64_t)(startMillis / MS_PER_SEC + 15));
+    EXPECT_EQ(tracker.mAlarmSec, nextAlarmTime);
 
     uint64_t currentTimeSec = startMillis / MS_PER_SEC + 10;
     std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> firedAlarmSet =
         subscriberAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec));
     EXPECT_TRUE(firedAlarmSet.empty());
     tracker.informAlarmsFired(currentTimeSec * NS_PER_SEC, firedAlarmSet);
-    EXPECT_EQ(tracker.mAlarmSec, (int64_t)(startMillis / MS_PER_SEC + 15));
+    EXPECT_EQ(tracker.mAlarmSec, nextAlarmTime);
+    EXPECT_EQ(tracker.getAlarmTimestampSec(), nextAlarmTime);
 
     currentTimeSec = startMillis / MS_PER_SEC + 7000;
+    nextAlarmTime = startMillis / MS_PER_SEC + 15 + 2 * 60 * 60;
     firedAlarmSet = subscriberAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec));
     ASSERT_EQ(firedAlarmSet.size(), 1u);
     tracker.informAlarmsFired(currentTimeSec * NS_PER_SEC, firedAlarmSet);
     EXPECT_TRUE(firedAlarmSet.empty());
-    EXPECT_EQ(tracker.mAlarmSec, (int64_t)(startMillis / MS_PER_SEC + 15 + 2 * 60 * 60));
+    EXPECT_EQ(tracker.mAlarmSec, nextAlarmTime);
+    EXPECT_EQ(tracker.getAlarmTimestampSec(), nextAlarmTime);
+
+    // Alarm fires exactly on time.
+    currentTimeSec = startMillis / MS_PER_SEC + 15 + 2 * 60 * 60;
+    nextAlarmTime = startMillis / MS_PER_SEC + 15 + 3 * 60 * 60;
+    firedAlarmSet = subscriberAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec));
+    ASSERT_EQ(firedAlarmSet.size(), 1u);
+    tracker.informAlarmsFired(currentTimeSec * NS_PER_SEC, firedAlarmSet);
+    EXPECT_TRUE(firedAlarmSet.empty());
+    EXPECT_EQ(tracker.mAlarmSec, nextAlarmTime);
+    EXPECT_EQ(tracker.getAlarmTimestampSec(), nextAlarmTime);
+
+    // Alarm fires exactly 1 period late.
+    currentTimeSec = startMillis / MS_PER_SEC + 15 + 4 * 60 * 60;
+    nextAlarmTime = startMillis / MS_PER_SEC + 15 + 5 * 60 * 60;
+    firedAlarmSet = subscriberAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec));
+    ASSERT_EQ(firedAlarmSet.size(), 1u);
+    tracker.informAlarmsFired(currentTimeSec * NS_PER_SEC, firedAlarmSet);
+    EXPECT_TRUE(firedAlarmSet.empty());
+    EXPECT_EQ(tracker.mAlarmSec, nextAlarmTime);
+    EXPECT_EQ(tracker.getAlarmTimestampSec(), nextAlarmTime);
 }
 
 }  // namespace statsd
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index 2d2dda0..e385cd2 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -121,7 +121,7 @@
 
         /**
          * Any biometric (e.g. fingerprint, iris, or face) on the device that meets or exceeds the
-         * requirements for <strong>Tier 3</strong> (formerly <strong>Strong</strong>), as defined
+         * requirements for <strong>Class 3</strong> (formerly <strong>Strong</strong>), as defined
          * by the Android CDD.
          *
          * <p>This corresponds to {@link KeyProperties#AUTH_BIOMETRIC_STRONG} during key generation.
@@ -132,7 +132,7 @@
 
         /**
          * Any biometric (e.g. fingerprint, iris, or face) on the device that meets or exceeds the
-         * requirements for <strong>Tier 2</strong> (formerly <strong>Weak</strong>), as defined by
+         * requirements for <strong>Class 2</strong> (formerly <strong>Weak</strong>), as defined by
          * the Android CDD.
          *
          * <p>Note that this is a superset of {@link #BIOMETRIC_STRONG} and is defined such that
@@ -142,7 +142,7 @@
 
         /**
          * Any biometric (e.g. fingerprint, iris, or face) on the device that meets or exceeds the
-         * requirements for <strong>Tier 1</strong> (formerly <strong>Convenience</strong>), as
+         * requirements for <strong>Class 1</strong> (formerly <strong>Convenience</strong>), as
          * defined by the Android CDD.
          *
          * <p>This constant is intended for use by {@link android.provider.DeviceConfig} to adjust
diff --git a/packages/SystemUI/res/layout/media_view.xml b/packages/SystemUI/res/layout/media_view.xml
index 3cafa1d..8441282 100644
--- a/packages/SystemUI/res/layout/media_view.xml
+++ b/packages/SystemUI/res/layout/media_view.xml
@@ -141,6 +141,7 @@
             android:layout_width="@dimen/qs_seamless_icon_size"
             android:layout_height="@dimen/qs_seamless_icon_size"
             android:layout_marginEnd="8dp"
+            android:layout_gravity="center_vertical"
             android:tint="@color/media_primary_text"
             android:src="@*android:drawable/ic_media_seamless" />
 
@@ -148,6 +149,7 @@
             android:id="@+id/media_seamless_text"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
             android:fontFamily="@*android:string/config_headlineFontFamily"
             android:singleLine="true"
             android:text="@*android:string/ext_media_seamless_action"
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index ee31706..7792afa 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -251,7 +251,8 @@
     private boolean mDeviceProvisioned;
 
     // Battery status
-    private BatteryStatus mBatteryStatus;
+    @VisibleForTesting
+    BatteryStatus mBatteryStatus;
 
     private StrongAuthTracker mStrongAuthTracker;
 
@@ -1698,6 +1699,17 @@
                     .getServiceStateForSubscriber(subId);
             mHandler.sendMessage(
                     mHandler.obtainMessage(MSG_SERVICE_STATE_CHANGE, subId, 0, serviceState));
+
+            // Get initial state. Relying on Sticky behavior until API for getting info.
+            if (mBatteryStatus == null) {
+                Intent intent = mContext.registerReceiver(
+                        null,
+                        new IntentFilter(Intent.ACTION_BATTERY_CHANGED)
+                );
+                if (intent != null && mBatteryStatus == null) {
+                    mBroadcastReceiver.onReceive(mContext, intent);
+                }
+            }
         });
 
         mHandler.post(this::registerRingerTracker);
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 2bfe015..1211fb4 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -495,12 +495,9 @@
         }
         final float alpha = visibility ? 1f : 0f;
 
-        if (alpha == mActivityView.getAlpha()) {
-            return;
-        }
-
         mPointerView.setAlpha(alpha);
-        if (mActivityView != null) {
+
+        if (mActivityView != null && alpha != mActivityView.getAlpha()) {
             mActivityView.setAlpha(alpha);
             mActivityView.bringToFront();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
index 5052386..d6b6660 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -193,12 +193,15 @@
     private fun clearData() {
         // Called on user change. Remove all current MediaData objects and inform listeners
         val listenersCopy = listeners.toSet()
-        mediaEntries.forEach {
+        val keyCopy = mediaEntries.keys.toMutableList()
+        // Clear the list first, to make sure callbacks from listeners if we have any entries
+        // are up to date
+        mediaEntries.clear()
+        keyCopy.forEach {
             listenersCopy.forEach { listener ->
-                listener.onMediaDataRemoved(it.key)
+                listener.onMediaDataRemoved(it)
             }
         }
-        mediaEntries.clear()
     }
 
     private fun removeAllForPackage(packageName: String) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
index 330b20e..a7dd53e4 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
@@ -224,6 +224,16 @@
         return new Rect(mLastReportedBounds);
     }
 
+    public Rect getCurrentOrAnimatingBounds() {
+        PipAnimationController.PipTransitionAnimator animator =
+                mPipAnimationController.getCurrentAnimator();
+        if (animator != null && animator.isRunning()) {
+            System.out.println("RUNNING ANIM: anim=" + animator.getDestinationBounds() + " last=" + getLastReportedBounds());
+            return new Rect(animator.getDestinationBounds());
+        }
+        return getLastReportedBounds();
+    }
+
     public boolean isInPip() {
         return mInPip;
     }
@@ -406,7 +416,7 @@
 
     private void sendOnPipTransitionStarted(
             @PipAnimationController.TransitionDirection int direction) {
-        mMainHandler.post(() -> {
+        runOnMainHandler(() -> {
             for (int i = mPipTransitionCallbacks.size() - 1; i >= 0; i--) {
                 final PipTransitionCallback callback = mPipTransitionCallbacks.get(i);
                 callback.onPipTransitionStarted(mTaskInfo.baseActivity, direction);
@@ -416,7 +426,7 @@
 
     private void sendOnPipTransitionFinished(
             @PipAnimationController.TransitionDirection int direction) {
-        mMainHandler.post(() -> {
+        runOnMainHandler(() -> {
             for (int i = mPipTransitionCallbacks.size() - 1; i >= 0; i--) {
                 final PipTransitionCallback callback = mPipTransitionCallbacks.get(i);
                 callback.onPipTransitionFinished(mTaskInfo.baseActivity, direction);
@@ -426,7 +436,7 @@
 
     private void sendOnPipTransitionCancelled(
             @PipAnimationController.TransitionDirection int direction) {
-        mMainHandler.post(() -> {
+        runOnMainHandler(() -> {
             for (int i = mPipTransitionCallbacks.size() - 1; i >= 0; i--) {
                 final PipTransitionCallback callback = mPipTransitionCallbacks.get(i);
                 callback.onPipTransitionCanceled(mTaskInfo.baseActivity, direction);
@@ -434,6 +444,14 @@
         });
     }
 
+    private void runOnMainHandler(Runnable r) {
+        if (Looper.getMainLooper() == Looper.myLooper()) {
+            r.run();
+        } else {
+            mMainHandler.post(r);
+        }
+    }
+
     /**
      * Note that dismissing PiP is now originated from SystemUI, see {@link #exitPip(int)}.
      * Meanwhile this callback is invoked whenever the task is removed. For instance:
@@ -505,15 +523,29 @@
      */
     @SuppressWarnings("unchecked")
     public void onMovementBoundsChanged(Rect destinationBoundsOut, boolean fromRotation,
-            boolean fromImeAdjustment, boolean fromShelfAdjustment) {
+            boolean fromImeAdjustment, boolean fromShelfAdjustment,
+            WindowContainerTransaction wct) {
         final PipAnimationController.PipTransitionAnimator animator =
                 mPipAnimationController.getCurrentAnimator();
         if (animator == null || !animator.isRunning()
                 || animator.getTransitionDirection() != TRANSITION_DIRECTION_TO_PIP) {
             if (mInPip && fromRotation) {
-                // this could happen if rotation finishes before the animation
+                // If we are rotating while there is a current animation, immediately cancel the
+                // animation (remove the listeners so we don't trigger the normal finish resize
+                // call that should only happen on the update thread)
+                int direction = animator.getTransitionDirection();
+                animator.removeAllUpdateListeners();
+                animator.removeAllListeners();
+                animator.cancel();
+                // Do notify the listeners that this was canceled
+                sendOnPipTransitionCancelled(direction);
                 mLastReportedBounds.set(destinationBoundsOut);
-                scheduleFinishResizePip(mLastReportedBounds);
+
+                // Create a reset surface transaction for the new bounds and update the window
+                // container transaction
+                final SurfaceControl.Transaction tx = createFinishResizeSurfaceTransaction(
+                        destinationBoundsOut);
+                prepareFinishResizeTransaction(destinationBoundsOut, direction, tx, wct);
             } else  {
                 // There could be an animation on-going. If there is one on-going, last-reported
                 // bounds isn't yet updated. We'll use the animator's bounds instead.
@@ -622,7 +654,7 @@
      * {@link #scheduleResizePip}.
      */
     public void scheduleFinishResizePip(Rect destinationBounds) {
-        scheduleFinishResizePip(destinationBounds, null);
+        scheduleFinishResizePip(destinationBounds, null /* updateBoundsCallback */);
     }
 
     /**
@@ -630,30 +662,36 @@
      */
     public void scheduleFinishResizePip(Rect destinationBounds,
             Consumer<Rect> updateBoundsCallback) {
-        final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
-        mSurfaceTransactionHelper
-                .crop(tx, mLeash, destinationBounds)
-                .resetScale(tx, mLeash, destinationBounds)
-                .round(tx, mLeash, mInPip);
-        scheduleFinishResizePip(tx, destinationBounds, TRANSITION_DIRECTION_NONE,
-                updateBoundsCallback);
+        scheduleFinishResizePip(destinationBounds, TRANSITION_DIRECTION_NONE, updateBoundsCallback);
     }
 
-    private void scheduleFinishResizePip(SurfaceControl.Transaction tx,
-            Rect destinationBounds, @PipAnimationController.TransitionDirection int direction,
+    private void scheduleFinishResizePip(Rect destinationBounds,
+            @PipAnimationController.TransitionDirection int direction,
             Consumer<Rect> updateBoundsCallback) {
         if (!mInPip) {
             // can be initiated in other component, ignore if we are no longer in PIP
             return;
         }
+
         SomeArgs args = SomeArgs.obtain();
         args.arg1 = updateBoundsCallback;
-        args.arg2 = tx;
+        args.arg2 = createFinishResizeSurfaceTransaction(
+                destinationBounds);
         args.arg3 = destinationBounds;
         args.argi1 = direction;
         mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_FINISH_RESIZE, args));
     }
 
+    private SurfaceControl.Transaction createFinishResizeSurfaceTransaction(
+            Rect destinationBounds) {
+        final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
+        mSurfaceTransactionHelper
+                .crop(tx, mLeash, destinationBounds)
+                .resetScale(tx, mLeash, destinationBounds)
+                .round(tx, mLeash, mInPip);
+        return tx;
+    }
+
     /**
      * Offset the PiP window by a given offset on Y-axis, triggered also from screen rotation.
      */
@@ -741,7 +779,15 @@
             return;
         }
 
-        final WindowContainerTransaction wct = new WindowContainerTransaction();
+        WindowContainerTransaction wct = new WindowContainerTransaction();
+        prepareFinishResizeTransaction(destinationBounds, direction, tx, wct);
+        applyFinishBoundsResize(wct, direction);
+    }
+
+    private void prepareFinishResizeTransaction(Rect destinationBounds,
+            @PipAnimationController.TransitionDirection int direction,
+            SurfaceControl.Transaction tx,
+            WindowContainerTransaction wct) {
         final Rect taskBounds;
         if (isInPipDirection(direction)) {
             // If we are animating from fullscreen using a bounds animation, then reset the
@@ -762,7 +808,6 @@
 
         wct.setBounds(mToken, taskBounds);
         wct.setBoundsChangeTransaction(mToken, tx);
-        applyFinishBoundsResize(wct, direction);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 7a18ec3..1fbe58d 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -36,6 +36,7 @@
 import android.util.Pair;
 import android.view.DisplayInfo;
 import android.view.IPinnedStackController;
+import android.view.SurfaceControl;
 import android.window.WindowContainerTransaction;
 
 import com.android.systemui.Dependency;
@@ -94,9 +95,12 @@
      */
     private final DisplayChangeController.OnDisplayChangingListener mRotationController = (
             int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) -> {
+        // If there is an animation running (ie. from a shelf offset), then ensure that we calculate
+        // the bounds for the next orientation using the destination bounds of the animation
+        // TODO: Techincally this should account for movement animation bounds as well
+        Rect currentBounds = mPipTaskOrganizer.getCurrentOrAnimatingBounds();
         final boolean changed = mPipBoundsHandler.onDisplayRotationChanged(mTmpNormalBounds,
-                mPipTaskOrganizer.getLastReportedBounds(), mTmpInsetBounds, displayId, fromRotation,
-                toRotation, t);
+                currentBounds, mTmpInsetBounds, displayId, fromRotation, toRotation, t);
         if (changed) {
             // If the pip was in the offset zone earlier, adjust the new bounds to the bottom of the
             // movement bounds
@@ -116,7 +120,7 @@
             }
 
             updateMovementBounds(mTmpNormalBounds, true /* fromRotation */,
-                    false /* fromImeAdjustment */, false /* fromShelfAdjustment */);
+                    false /* fromImeAdjustment */, false /* fromShelfAdjustment */, t);
         }
     };
 
@@ -194,7 +198,8 @@
         @Override
         public void onMovementBoundsChanged(boolean fromImeAdjustment) {
             mHandler.post(() -> updateMovementBounds(null /* toBounds */,
-                    false /* fromRotation */, fromImeAdjustment, false /* fromShelfAdjustment */));
+                    false /* fromRotation */, fromImeAdjustment, false /* fromShelfAdjustment */,
+                    null /* windowContainerTransaction */));
         }
 
         @Override
@@ -327,7 +332,7 @@
                 mTouchHandler.onShelfVisibilityChanged(visible, shelfHeight);
                 updateMovementBounds(mPipTaskOrganizer.getLastReportedBounds(),
                         false /* fromRotation */, false /* fromImeAdjustment */,
-                        true /* fromShelfAdjustment */);
+                        true /* fromShelfAdjustment */, null /* windowContainerTransaction */);
             }
         });
     }
@@ -387,15 +392,16 @@
     }
 
     private void updateMovementBounds(@Nullable Rect toBounds, boolean fromRotation,
-            boolean fromImeAdjustment, boolean fromShelfAdjustment) {
+            boolean fromImeAdjustment, boolean fromShelfAdjustment,
+            WindowContainerTransaction wct) {
         // Populate inset / normal bounds and DisplayInfo from mPipBoundsHandler before
         // passing to mTouchHandler/mPipTaskOrganizer
         final Rect outBounds = new Rect(toBounds);
         mPipBoundsHandler.onMovementBoundsChanged(mTmpInsetBounds, mTmpNormalBounds,
                 outBounds, mTmpDisplayInfo);
         // mTouchHandler would rely on the bounds populated from mPipTaskOrganizer
-        mPipTaskOrganizer.onMovementBoundsChanged(outBounds, fromRotation,
-                fromImeAdjustment, fromShelfAdjustment);
+        mPipTaskOrganizer.onMovementBoundsChanged(outBounds, fromRotation, fromImeAdjustment,
+                fromShelfAdjustment, wct);
         mTouchHandler.onMovementBoundsChanged(mTmpInsetBounds, mTmpNormalBounds,
                 outBounds, fromImeAdjustment, fromShelfAdjustment,
                 mTmpDisplayInfo.rotation);
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index 078c540..66804be 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -225,6 +225,8 @@
     @VisibleForTesting
     final class Receiver extends BroadcastReceiver {
 
+        private boolean mHasReceivedBattery = false;
+
         public void init() {
             // Register for Intent broadcasts for...
             IntentFilter filter = new IntentFilter();
@@ -234,6 +236,17 @@
             filter.addAction(Intent.ACTION_SCREEN_ON);
             filter.addAction(Intent.ACTION_USER_SWITCHED);
             mBroadcastDispatcher.registerReceiverWithHandler(this, filter, mHandler);
+            // Force get initial values. Relying on Sticky behavior until API for getting info.
+            if (!mHasReceivedBattery) {
+                // Get initial state
+                Intent intent = mContext.registerReceiver(
+                        null,
+                        new IntentFilter(Intent.ACTION_BATTERY_CHANGED)
+                );
+                if (intent != null) {
+                    onReceive(mContext, intent);
+                }
+            }
         }
 
         @Override
@@ -246,6 +259,7 @@
                     }
                 });
             } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
+                mHasReceivedBattery = true;
                 final int oldBatteryLevel = mBatteryLevel;
                 mBatteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 100);
                 final int oldBatteryStatus = mBatteryStatus;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index 00419e6..7f35161 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -74,7 +74,8 @@
     protected boolean mPowerSave;
     private boolean mAodPowerSave;
     private boolean mTestmode = false;
-    private boolean mHasReceivedBattery = false;
+    @VisibleForTesting
+    boolean mHasReceivedBattery = false;
     private Estimate mEstimate;
     private boolean mFetchingEstimate = false;
 
@@ -102,6 +103,16 @@
     @Override
     public void init() {
         registerReceiver();
+        if (!mHasReceivedBattery) {
+            // Get initial state. Relying on Sticky behavior until API for getting info.
+            Intent intent = mContext.registerReceiver(
+                    null,
+                    new IntentFilter(Intent.ACTION_BATTERY_CHANGED)
+            );
+            if (intent != null && !mHasReceivedBattery) {
+                onReceive(mContext, intent);
+            }
+        }
         updatePowerSave();
         updateEstimate();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
index bc2a55c..7561af7 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
@@ -139,13 +139,18 @@
         if (mDisconnectedReceiver != null) {
             mBroadcastDispatcher.unregisterReceiver(mDisconnectedReceiver);
         }
+        super.onStop();
+    }
+
+    @Override
+    protected void onDestroy() {
         // If the ADB service has not yet been notified due to this dialog being closed in some
         // other way then notify the service to deny the connection to ensure system_server sends
         // a response to adbd.
         if (!mServiceNotified) {
             notifyService(false);
         }
-        super.onStop();
+        super.onDestroy();
     }
 
     @Override
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 7bc453a..9e056cf 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -211,6 +211,13 @@
     }
 
     @Test
+    public void testInitialBatteryLevelRequested() {
+        mTestableLooper.processAllMessages();
+
+        assertThat(mKeyguardUpdateMonitor.mBatteryStatus).isNotNull();
+    }
+
+    @Test
     public void testReceiversRegistered() {
         verify(mBroadcastDispatcher, atLeastOnce()).registerReceiverWithHandler(
                 eq(mKeyguardUpdateMonitor.mBroadcastReceiver),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestableContext.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestableContext.java
index 95ff98a..f29f042 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestableContext.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestableContext.java
@@ -67,27 +67,35 @@
 
     @Override
     public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
-        mRegisteredReceivers.add(receiver);
+        if (receiver != null) {
+            mRegisteredReceivers.add(receiver);
+        }
         return super.registerReceiver(receiver, filter);
     }
 
     @Override
     public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
             String broadcastPermission, Handler scheduler) {
-        mRegisteredReceivers.add(receiver);
+        if (receiver != null) {
+            mRegisteredReceivers.add(receiver);
+        }
         return super.registerReceiver(receiver, filter, broadcastPermission, scheduler);
     }
 
     @Override
     public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
             IntentFilter filter, String broadcastPermission, Handler scheduler) {
-        mRegisteredReceivers.add(receiver);
+        if (receiver != null) {
+            mRegisteredReceivers.add(receiver);
+        }
         return super.registerReceiverAsUser(receiver, user, filter, broadcastPermission, scheduler);
     }
 
     @Override
     public void unregisterReceiver(BroadcastReceiver receiver) {
-        mRegisteredReceivers.remove(receiver);
+        if (receiver != null) {
+            mRegisteredReceivers.remove(receiver);
+        }
         super.unregisterReceiver(receiver);
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
index f83fbd4..eca48c8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
@@ -59,6 +59,11 @@
     }
 
     @Test
+    public void testBatteryInitialized() {
+        Assert.assertTrue(mBatteryController.mHasReceivedBattery);
+    }
+
+    @Test
     public void testIndependentAODBatterySaver_true() {
         PowerSaveState state = new PowerSaveState.Builder()
                 .setBatterySaverEnabled(true)
diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
index df3b688..ed83a64 100644
--- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java
+++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
@@ -878,6 +878,7 @@
 
                 case MESSAGE_ADB_DENY:
                     if (mThread != null) {
+                        Slog.w(TAG, "Denying adb confirmation");
                         mThread.sendResponse("NO");
                         logAdbConnectionChanged(null, AdbProtoEnums.USER_DENIED, false);
                     }
@@ -887,7 +888,7 @@
                     String key = (String) msg.obj;
                     if ("trigger_restart_min_framework".equals(
                             SystemProperties.get("vold.decrypt"))) {
-                        Slog.d(TAG, "Deferring adb confirmation until after vold decrypt");
+                        Slog.w(TAG, "Deferring adb confirmation until after vold decrypt");
                         if (mThread != null) {
                             mThread.sendResponse("NO");
                             logAdbConnectionChanged(key, AdbProtoEnums.DENIED_VOLD_DECRYPT, false);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index e77b361..c9dbacd 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -8086,6 +8086,12 @@
     }
 
     int checkContentProviderUriPermission(Uri uri, int userId, int callingUid, int modeFlags) {
+        if (Thread.holdsLock(mActivityTaskManager.getGlobalLock())) {
+            Slog.wtf(TAG, new IllegalStateException("Unable to check Uri permission"
+                    + " because caller is holding WM lock; assuming permission denied"));
+            return PackageManager.PERMISSION_DENIED;
+        }
+
         final String name = uri.getAuthority();
         final long ident = Binder.clearCallingIdentity();
         ContentProviderHolder holder = null;
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 31712ef..b378621 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -640,13 +640,10 @@
             }
 
             // If the caller hasn't already resolved the activity, we're willing
-            // to do so here, but because that may require acquiring the AM lock
-            // as part of calculating the NeededUriGrants, we must never hold
-            // the WM lock here to avoid deadlocking.
+            // to do so here. If the caller is already holding the WM lock here,
+            // and we need to check dynamic Uri permissions, then we're forced
+            // to assume those permissions are denied to avoid deadlocking.
             if (mRequest.activityInfo == null) {
-                if (Thread.holdsLock(mService.mGlobalLock)) {
-                    Slog.wtf(TAG, new IllegalStateException("Caller must not hold WM lock"));
-                }
                 mRequest.resolveActivity(mSupervisor);
             }