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))