Merge "Reduce timeout for DL to destroy." into sc-dev
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 317e51c..8a26578 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
+import android.app.ActivityManager.ProcessCapability;
 import android.content.ComponentName;
 import android.content.IIntentReceiver;
 import android.content.IIntentSender;
@@ -634,4 +635,9 @@
      * Return the temp allowlist type when server push messaging is over the quota.
      */
     public abstract @TempAllowListType int getPushMessagingOverQuotaBehavior();
+
+    /**
+     * Returns the capability of the given uid
+     */
+    public abstract @ProcessCapability int getUidCapability(int uid);
 }
diff --git a/core/java/android/view/ScrollCaptureTarget.java b/core/java/android/view/ScrollCaptureTarget.java
index a8bb037..44017ed 100644
--- a/core/java/android/view/ScrollCaptureTarget.java
+++ b/core/java/android/view/ScrollCaptureTarget.java
@@ -21,10 +21,13 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UiThread;
+import android.graphics.Matrix;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.CancellationSignal;
 
+import com.android.internal.util.FastMath;
+
 import java.io.PrintWriter;
 import java.util.function.Consumer;
 
@@ -40,7 +43,8 @@
     private final int mHint;
     private Rect mScrollBounds;
 
-    private final int[] mTmpIntArr = new int[2];
+    private final float[] mTmpFloatArr = new float[2];
+    private final Matrix mMatrixViewLocalToWindow = new Matrix();
 
     public ScrollCaptureTarget(@NonNull View scrollTarget, @NonNull Rect localVisibleRect,
             @NonNull Point positionInWindow, @NonNull ScrollCaptureCallback callback) {
@@ -113,15 +117,28 @@
         }
     }
 
+    private static void zero(float[] pointArray) {
+        pointArray[0] = 0;
+        pointArray[1] = 0;
+    }
+
+    private static void roundIntoPoint(Point pointObj, float[] pointArray) {
+        pointObj.x = FastMath.round(pointArray[0]);
+        pointObj.y = FastMath.round(pointArray[1]);
+    }
+
     /**
-     * Refresh the local visible bounds and its offset within the window, based on the current
+     * Refresh the local visible bounds and it's offset within the window, based on the current
      * state of the {@code containing view}.
      */
     @UiThread
     public void updatePositionInWindow() {
-        mContainingView.getLocationInWindow(mTmpIntArr);
-        mPositionInWindow.x = mTmpIntArr[0];
-        mPositionInWindow.y = mTmpIntArr[1];
+        mMatrixViewLocalToWindow.reset();
+        mContainingView.transformMatrixToGlobal(mMatrixViewLocalToWindow);
+
+        zero(mTmpFloatArr);
+        mMatrixViewLocalToWindow.mapPoints(mTmpFloatArr);
+        roundIntoPoint(mPositionInWindow, mTmpFloatArr);
     }
 
     public String toString() {
diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
index 8943db6..0038579 100644
--- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
+++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
@@ -23,6 +23,7 @@
 import android.os.BatteryUsageStatsQuery;
 import android.os.SystemClock;
 import android.os.UidBatteryConsumer;
+import android.util.Log;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -36,6 +37,7 @@
  * usage data attributed to subsystems and UIDs.
  */
 public class BatteryUsageStatsProvider {
+    private static final String TAG = "BatteryUsageStatsProv";
     private final Context mContext;
     private final BatteryStats mStats;
     private final BatteryUsageStatsStore mBatteryUsageStatsStore;
@@ -234,6 +236,11 @@
 
         final BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder(
                 mStats.getCustomEnergyConsumerNames(), includePowerModels);
+        if (mBatteryUsageStatsStore == null) {
+            Log.e(TAG, "BatteryUsageStatsStore is unavailable");
+            return builder.build();
+        }
+
         final long[] timestamps = mBatteryUsageStatsStore.listBatteryUsageStatsTimestamps();
         for (long timestamp : timestamps) {
             if (timestamp > query.getFromTimestamp() && timestamp <= query.getToTimestamp()) {
diff --git a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
index 45b63e0..652622d 100644
--- a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
+++ b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
@@ -304,11 +304,6 @@
         forwardDelete(state, 0);
         state.assertEquals("|");
 
-        // Regional indicator symbol + COMBINING ENCLOSING KEYCAP
-        state.setByString("| U+1F1FA U+20E3");
-        forwardDelete(state, 0);
-        state.assertEquals("|");
-
         // COMBINING ENCLOSING KEYCAP + emoji modifier
         state.setByString("| '1' U+20E3 U+1F3FB");
         forwardDelete(state, 0);
@@ -408,11 +403,6 @@
         // forwardDelete(state, 0);
         // state.assertEquals("|");
 
-        // Regional indicator symbol + emoji modifier
-        state.setByString("| U+1F1FA U+1F3FB");
-        forwardDelete(state, 0);
-        state.assertEquals("|");
-
         // Emoji modifier + regional indicator symbol
         state.setByString("| U+1F466 U+1F3FB U+1F1FA");
         forwardDelete(state, 0);
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index d757a8c..4ae0fc4 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -1331,6 +1331,9 @@
     <family lang="und-Zsye">
         <font weight="400" style="normal">NotoColorEmoji.ttf</font>
     </family>
+    <family lang="und-Zsye">
+        <font weight="400" style="normal">NotoColorEmojiFlags.ttf</font>
+    </family>
     <family lang="und-Zsym">
         <font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted2.ttf</font>
     </family>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
index 7e4010d..362b40f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
@@ -408,7 +408,7 @@
     }
 
     boolean isHidden() {
-        return mSurfaceHidden;
+        return getVisibility() != View.VISIBLE || mSurfaceHidden;
     }
 
     /** Starts dragging the divider bar. */
diff --git a/libs/hwui/renderthread/TimeLord.cpp b/libs/hwui/renderthread/TimeLord.cpp
index 406066c..a43fcdc 100644
--- a/libs/hwui/renderthread/TimeLord.cpp
+++ b/libs/hwui/renderthread/TimeLord.cpp
@@ -15,22 +15,28 @@
  */
 #include "TimeLord.h"
 #include <limits>
+#include "FrameInfo.h"
 
 namespace android {
 namespace uirenderer {
 namespace renderthread {
 
-TimeLord::TimeLord() : mFrameIntervalNanos(milliseconds_to_nanoseconds(16)),
-                       mFrameTimeNanos(0),
-                       mFrameIntendedTimeNanos(0),
-                       mFrameVsyncId(-1),
-                       mFrameDeadline(std::numeric_limits<int64_t>::max()){}
+TimeLord::TimeLord()
+        : mFrameIntervalNanos(milliseconds_to_nanoseconds(16))
+        , mFrameTimeNanos(0)
+        , mFrameIntendedTimeNanos(0)
+        , mFrameVsyncId(UiFrameInfoBuilder::INVALID_VSYNC_ID)
+        , mFrameDeadline(std::numeric_limits<int64_t>::max()) {}
 
 bool TimeLord::vsyncReceived(nsecs_t vsync, nsecs_t intendedVsync, int64_t vsyncId,
                              int64_t frameDeadline, nsecs_t frameInterval) {
     if (intendedVsync > mFrameIntendedTimeNanos) {
         mFrameIntendedTimeNanos = intendedVsync;
-        mFrameVsyncId = vsyncId;
+
+        // The intendedVsync might have been advanced to account for scheduling
+        // jitter. Since we don't have a way to advance the vsync id we just
+        // reset it.
+        mFrameVsyncId = (vsyncId > mFrameVsyncId) ? vsyncId : UiFrameInfoBuilder::INVALID_VSYNC_ID;
         mFrameDeadline = frameDeadline;
         if (frameInterval > 0) {
             mFrameIntervalNanos = frameInterval;
diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml
index d0218f6..e53964d 100644
--- a/packages/SystemUI/res-keyguard/values-hi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml
@@ -38,7 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज हो रहा है"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • तेज़ चार्ज हो रहा है"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • धीरे चार्ज हो रहा है"</string>
-    <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्जिंग कुछ समय के लिए रोकी गई"</string>
+    <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • कुछ समय के लिए चार्जिंग रोक दी गई"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"अपना चार्जर कनेक्‍ट करें."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"लॉक खोलने के लिए मेन्यू दबाएं."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लॉक किया हुआ है"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sw/strings.xml b/packages/SystemUI/res-keyguard/values-sw/strings.xml
index fcf8edc..5381d76 100644
--- a/packages/SystemUI/res-keyguard/values-sw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sw/strings.xml
@@ -38,7 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji kwa kasi"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji pole pole"</string>
-    <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hali ya kuchaji kwa muda imedhibitiwa"</string>
+    <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kuchaji kumedhibitiwa kwa muda"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Unganisha chaja yako."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Bonyeza Menyu ili kufungua."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mtandao umefungwa"</string>
diff --git a/packages/SystemUI/res-keyguard/values-vi/strings.xml b/packages/SystemUI/res-keyguard/values-vi/strings.xml
index 6052f40..3c3972c 100644
--- a/packages/SystemUI/res-keyguard/values-vi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-vi/strings.xml
@@ -38,7 +38,7 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc nhanh"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc chậm"</string>
-    <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mức sạc tạm thời bị giới hạn"</string>
+    <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Khả năng sạc tạm thời bị hạn chế"</string>
     <string name="keyguard_low_battery" msgid="1868012396800230904">"Kết nối bộ sạc của bạn."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Nhấn vào Menu để mở khóa."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mạng đã bị khóa"</string>
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
index d85c9a7..c97a30e 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
@@ -77,6 +77,7 @@
 import com.android.systemui.shared.system.WindowManagerWrapper;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.phone.AutoHideController;
 import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
 import com.android.systemui.statusbar.phone.ShadeController;
@@ -227,6 +228,7 @@
             Lazy<StatusBar> statusBarLazy,
             ShadeController shadeController,
             NotificationRemoteInputManager notificationRemoteInputManager,
+            NotificationShadeDepthController notificationShadeDepthController,
             SystemActions systemActions,
             @Main Handler mainHandler,
             UiEventLogger uiEventLogger,
@@ -253,6 +255,7 @@
                 statusBarLazy,
                 shadeController,
                 notificationRemoteInputManager,
+                notificationShadeDepthController,
                 systemActions,
                 mainHandler,
                 uiEventLogger,
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index 711bb56..26f38dd 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -136,6 +136,7 @@
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 import com.android.systemui.statusbar.phone.AutoHideController;
@@ -201,6 +202,7 @@
     private final NavigationBarOverlayController mNavbarOverlayController;
     private final UiEventLogger mUiEventLogger;
     private final UserTracker mUserTracker;
+    private final NotificationShadeDepthController mNotificationShadeDepthController;
 
     private Bundle mSavedState;
     private NavigationBarView mNavigationBarView;
@@ -438,6 +440,25 @@
                 }
             };
 
+    private final NotificationShadeDepthController.DepthListener mDepthListener =
+            new NotificationShadeDepthController.DepthListener() {
+                boolean mHasBlurs;
+
+                @Override
+                public void onWallpaperZoomOutChanged(float zoomOut) {
+                }
+
+                @Override
+                public void onBlurRadiusChanged(int radius) {
+                    boolean hasBlurs = radius != 0;
+                    if (hasBlurs == mHasBlurs) {
+                        return;
+                    }
+                    mHasBlurs = hasBlurs;
+                    mNavigationBarView.setWindowHasBlurs(hasBlurs);
+                }
+            };
+
     public NavigationBar(Context context,
             WindowManager windowManager,
             Lazy<AssistManager> assistManagerLazy,
@@ -457,6 +478,7 @@
             Optional<Recents> recentsOptional, Lazy<StatusBar> statusBarLazy,
             ShadeController shadeController,
             NotificationRemoteInputManager notificationRemoteInputManager,
+            NotificationShadeDepthController notificationShadeDepthController,
             SystemActions systemActions,
             @Main Handler mainHandler,
             NavigationBarOverlayController navbarOverlayController,
@@ -487,6 +509,7 @@
         mNavbarOverlayController = navbarOverlayController;
         mUiEventLogger = uiEventLogger;
         mUserTracker = userTracker;
+        mNotificationShadeDepthController = notificationShadeDepthController;
 
         mNavBarMode = mNavigationModeController.addListener(this);
         mAccessibilityButtonModeObserver.addListener(this);
@@ -570,6 +593,7 @@
 
         mIsCurrentUserSetup = mDeviceProvisionedController.isCurrentUserSetup();
         mDeviceProvisionedController.addCallback(mUserSetupListener);
+        mNotificationShadeDepthController.addListener(mDepthListener);
 
         setAccessibilityFloatingMenuModeIfNeeded();
 
@@ -586,6 +610,7 @@
         mAccessibilityManagerWrapper.removeCallback(mAccessibilityListener);
         mContentResolver.unregisterContentObserver(mAssistContentObserver);
         mDeviceProvisionedController.removeCallback(mUserSetupListener);
+        mNotificationShadeDepthController.removeListener(mDepthListener);
 
         DeviceConfig.removeOnPropertiesChangedListener(mOnPropertiesChangedListener);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index 5359210..b9e9240 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -61,6 +61,7 @@
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
 import com.android.systemui.statusbar.phone.ShadeController;
 import com.android.systemui.statusbar.phone.StatusBar;
@@ -115,6 +116,7 @@
     private final DisplayManager mDisplayManager;
     private final NavigationBarOverlayController mNavBarOverlayController;
     private final TaskbarDelegate mTaskbarDelegate;
+    private final NotificationShadeDepthController mNotificationShadeDepthController;
     private int mNavMode;
     private boolean mIsTablet;
     private final UserTracker mUserTracker;
@@ -149,6 +151,7 @@
             Lazy<StatusBar> statusBarLazy,
             ShadeController shadeController,
             NotificationRemoteInputManager notificationRemoteInputManager,
+            NotificationShadeDepthController notificationShadeDepthController,
             SystemActions systemActions,
             @Main Handler mainHandler,
             UiEventLogger uiEventLogger,
@@ -175,6 +178,7 @@
         mStatusBarLazy = statusBarLazy;
         mShadeController = shadeController;
         mNotificationRemoteInputManager = notificationRemoteInputManager;
+        mNotificationShadeDepthController = notificationShadeDepthController;
         mSystemActions = systemActions;
         mUiEventLogger = uiEventLogger;
         mHandler = mainHandler;
@@ -362,6 +366,7 @@
                 mStatusBarLazy,
                 mShadeController,
                 mNotificationRemoteInputManager,
+                mNotificationShadeDepthController,
                 mSystemActions,
                 mHandler,
                 mNavBarOverlayController,
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index 7af4853..4816f1c 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -413,6 +413,13 @@
         return super.onTouchEvent(event);
     }
 
+    /**
+     * If we're blurring the shade window.
+     */
+    public void setWindowHasBlurs(boolean hasBlurs) {
+        mRegionSamplingHelper.setWindowHasBlurs(hasBlurs);
+    }
+
     void onTransientStateChanged(boolean isTransient) {
         mEdgeBackGestureHandler.onNavBarTransientStateChanged(isTransient);
 
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/RegionSamplingHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/RegionSamplingHelper.java
index 70117eb..560d89a 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/RegionSamplingHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/RegionSamplingHelper.java
@@ -65,6 +65,7 @@
     private final float mLuminanceChangeThreshold;
     private boolean mFirstSamplingAfterStart;
     private boolean mWindowVisible;
+    private boolean mWindowHasBlurs;
     private SurfaceControl mRegisteredStopLayer = null;
     private ViewTreeObserver.OnDrawListener mUpdateOnDraw = new ViewTreeObserver.OnDrawListener() {
         @Override
@@ -153,6 +154,7 @@
         boolean isSamplingEnabled = mSamplingEnabled
                 && !mSamplingRequestBounds.isEmpty()
                 && mWindowVisible
+                && !mWindowHasBlurs
                 && (mSampledView.isAttachedToWindow() || mFirstSamplingAfterStart);
         if (isSamplingEnabled) {
             ViewRootImpl viewRootImpl = mSampledView.getViewRootImpl();
@@ -225,6 +227,14 @@
         updateSamplingListener();
     }
 
+    /**
+     * If we're blurring the shade window.
+     */
+    public void setWindowHasBlurs(boolean hasBlurs) {
+        mWindowHasBlurs = hasBlurs;
+        updateSamplingListener();
+    }
+
     public void dump(PrintWriter pw) {
         pw.println("RegionSamplingHelper:");
         pw.println("  sampleView isAttached: " + mSampledView.isAttachedToWindow());
@@ -238,6 +248,7 @@
         pw.println("  mLastMedianLuma: " + mLastMedianLuma);
         pw.println("  mCurrentMedianLuma: " + mCurrentMedianLuma);
         pw.println("  mWindowVisible: " + mWindowVisible);
+        pw.println("  mWindowHasBlurs: " + mWindowHasBlurs);
         pw.println("  mWaitingOnDraw: " + mWaitingOnDraw);
         pw.println("  mRegisteredStopLayer: " + mRegisteredStopLayer);
         pw.println("  mIsDestroyed: " + mIsDestroyed);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
index 1457012..a2048e2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
@@ -210,6 +210,7 @@
         }
         listeners.forEach {
             it.onWallpaperZoomOutChanged(zoomOut)
+            it.onBlurRadiusChanged(blur)
         }
         notificationShadeWindowController.setBackgroundBlurRadius(blur)
     }
@@ -513,5 +514,8 @@
          * Current wallpaper zoom out, where 0 is the closest, and 1 the farthest
          */
         fun onWallpaperZoomOutChanged(zoomOut: Float)
+
+        @JvmDefault
+        fun onBlurRadiusChanged(blurRadius: Int) {}
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/SensorModule.java b/packages/SystemUI/src/com/android/systemui/util/sensors/SensorModule.java
index 7f37562..11e7df8 100644
--- a/packages/SystemUI/src/com/android/systemui/util/sensors/SensorModule.java
+++ b/packages/SystemUI/src/com/android/systemui/util/sensors/SensorModule.java
@@ -36,12 +36,13 @@
         try {
             return thresholdSensorBuilder
                     .setSensorDelay(SensorManager.SENSOR_DELAY_NORMAL)
-                    .setSensorResourceId(R.string.proximity_sensor_type)
+                    .setSensorResourceId(R.string.proximity_sensor_type, true)
                     .setThresholdResourceId(R.dimen.proximity_sensor_threshold)
                     .setThresholdLatchResourceId(R.dimen.proximity_sensor_threshold_latch)
                     .build();
         } catch (IllegalStateException e) {
-            Sensor defaultSensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
+            Sensor defaultSensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY,
+                    true);
             return thresholdSensorBuilder
                     .setSensor(defaultSensor)
                     .setThresholdValue(defaultSensor != null ? defaultSensor.getMaximumRange() : 0)
@@ -55,7 +56,7 @@
             ThresholdSensorImpl.Builder thresholdSensorBuilder) {
         try {
             return thresholdSensorBuilder
-                    .setSensorResourceId(R.string.proximity_sensor_secondary_type)
+                    .setSensorResourceId(R.string.proximity_sensor_secondary_type, true)
                     .setThresholdResourceId(R.dimen.proximity_sensor_secondary_threshold)
                     .setThresholdLatchResourceId(R.dimen.proximity_sensor_secondary_threshold_latch)
                     .build();
diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ThresholdSensorImpl.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ThresholdSensorImpl.java
index 31c3072..d10cf9b 100644
--- a/packages/SystemUI/src/com/android/systemui/util/sensors/ThresholdSensorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ThresholdSensorImpl.java
@@ -230,14 +230,16 @@
             mExecution = execution;
         }
 
-
         Builder setSensorDelay(int sensorDelay) {
             mSensorDelay = sensorDelay;
             return this;
         }
-
-        Builder setSensorResourceId(int sensorResourceId) {
-            setSensorType(mResources.getString(sensorResourceId));
+        /**
+         * If requiresWakeUp is false, the first sensor with sensorType (regardless of whether the
+         * sensor is a wakeup sensor or not) will be set.
+         */
+        Builder setSensorResourceId(int sensorResourceId, boolean requireWakeUp) {
+            setSensorType(mResources.getString(sensorResourceId), requireWakeUp);
             return this;
         }
 
@@ -259,8 +261,12 @@
             return this;
         }
 
-        Builder setSensorType(String sensorType) {
-            Sensor sensor = findSensorByType(sensorType);
+        /**
+         * If requiresWakeUp is false, the first sensor with sensorType (regardless of whether the
+         * sensor is a wakeup sensor or not) will be set.
+         */
+        Builder setSensorType(String sensorType, boolean requireWakeUp) {
+            Sensor sensor = findSensorByType(sensorType, requireWakeUp);
             if (sensor != null) {
                 setSensor(sensor);
             }
@@ -310,7 +316,8 @@
                     mThresholdValue, mThresholdLatchValue, mSensorDelay);
         }
 
-        private Sensor findSensorByType(String sensorType) {
+        @VisibleForTesting
+        Sensor findSensorByType(String sensorType, boolean requireWakeUp) {
             if (sensorType.isEmpty()) {
                 return null;
             }
@@ -320,7 +327,9 @@
             for (Sensor s : sensorList) {
                 if (sensorType.equals(s.getStringType())) {
                     sensor = s;
-                    break;
+                    if (!requireWakeUp || sensor.isWakeUpSensor()) {
+                        break;
+                    }
                 }
             }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
index 4980f74..d2527c6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
@@ -55,6 +55,7 @@
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.phone.ShadeController;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
@@ -105,6 +106,7 @@
                         () -> mock(StatusBar.class),
                         mock(ShadeController.class),
                         mock(NotificationRemoteInputManager.class),
+                        mock(NotificationShadeDepthController.class),
                         mock(SystemActions.class),
                         Dependency.get(Dependency.MAIN_HANDLER),
                         mock(UiEventLogger.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
index b1afeec..a570675 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
@@ -79,6 +79,7 @@
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.phone.ShadeController;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
@@ -274,6 +275,7 @@
                 () -> mock(StatusBar.class),
                 mock(ShadeController.class),
                 mock(NotificationRemoteInputManager.class),
+                mock(NotificationShadeDepthController.class),
                 mock(SystemActions.class),
                 mHandler,
                 mock(NavigationBarOverlayController.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeSensorManager.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeSensorManager.java
index 27b225e..6e73827 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeSensorManager.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeSensorManager.java
@@ -60,7 +60,7 @@
 
     public FakeSensorManager(Context context) throws Exception {
         Sensor proxSensor = context.getSystemService(SensorManager.class)
-                .getDefaultSensor(Sensor.TYPE_PROXIMITY);
+                .getDefaultSensor(Sensor.TYPE_PROXIMITY, true);
         if (proxSensor == null) {
             // No prox? Let's create a fake one!
             proxSensor =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ThresholdSensorImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ThresholdSensorImplTest.java
index 1276567..125063a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ThresholdSensorImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ThresholdSensorImplTest.java
@@ -16,10 +16,15 @@
 
 package com.android.systemui.util.sensors;
 
+import static android.hardware.Sensor.TYPE_ALL;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
+import android.hardware.Sensor;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 
@@ -33,6 +38,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.List;
+
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 public class ThresholdSensorImplTest extends SysuiTestCase {
@@ -60,6 +67,79 @@
     }
 
     @Test
+    public void testRegistersWakeUpProxSensor_givenWakeUpExistsAfterNonWakeup() {
+        // GIVEN sensor manager with two prox sensors (one non-wakeup, one wakeup)
+        final String sensorTypeProx = "prox";
+        AsyncSensorManager mockSensorManager = mock(AsyncSensorManager.class);
+
+        Sensor mockNonWakeupProx = mock(Sensor.class);
+        when(mockNonWakeupProx.isWakeUpSensor()).thenReturn(false);
+        when(mockNonWakeupProx.getStringType()).thenReturn(sensorTypeProx);
+
+        Sensor mockWakeupProx = mock(Sensor.class);
+        when(mockWakeupProx.isWakeUpSensor()).thenReturn(true);
+        when(mockWakeupProx.getStringType()).thenReturn(sensorTypeProx);
+
+        when(mockSensorManager.getSensorList(TYPE_ALL)).thenReturn(
+                List.of(mockNonWakeupProx, mockWakeupProx));
+
+        // WHEN we build a threshold sensor by type
+        ThresholdSensorImpl.Builder thresholdSensorBuilder = new ThresholdSensorImpl.Builder(
+                null, mockSensorManager, new FakeExecution());
+        Sensor proxSensor = thresholdSensorBuilder.findSensorByType(sensorTypeProx, true);
+
+        // THEN the prox sensor used is the wakeup sensor
+        assertEquals(mockWakeupProx, proxSensor);
+    }
+
+    @Test
+    public void testRegistersWakeUpProxSensor_givenNonWakeUpExistsAfterWakeup() {
+        // GIVEN sensor manager with two prox sensors (one wakeup, one non-wakeup)
+        final String sensorTypeProx = "prox";
+        AsyncSensorManager mockSensorManager = mock(AsyncSensorManager.class);
+
+        Sensor mockNonWakeupProx = mock(Sensor.class);
+        when(mockNonWakeupProx.isWakeUpSensor()).thenReturn(false);
+        when(mockNonWakeupProx.getStringType()).thenReturn(sensorTypeProx);
+
+        Sensor mockWakeupProx = mock(Sensor.class);
+        when(mockWakeupProx.isWakeUpSensor()).thenReturn(true);
+        when(mockWakeupProx.getStringType()).thenReturn(sensorTypeProx);
+
+        when(mockSensorManager.getSensorList(TYPE_ALL)).thenReturn(
+                List.of(mockWakeupProx, mockNonWakeupProx));
+
+        // WHEN we build a threshold sensor by type
+        ThresholdSensorImpl.Builder thresholdSensorBuilder = new ThresholdSensorImpl.Builder(
+                null, mockSensorManager, new FakeExecution());
+        Sensor proxSensor = thresholdSensorBuilder.findSensorByType(sensorTypeProx, true);
+
+        // THEN the prox sensor used is the wakeup sensor
+        assertEquals(mockWakeupProx, proxSensor);
+    }
+
+    @Test
+    public void testRegistersNonWakeUpProxSensor_givenNonWakeUpOnly() {
+        // GIVEN sensor manager with one non-wakeup prox sensor
+        final String sensorTypeProx = "prox";
+        AsyncSensorManager mockSensorManager = mock(AsyncSensorManager.class);
+
+        Sensor mockNonWakeupProx = mock(Sensor.class);
+        when(mockNonWakeupProx.isWakeUpSensor()).thenReturn(false);
+        when(mockNonWakeupProx.getStringType()).thenReturn(sensorTypeProx);
+
+        when(mockSensorManager.getSensorList(TYPE_ALL)).thenReturn(List.of(mockNonWakeupProx));
+
+        // WHEN we build a threshold sensor by type
+        ThresholdSensorImpl.Builder thresholdSensorBuilder = new ThresholdSensorImpl.Builder(
+                null, mockSensorManager, new FakeExecution());
+        Sensor proxSensor = thresholdSensorBuilder.findSensorByType(sensorTypeProx, true);
+
+        // THEN the prox sensor used is the one available (non-wakeup)
+        assertEquals(mockNonWakeupProx, proxSensor);
+    }
+
+    @Test
     public void testSingleListener() {
         TestableListener listener = new TestableListener();
 
diff --git a/services/core/java/com/android/server/SensorPrivacyService.java b/services/core/java/com/android/server/SensorPrivacyService.java
index 71609d2..e753226 100644
--- a/services/core/java/com/android/server/SensorPrivacyService.java
+++ b/services/core/java/com/android/server/SensorPrivacyService.java
@@ -17,6 +17,8 @@
 package com.android.server;
 
 import static android.Manifest.permission.MANAGE_SENSOR_PRIVACY;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
 import static android.app.ActivityManager.RunningServiceInfo;
 import static android.app.ActivityManager.RunningTaskInfo;
 import static android.app.ActivityManager.getCurrentUser;
@@ -41,6 +43,7 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
 import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
 import android.app.AppOpsManager;
@@ -83,6 +86,7 @@
 import android.telephony.TelephonyManager;
 import android.telephony.emergency.EmergencyNumber;
 import android.text.Html;
+import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.AtomicFile;
@@ -156,6 +160,7 @@
     private final SensorPrivacyServiceImpl mSensorPrivacyServiceImpl;
     private final UserManagerInternal mUserManagerInternal;
     private final ActivityManager mActivityManager;
+    private final ActivityManagerInternal mActivityManagerInternal;
     private final ActivityTaskManager mActivityTaskManager;
     private final AppOpsManager mAppOpsManager;
     private final TelephonyManager mTelephonyManager;
@@ -173,6 +178,7 @@
         mAppOpsManager = context.getSystemService(AppOpsManager.class);
         mUserManagerInternal = getLocalService(UserManagerInternal.class);
         mActivityManager = context.getSystemService(ActivityManager.class);
+        mActivityManagerInternal = getLocalService(ActivityManagerInternal.class);
         mActivityTaskManager = context.getSystemService(ActivityTaskManager.class);
         mTelephonyManager = context.getSystemService(TelephonyManager.class);
 
@@ -421,11 +427,33 @@
                 }
             }
 
-            VoiceInteractionManagerInternal voiceInteractionManagerInternal =
-                    LocalServices.getService(VoiceInteractionManagerInternal.class);
+            String inputMethodComponent = Settings.Secure.getString(mContext.getContentResolver(),
+                    Settings.Secure.DEFAULT_INPUT_METHOD);
+            String inputMethodPackageName = null;
+            if (inputMethodComponent != null) {
+                inputMethodPackageName = ComponentName.unflattenFromString(
+                        inputMethodComponent).getPackageName();
+            }
+            int capability = mActivityManagerInternal.getUidCapability(uid);
 
-            if (sensor == MICROPHONE && voiceInteractionManagerInternal != null
-                    && voiceInteractionManagerInternal.hasActiveSession(packageName)) {
+            if (sensor == MICROPHONE) {
+                VoiceInteractionManagerInternal voiceInteractionManagerInternal =
+                        LocalServices.getService(VoiceInteractionManagerInternal.class);
+                if (voiceInteractionManagerInternal != null
+                        && voiceInteractionManagerInternal.hasActiveSession(packageName)) {
+                    enqueueSensorUseReminderDialogAsync(-1, user, packageName, sensor);
+                    return;
+                }
+
+                if (TextUtils.equals(packageName, inputMethodPackageName)
+                        && (capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) {
+                    enqueueSensorUseReminderDialogAsync(-1, user, packageName, sensor);
+                    return;
+                }
+            }
+
+            if (sensor == CAMERA && TextUtils.equals(packageName, inputMethodPackageName)
+                    && (capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
                 enqueueSensorUseReminderDialogAsync(-1, user, packageName, sensor);
                 return;
             }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0c97724..a04edc7 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -16333,6 +16333,17 @@
                 return mConstants.mPushMessagingOverQuotaBehavior;
             }
         }
+
+        @Override
+        public int getUidCapability(int uid) {
+            synchronized (ActivityManagerService.this) {
+                UidRecord uidRecord = mProcessList.getUidRecordLOSP(uid);
+                if (uidRecord == null) {
+                    throw new IllegalArgumentException("uid record for " + uid + " not found");
+                }
+                return uidRecord.getCurCapability();
+            }
+        }
     }
 
     long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 08f6f1e..7d9d789 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -126,7 +126,7 @@
         Watchdog.Monitor {
     static final String TAG = "BatteryStatsService";
     static final boolean DBG = false;
-    private static final boolean BATTERY_USAGE_STORE_ENABLED = true;
+    private static final boolean BATTERY_USAGE_STORE_ENABLED = false;
 
     private static IBatteryStats sService;
 
@@ -784,6 +784,10 @@
                     bus = getBatteryUsageStats(List.of(powerProfileQuery)).get(0);
                     break;
                 case FrameworkStatsLog.BATTERY_USAGE_STATS_BEFORE_RESET:
+                    if (!BATTERY_USAGE_STORE_ENABLED) {
+                        return StatsManager.PULL_SKIP;
+                    }
+
                     final long sessionStart = mBatteryUsageStatsStore
                             .getLastBatteryUsageStatsBeforeResetAtomPullTimestamp();
                     final long sessionEnd = mStats.getStartClockTime();
diff --git a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
index f439777..7513512 100644
--- a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
+++ b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
@@ -133,8 +133,12 @@
 
 static int waitForDataOrSignal(int fd, int event_fd) {
     struct pollfd pfds[2] = {{fd, POLLIN, 0}, {event_fd, POLLIN, 0}};
-    // Wait indefinitely until either data is ready or stop signal is received
+    // Wait until either data is ready or stop signal is received
     int res = poll(pfds, 2, PollTimeoutMs);
+    if (res == -1 && errno == EINTR) {
+        // Treat it the same as timeout and allow the caller to retry.
+        return 0;
+    }
     if (res <= 0) {
         return res;
     }
diff --git a/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java b/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java
index 16a2d8d..6606fb0 100644
--- a/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java
+++ b/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java
@@ -182,15 +182,28 @@
                     + "translation state for token=" + token + " taskId=" + taskId);
             return;
         }
+        int translationActivityUid = -1;
         try {
+            IBinder activityToken = taskTopActivityTokens.getActivityToken();
             taskTopActivityTokens.getApplicationThread().updateUiTranslationState(
-                    taskTopActivityTokens.getActivityToken(), state, sourceSpec, targetSpec,
+                    activityToken, state, sourceSpec, targetSpec,
                     viewIds, uiTranslationSpec);
             mLastActivityTokens = new WeakReference<>(taskTopActivityTokens);
+            ComponentName componentName =
+                    mActivityTaskManagerInternal.getActivityName(activityToken);
+            try {
+                if (componentName != null) {
+                    translationActivityUid =
+                            getContext().getPackageManager().getApplicationInfoAsUser(
+                                    componentName.getPackageName(), 0, getUserId()).uid;
+                }
+            } catch (PackageManager.NameNotFoundException e) {
+                Slog.d(TAG, "Cannot find package for" +  componentName);
+            }
         } catch (RemoteException e) {
             Slog.w(TAG, "Update UiTranslationState fail: " + e);
         }
-        invokeCallbacks(state, sourceSpec, targetSpec);
+        invokeCallbacks(state, sourceSpec, targetSpec, translationActivityUid);
     }
 
     @GuardedBy("mLock")
@@ -216,7 +229,8 @@
     }
 
     private void invokeCallbacks(
-            int state, TranslationSpec sourceSpec, TranslationSpec targetSpec) {
+            int state, TranslationSpec sourceSpec, TranslationSpec targetSpec,
+            int translationActivityUid) {
         Bundle res = new Bundle();
         res.putInt(EXTRA_STATE, state);
         // TODO(177500482): Store the locale pair so it can be sent for RESUME events.
@@ -229,6 +243,14 @@
                 LocalServices.getService(InputMethodManagerInternal.class)
                         .getEnabledInputMethodListAsUser(mUserId);
         mCallbacks.broadcast((callback, uid) -> {
+            // callback to the application that is translated if registered.
+            if ((int) uid == translationActivityUid) {
+                try {
+                    callback.sendResult(res);
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "Failed to invoke UiTranslationStateCallback: " + e);
+                }
+            }
             // Code here is non-optimal since it's temporary..
             boolean isIme = false;
             for (InputMethodInfo inputMethod : enabledInputMethods) {
diff --git a/telephony/java/android/telephony/ims/RcsContactUceCapability.java b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
index 530003d..9112118 100644
--- a/telephony/java/android/telephony/ims/RcsContactUceCapability.java
+++ b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
@@ -331,7 +331,7 @@
             return null;
         }
         for (RcsContactPresenceTuple tuple : mPresenceTuples) {
-            if (tuple.getServiceId().equals(serviceId)) {
+            if (tuple.getServiceId() != null && tuple.getServiceId().equals(serviceId)) {
                 return tuple;
             }
         }
diff --git a/tools/fonts/fontchain_linter.py b/tools/fonts/fontchain_linter.py
index 1266cce..e181c62 100755
--- a/tools/fonts/fontchain_linter.py
+++ b/tools/fonts/fontchain_linter.py
@@ -117,13 +117,14 @@
     reverse_cmap = {glyph: code for code, glyph in emoji_map.items() if not contains_pua(code) }
 
     # Add variation sequences
-    vs_dict = get_variation_sequences_cmap(font).uvsDict
-    for vs in vs_dict:
-        for base, glyph in vs_dict[vs]:
-            if glyph is None:
-                emoji_map[(base, vs)] = emoji_map[base]
-            else:
-                emoji_map[(base, vs)] = glyph
+    vs_cmap = get_variation_sequences_cmap(font)
+    if vs_cmap:
+        for vs in vs_cmap.uvsDict:
+            for base, glyph in vs_cmap.uvsDict[vs]:
+                if glyph is None:
+                    emoji_map[(base, vs)] = emoji_map[base]
+                else:
+                    emoji_map[(base, vs)] = glyph
 
     # Add GSUB rules
     ttfont = open_font(font)
@@ -310,17 +311,12 @@
 
 
 def check_emoji_coverage(all_emoji, equivalent_emoji):
-    emoji_font = get_emoji_font()
-    check_emoji_font_coverage(emoji_font, all_emoji, equivalent_emoji)
+    emoji_fonts = get_emoji_fonts()
+    check_emoji_font_coverage(emoji_fonts, all_emoji, equivalent_emoji)
 
 
-def get_emoji_font():
-    emoji_fonts = [
-        record.font for record in _all_fonts
-        if 'Zsye' in record.scripts]
-    assert len(emoji_fonts) == 1, 'There are %d emoji fonts.' % len(emoji_fonts)
-    return emoji_fonts[0]
-
+def get_emoji_fonts():
+    return [ record.font for record in _all_fonts if 'Zsye' in record.scripts ]
 
 def is_pua(x):
     return 0xE000 <= x <= 0xF8FF or 0xF0000 <= x <= 0xFFFFD or 0x100000 <= x <= 0x10FFFD
@@ -331,58 +327,71 @@
   else:
     return is_pua(sequence)
 
+def get_psname(ttf):
+    return str(next(x for x in ttf['name'].names
+        if x.platformID == 3 and x.platEncID == 1 and x.nameID == 6))
 
 def check_emoji_compat():
-    ttf = open_font(get_emoji_font())
-    meta = ttf['meta']
-    assert meta, 'Compat font must have meta table'
-    assert 'Emji' in meta.data, 'meta table should have \'Emji\' data.'
+    for emoji_font in get_emoji_fonts():
+        ttf = open_font(emoji_font)
+        psname = get_psname(ttf)
 
-def check_emoji_font_coverage(emoji_font, all_emoji, equivalent_emoji):
-    coverage = get_emoji_map(emoji_font)
+        # If the font file is NotoColorEmoji, it must be Compat font.
+        if psname == 'NotoColorEmoji':
+            meta = ttf['meta']
+            assert meta, 'Compat font must have meta table'
+            assert 'Emji' in meta.data, 'meta table should have \'Emji\' data.'
+
+def check_emoji_font_coverage(emoji_fonts, all_emoji, equivalent_emoji):
+    coverages = []
+    for emoji_font in emoji_fonts:
+        coverages.append(get_emoji_map(emoji_font))
 
     errors = []
 
     for sequence in all_emoji:
-        if not sequence in coverage:
-          errors.append('%s is not supported in the emoji font.' % printable(sequence))
+        if all([sequence not in coverage for coverage in coverages]):
+            errors.append('%s is not supported in the emoji font.' % printable(sequence))
 
-    for sequence in coverage:
-        if sequence in {0x0000, 0x000D, 0x0020}:
-            # The font needs to support a few extra characters, which is OK
-            continue
+    for coverage in coverages:
+        for sequence in coverage:
+            if sequence in {0x0000, 0x000D, 0x0020}:
+                # The font needs to support a few extra characters, which is OK
+                continue
 
-        if contains_pua(sequence):
-            # The font needs to have some PUA for EmojiCompat library.
-            continue
+            if contains_pua(sequence):
+                # The font needs to have some PUA for EmojiCompat library.
+                continue
 
-        if sequence not in all_emoji:
-          errors.append('%s support unexpected in the emoji font.' % printable(sequence))
+            if sequence not in all_emoji:
+                errors.append('%s support unexpected in the emoji font.' % printable(sequence))
 
     for first, second in equivalent_emoji.items():
-        if first not in coverage or second not in coverage:
-            continue  # sequence will be reported missing
-        if coverage[first] != coverage[second]:
-            errors.append('%s and %s should map to the same glyph.' % (
-                printable(first),
-                printable(second)))
+        for coverage in coverages:
+            if first not in coverage or second not in coverage:
+                continue  # sequence will be reported missing
+            if coverage[first] != coverage[second]:
+                errors.append('%s and %s should map to the same glyph.' % (
+                    printable(first),
+                    printable(second)))
 
-    for glyph in set(coverage.values()):
-        maps_to_glyph = [
-            seq for seq in coverage if coverage[seq] == glyph and not contains_pua(seq) ]
-        if len(maps_to_glyph) > 1:
-            # There are more than one sequences mapping to the same glyph. We
-            # need to make sure they were expected to be equivalent.
-            equivalent_seqs = set()
-            for seq in maps_to_glyph:
-                equivalent_seq = seq
-                while equivalent_seq in equivalent_emoji:
-                    equivalent_seq = equivalent_emoji[equivalent_seq]
-                equivalent_seqs.add(equivalent_seq)
-            if len(equivalent_seqs) != 1:
-                errors.append('The sequences %s should not result in the same glyph %s' % (
-                    printable(equivalent_seqs),
-                    glyph))
+    for coverage in coverages:
+        for glyph in set(coverage.values()):
+            maps_to_glyph = [
+                seq for seq in coverage if coverage[seq] == glyph and not contains_pua(seq) ]
+            if len(maps_to_glyph) > 1:
+                # There are more than one sequences mapping to the same glyph. We
+                # need to make sure they were expected to be equivalent.
+                equivalent_seqs = set()
+                for seq in maps_to_glyph:
+                    equivalent_seq = seq
+                    while equivalent_seq in equivalent_emoji:
+                        equivalent_seq = equivalent_emoji[equivalent_seq]
+                    equivalent_seqs.add(equivalent_seq)
+                if len(equivalent_seqs) != 1:
+                    errors.append('The sequences %s should not result in the same glyph %s' % (
+                        printable(equivalent_seqs),
+                        glyph))
 
     assert not errors, '%d emoji font errors:\n%s\n%d emoji font coverage errors' % (len(errors), '\n'.join(errors), len(errors))