Merge "Exposing setRecentsVisibility method and associated callbacks to the Recents components" into pi-dev
diff --git a/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java b/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
index 28d4096..ba072da 100644
--- a/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
+++ b/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
@@ -69,7 +69,6 @@
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
Binder b = new Binder();
mBinderCallsStats = new BinderCallsStats(false);
- assertNull(mBinderCallsStats.callStarted(b, 0));
while (state.keepRunning()) {
BinderCallsStats.CallSession s = mBinderCallsStats.callStarted(b, 0);
mBinderCallsStats.callEnded(s);
diff --git a/core/java/android/text/AndroidBidi.java b/core/java/android/text/AndroidBidi.java
index 179d545..72383cf 100644
--- a/core/java/android/text/AndroidBidi.java
+++ b/core/java/android/text/AndroidBidi.java
@@ -32,8 +32,12 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public class AndroidBidi {
- private static class EmojiBidiOverride extends BidiClassifier {
- EmojiBidiOverride() {
+ /**
+ * Overrides ICU {@link BidiClassifier} in order to correctly handle character directions for
+ * newest emoji that ICU is not aware of.
+ */
+ public static class EmojiBidiOverride extends BidiClassifier {
+ public EmojiBidiOverride() {
super(null /* No persisting object needed */);
}
diff --git a/core/java/android/text/BidiFormatter.java b/core/java/android/text/BidiFormatter.java
index f65f397..77f17a7 100644
--- a/core/java/android/text/BidiFormatter.java
+++ b/core/java/android/text/BidiFormatter.java
@@ -21,6 +21,8 @@
import android.annotation.Nullable;
import android.view.View;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.Locale;
/**
@@ -570,8 +572,10 @@
/**
* An object that estimates the directionality of a given string by various methods.
*
+ * @hide
*/
- private static class DirectionalityEstimator {
+ @VisibleForTesting
+ public static class DirectionalityEstimator {
// Internal static variables and constants.
@@ -598,7 +602,11 @@
}
}
- private static byte getDirectionality(int codePoint) {
+ /**
+ * Return Character directionality. Same as {@link Character#getDirectionality(int)} except
+ * it overrides values for newest emoji that are not covered by ICU.
+ */
+ public static byte getDirectionality(int codePoint) {
if (Emoji.isNewEmoji(codePoint)) {
// TODO: Fix or remove once emoji-data.text 5.0 is in ICU or update to 6.0.
return Character.DIRECTIONALITY_OTHER_NEUTRALS;
diff --git a/core/java/android/text/Emoji.java b/core/java/android/text/Emoji.java
index d33aad9..876c64e 100644
--- a/core/java/android/text/Emoji.java
+++ b/core/java/android/text/Emoji.java
@@ -46,44 +46,49 @@
return UCharacter.hasBinaryProperty(codePoint, UProperty.EMOJI_MODIFIER);
}
- // Returns true if the given code point is emoji modifier base.
- public static boolean isEmojiModifierBase(int codePoint) {
+ //
+
+ /**
+ * Returns true if the given code point is emoji modifier base.
+ * @param c codepoint to check
+ * @return true if is emoji modifier base
+ */
+ public static boolean isEmojiModifierBase(int c) {
// These two characters were removed from Emoji_Modifier_Base in Emoji 4.0, but we need to
// keep them as emoji modifier bases since there are fonts and user-generated text out there
// that treats these as potential emoji bases.
- if (codePoint == 0x1F91D || codePoint == 0x1F93C) {
+ if (c == 0x1F91D || c == 0x1F93C) {
return true;
}
- // Emoji Modifier Base characters new in Unicode emoji 5.0.
- // From http://www.unicode.org/Public/emoji/5.0/emoji-data.txt
- // TODO: Remove once emoji-data.text 5.0 is in ICU or update to 6.0.
- if (codePoint == 0x1F91F
- || (0x1F931 <= codePoint && codePoint <= 0x1F932)
- || (0x1F9D1 <= codePoint && codePoint <= 0x1F9DD)) {
+ // Emoji Modifier Base characters new in Unicode emoji 11
+ // From https://www.unicode.org/Public/emoji/11.0/emoji-data.txt
+ // TODO: Remove once emoji-data.text 11 is in ICU or update to 11.
+ if ((0x1F9B5 <= c && c <= 0x1F9B6) || (0x1F9B8 <= c && c <= 0x1F9B9)) {
return true;
}
- return UCharacter.hasBinaryProperty(codePoint, UProperty.EMOJI_MODIFIER_BASE);
+ return UCharacter.hasBinaryProperty(c, UProperty.EMOJI_MODIFIER_BASE);
}
/**
* Returns true if the character is a new emoji still not supported in our version of ICU.
*/
- public static boolean isNewEmoji(int codePoint) {
- // Emoji characters new in Unicode emoji 5.0.
- // From http://www.unicode.org/Public/emoji/5.0/emoji-data.txt
- // TODO: Remove once emoji-data.text 5.0 is in ICU or update to 6.0.
- if (codePoint < 0x1F6F7 || codePoint > 0x1F9E6) {
+ public static boolean isNewEmoji(int c) {
+ // Emoji characters new in Unicode emoji 11
+ // From https://www.unicode.org/Public/emoji/11.0/emoji-data.txt
+ // TODO: Remove once emoji-data.text 11 is in ICU or update to 11.
+ if (c < 0x1F6F9 || c > 0x1F9FF) {
// Optimization for characters outside the new emoji range.
return false;
}
- return (0x1F6F7 <= codePoint && codePoint <= 0x1F6F8)
- || codePoint == 0x1F91F
- || (0x1F928 <= codePoint && codePoint <= 0x1F92F)
- || (0x1F931 <= codePoint && codePoint <= 0x1F932)
- || codePoint == 0x1F94C
- || (0x1F95F <= codePoint && codePoint <= 0x1F96B)
- || (0x1F992 <= codePoint && codePoint <= 0x1F997)
- || (0x1F9D0 <= codePoint && codePoint <= 0x1F9E6);
+ return c == 0x265F || c == 0x267E || c == 0x1F6F9 || c == 0x1F97A
+ || (0x1F94D <= c && c <= 0x1F94F)
+ || (0x1F96C <= c && c <= 0x1F970)
+ || (0x1F973 <= c && c <= 0x1F976)
+ || (0x1F97C <= c && c <= 0x1F97F)
+ || (0x1F998 <= c && c <= 0x1F9A2)
+ || (0x1F9B0 <= c && c <= 0x1F9B9)
+ || (0x1F9C1 <= c && c <= 0x1F9C2)
+ || (0x1F9E7 <= c && c <= 0x1F9FF);
}
/**
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index 2c48506..7eefe59 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -21,6 +21,7 @@
import android.util.ArrayMap;
import android.util.SparseArray;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
@@ -40,23 +41,21 @@
private static final int CALL_SESSIONS_POOL_SIZE = 100;
private static final BinderCallsStats sInstance = new BinderCallsStats();
- private volatile boolean mTrackingEnabled = false;
+ private volatile boolean mDetailedTracking = false;
+ @GuardedBy("mLock")
private final SparseArray<UidEntry> mUidEntries = new SparseArray<>();
private final Queue<CallSession> mCallSessionsPool = new ConcurrentLinkedQueue<>();
+ private final Object mLock = new Object();
private BinderCallsStats() {
}
@VisibleForTesting
- public BinderCallsStats(boolean trackingEnabled) {
- mTrackingEnabled = trackingEnabled;
+ public BinderCallsStats(boolean detailedTracking) {
+ mDetailedTracking = detailedTracking;
}
public CallSession callStarted(Binder binder, int code) {
- if (!mTrackingEnabled) {
- return null;
- }
-
return callStarted(binder.getClass().getName(), code);
}
@@ -73,32 +72,31 @@
}
public void callEnded(CallSession s) {
- if (!mTrackingEnabled) {
- return;
- }
Preconditions.checkNotNull(s);
- final long cpuTimeNow = getThreadTimeMicro();
- final long duration = cpuTimeNow - s.mStarted;
+ long duration = mDetailedTracking ? getThreadTimeMicro() - s.mStarted : 1;
s.mCallingUId = Binder.getCallingUid();
- synchronized (mUidEntries) {
+ synchronized (mLock) {
UidEntry uidEntry = mUidEntries.get(s.mCallingUId);
if (uidEntry == null) {
uidEntry = new UidEntry(s.mCallingUId);
mUidEntries.put(s.mCallingUId, uidEntry);
}
- // Find CallDesc entry and update its total time
- CallStat callStat = uidEntry.mCallStats.get(s.mCallStat);
- // Only create CallStat if it's a new entry, otherwise update existing instance
- if (callStat == null) {
- callStat = new CallStat(s.mCallStat.className, s.mCallStat.msg);
- uidEntry.mCallStats.put(callStat, callStat);
+ if (mDetailedTracking) {
+ // Find CallDesc entry and update its total time
+ CallStat callStat = uidEntry.mCallStats.get(s.mCallStat);
+ // Only create CallStat if it's a new entry, otherwise update existing instance
+ if (callStat == null) {
+ callStat = new CallStat(s.mCallStat.className, s.mCallStat.msg);
+ uidEntry.mCallStats.put(callStat, callStat);
+ }
+ callStat.callCount++;
+ callStat.time += duration;
}
+
uidEntry.time += duration;
uidEntry.callCount++;
- callStat.callCount++;
- callStat.time += duration;
}
if (mCallSessionsPool.size() < CALL_SESSIONS_POOL_SIZE) {
mCallSessionsPool.add(s);
@@ -112,7 +110,7 @@
long totalCallsTime = 0;
int uidEntriesSize = mUidEntries.size();
List<UidEntry> entries = new ArrayList<>();
- synchronized (mUidEntries) {
+ synchronized (mLock) {
for (int i = 0; i < uidEntriesSize; i++) {
UidEntry e = mUidEntries.valueAt(i);
entries.add(e);
@@ -127,20 +125,10 @@
totalCallsCount += e.callCount;
}
}
- pw.println("Binder call stats:");
- pw.println(" Raw data (uid,call_desc,time):");
- entries.sort((o1, o2) -> {
- if (o1.time < o2.time) {
- return 1;
- } else if (o1.time > o2.time) {
- return -1;
- }
- return 0;
- });
- StringBuilder sb = new StringBuilder();
- for (UidEntry uidEntry : entries) {
- List<CallStat> callStats = new ArrayList<>(uidEntry.mCallStats.keySet());
- callStats.sort((o1, o2) -> {
+ if (mDetailedTracking) {
+ pw.println("Binder call stats:");
+ pw.println(" Raw data (uid,call_desc,time):");
+ entries.sort((o1, o2) -> {
if (o1.time < o2.time) {
return 1;
} else if (o1.time > o2.time) {
@@ -148,44 +136,72 @@
}
return 0;
});
- for (CallStat e : callStats) {
- sb.setLength(0);
- sb.append(" ")
- .append(uidEntry.uid).append(",").append(e).append(',').append(e.time);
- pw.println(sb);
+ StringBuilder sb = new StringBuilder();
+ for (UidEntry uidEntry : entries) {
+ List<CallStat> callStats = new ArrayList<>(uidEntry.mCallStats.keySet());
+ callStats.sort((o1, o2) -> {
+ if (o1.time < o2.time) {
+ return 1;
+ } else if (o1.time > o2.time) {
+ return -1;
+ }
+ return 0;
+ });
+ for (CallStat e : callStats) {
+ sb.setLength(0);
+ sb.append(" ")
+ .append(uidEntry.uid).append(",").append(e).append(',').append(e.time);
+ pw.println(sb);
+ }
+ }
+ pw.println();
+ pw.println(" Per UID Summary(UID: time, % of total_time, calls_count):");
+ List<Map.Entry<Integer, Long>> uidTotals = new ArrayList<>(uidTimeMap.entrySet());
+ uidTotals.sort((o1, o2) -> o2.getValue().compareTo(o1.getValue()));
+ for (Map.Entry<Integer, Long> uidTotal : uidTotals) {
+ Long callCount = uidCallCountMap.get(uidTotal.getKey());
+ pw.println(String.format(" %7d: %11d %3.0f%% %8d",
+ uidTotal.getKey(), uidTotal.getValue(),
+ 100d * uidTotal.getValue() / totalCallsTime, callCount));
+ }
+ pw.println();
+ pw.println(String.format(" Summary: total_time=%d, "
+ + "calls_count=%d, avg_call_time=%.0f",
+ totalCallsTime, totalCallsCount,
+ (double)totalCallsTime / totalCallsCount));
+ } else {
+ pw.println(" Per UID Summary(UID: calls_count, % of total calls_count):");
+ List<Map.Entry<Integer, Long>> uidTotals = new ArrayList<>(uidTimeMap.entrySet());
+ uidTotals.sort((o1, o2) -> o2.getValue().compareTo(o1.getValue()));
+ for (Map.Entry<Integer, Long> uidTotal : uidTotals) {
+ Long callCount = uidCallCountMap.get(uidTotal.getKey());
+ pw.println(String.format(" %7d: %8d %3.0f%%",
+ uidTotal.getKey(), callCount, 100d * uidTotal.getValue() / totalCallsTime));
}
}
- pw.println();
- pw.println(" Per UID Summary(UID: time, total_time_percentage, calls_count):");
- List<Map.Entry<Integer, Long>> uidTotals = new ArrayList<>(uidTimeMap.entrySet());
- uidTotals.sort((o1, o2) -> o2.getValue().compareTo(o1.getValue()));
- for (Map.Entry<Integer, Long> uidTotal : uidTotals) {
- Long callCount = uidCallCountMap.get(uidTotal.getKey());
- pw.println(String.format(" %5d: %11d %3.0f%% %8d",
- uidTotal.getKey(), uidTotal.getValue(),
- 100d * uidTotal.getValue() / totalCallsTime, callCount));
- }
- pw.println();
- pw.println(String.format(" Summary: total_time=%d, "
- + "calls_count=%d, avg_call_time=%.0f",
- totalCallsTime, totalCallsCount,
- (double)totalCallsTime / totalCallsCount));
}
- private static long getThreadTimeMicro() {
- return SystemClock.currentThreadTimeMicro();
+ private long getThreadTimeMicro() {
+ // currentThreadTimeMicro is expensive, so we measure cpu time only if detailed tracking is
+ // enabled
+ return mDetailedTracking ? SystemClock.currentThreadTimeMicro() : 0;
}
public static BinderCallsStats getInstance() {
return sInstance;
}
- public void setTrackingEnabled(boolean enabled) {
- mTrackingEnabled = enabled;
+ public void setDetailedTracking(boolean enabled) {
+ if (enabled != mDetailedTracking) {
+ reset();
+ mDetailedTracking = enabled;
+ }
}
- public boolean isTrackingEnabled() {
- return mTrackingEnabled;
+ public void reset() {
+ synchronized (mLock) {
+ mUidEntries.clear();
+ }
}
private static class CallStat {
@@ -210,7 +226,7 @@
CallStat callStat = (CallStat) o;
- return msg == callStat.msg && (className == callStat.className);
+ return msg == callStat.msg && (className.equals(callStat.className));
}
@Override
diff --git a/core/res/res/layout/global_actions_item.xml b/core/res/res/layout/global_actions_item.xml
index e5a9854..6ac0b17 100644
--- a/core/res/res/layout/global_actions_item.xml
+++ b/core/res/res/layout/global_actions_item.xml
@@ -13,6 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+<!-- Used with LegacyGlobalActions. -->
<!-- RelativeLayouts have an issue enforcing minimum heights, so just
work around this for now with LinearLayouts. -->
diff --git a/core/tests/coretests/src/android/text/EmojiTest.java b/core/tests/coretests/src/android/text/EmojiTest.java
new file mode 100644
index 0000000..313f1b6
--- /dev/null
+++ b/core/tests/coretests/src/android/text/EmojiTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.icu.lang.UCharacterDirection;
+import android.icu.text.Bidi;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Emoji and ICU drops does not happen at the same time. Therefore there are almost always cases
+ * where the existing ICU version is not aware of the latest emoji that Android supports.
+ * This test covers Emoji and ICU related functions where other components such as
+ * {@link AndroidBidi}, {@link BidiFormatter} depend on. The tests are collected into the same
+ * class since the changes effect all those classes.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class EmojiTest {
+
+ @Test
+ public void testIsNewEmoji_Emoji5() {
+ // each row in the data is the range of emoji
+ final int[][][] data = new int[][][]{
+ { // EMOJI 5
+ // range of emoji: i.e from 0x1F6F7 to 0x1F6F8 inclusive
+ {0x1F6F7, 0x1F6F8},
+ {0x1F91F, 0x1F91F},
+ {0x1F928, 0x1F92F},
+ {0x1F94C, 0x1F94C},
+ {0x1F95F, 0x1F96B},
+ {0x1F992, 0x1F997},
+ {0x1F9D0, 0x1F9E6},
+ },
+ { // EMOJI 11
+ {0x265F, 0x265F},
+ {0x267E, 0x267E},
+ {0x1F6F9, 0x1F6F9},
+ {0x1F94D, 0x1F94F},
+ {0x1F96C, 0x1F970},
+ {0x1F973, 0x1F976},
+ {0x1F97A, 0x1F97A},
+ {0x1F97C, 0x1F97F},
+ {0x1F998, 0x1F9A2},
+ {0x1F9B0, 0x1F9B9},
+ {0x1F9C1, 0x1F9C2},
+ {0x1F9E7, 0x1F9FF},
+ }
+ };
+
+ final Bidi icuBidi = new Bidi(0 /* maxLength */, 0 /* maxRunCount */);
+ icuBidi.setCustomClassifier(new AndroidBidi.EmojiBidiOverride());
+
+ for (int version = 0; version < data.length; version++) {
+ for (int row = 0; row < data[version].length; row++) {
+ for (int c = data[version][row][0]; c < data[version][row][1]; c++) {
+ assertTrue(Integer.toHexString(c) + " should be emoji", Emoji.isEmoji(c));
+
+ assertEquals(Integer.toHexString(c) + " should have neutral directionality",
+ Character.DIRECTIONALITY_OTHER_NEUTRALS,
+ BidiFormatter.DirectionalityEstimator.getDirectionality(c));
+
+ assertEquals(Integer.toHexString(c) + " shoud be OTHER_NEUTRAL for ICU Bidi",
+ UCharacterDirection.OTHER_NEUTRAL, icuBidi.getCustomizedClass(c));
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testisEmojiModifierBase_LegacyCompat() {
+ assertTrue(Emoji.isEmojiModifierBase(0x1F91D));
+ assertTrue(Emoji.isEmojiModifierBase(0x1F93C));
+ }
+
+ @Test
+ public void testisEmojiModifierBase() {
+ // each row in the data is the range of emoji
+ final int[][][] data = new int[][][]{
+ { // EMOJI 5
+ // range of emoji: i.e from 0x1F91F to 0x1F91F inclusive
+ {0x1F91F, 0x1F91F},
+ {0x1F931, 0x1F932},
+ {0x1F9D1, 0x1F9DD},
+ },
+ { // EMOJI 11
+ {0x1F9B5, 0x1F9B6},
+ {0x1F9B8, 0x1F9B9}
+ }
+ };
+ for (int version = 0; version < data.length; version++) {
+ for (int row = 0; row < data[version].length; row++) {
+ for (int c = data[version][row][0]; c < data[version][row][1]; c++) {
+ assertTrue(Integer.toHexString(c) + " should be emoji modifier base",
+ Emoji.isEmojiModifierBase(c));
+ }
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/res/layout/global_actions_item.xml b/packages/SystemUI/res/layout/global_actions_item.xml
index bf3aea8..66a4b73 100644
--- a/packages/SystemUI/res/layout/global_actions_item.xml
+++ b/packages/SystemUI/res/layout/global_actions_item.xml
@@ -25,8 +25,8 @@
android:minHeight="92dp"
android:gravity="center"
android:orientation="vertical"
- android:paddingEnd="0dip"
- android:paddingStart="0dip">
+ android:paddingEnd="4dip"
+ android:paddingStart="4dip">
<ImageView
android:id="@*android:id/icon"
diff --git a/packages/SystemUI/res/layout/global_actions_wrapped.xml b/packages/SystemUI/res/layout/global_actions_wrapped.xml
index 4a6af9e..b715def 100644
--- a/packages/SystemUI/res/layout/global_actions_wrapped.xml
+++ b/packages/SystemUI/res/layout/global_actions_wrapped.xml
@@ -17,7 +17,7 @@
android:layout_gravity="top|right"
android:gravity="center"
android:orientation="vertical"
- android:padding="16dp"
+ android:padding="12dp"
android:translationZ="9dp" />
</com.android.systemui.HardwareUiLayout>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index a1e5b0e..875000c 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -899,8 +899,6 @@
<dimen name="default_gear_space">18dp</dimen>
<dimen name="cell_overlay_padding">18dp</dimen>
- <dimen name="hwui_edge_margin">16dp</dimen>
-
<dimen name="global_actions_panel_width">120dp</dimen>
<dimen name="global_actions_top_padding">120dp</dimen>
@@ -916,7 +914,7 @@
<dimen name="corner_size">8dp</dimen>
<dimen name="top_padding">0dp</dimen>
<dimen name="bottom_padding">48dp</dimen>
- <dimen name="edge_margin">16dp</dimen>
+ <dimen name="edge_margin">8dp</dimen>
<dimen name="rounded_corner_radius">0dp</dimen>
<dimen name="rounded_corner_content_padding">0dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
index 3bdb247..98dc321 100644
--- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
@@ -89,7 +89,7 @@
mEdgeBleed = Settings.Secure.getInt(getContext().getContentResolver(),
EDGE_BLEED, 0) != 0;
mRoundedDivider = Settings.Secure.getInt(getContext().getContentResolver(),
- ROUNDED_DIVIDER, 1) != 0;
+ ROUNDED_DIVIDER, 0) != 0;
updateEdgeMargin(mEdgeBleed ? 0 : getEdgePadding());
mBackground = new HardwareBgDrawable(mRoundedDivider, !mEdgeBleed, getContext());
if (mChild != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java b/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java
index 8515bf2..4fea45c3 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java
@@ -116,6 +116,7 @@
private SettingsObserver mSettingsObserver;
public AlwaysOnDisplayPolicy(Context context) {
+ context = context.getApplicationContext();
mContext = context;
mParser = new KeyValueListParser(',');
mSettingsObserver = new SettingsObserver(context.getMainThreadHandler());
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index 5bf62f6..e9d78d9 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -61,13 +61,14 @@
DozeMachine machine = new DozeMachine(wrappedService, config, wakeLock);
machine.setParts(new DozeMachine.Part[]{
- new DozePauser(handler, machine, alarmManager, new AlwaysOnDisplayPolicy(context)),
+ new DozePauser(handler, machine, alarmManager, params.getPolicy()),
new DozeFalsingManagerAdapter(FalsingManager.getInstance(context)),
createDozeTriggers(context, sensorManager, host, alarmManager, config, params,
handler, wakeLock, machine),
createDozeUi(context, host, wakeLock, machine, handler, alarmManager, params),
new DozeScreenState(wrappedService, handler, params, wakeLock),
- createDozeScreenBrightness(context, wrappedService, sensorManager, host, handler),
+ createDozeScreenBrightness(context, wrappedService, sensorManager, host, params,
+ handler),
new DozeWallpaperState(context, params)
});
@@ -76,11 +77,11 @@
private DozeMachine.Part createDozeScreenBrightness(Context context,
DozeMachine.Service service, SensorManager sensorManager, DozeHost host,
- Handler handler) {
+ DozeParameters params, Handler handler) {
Sensor sensor = DozeSensors.findSensorWithType(sensorManager,
context.getString(R.string.doze_brightness_sensor_type));
return new DozeScreenBrightness(context, service, sensorManager, sensor, host, handler,
- new AlwaysOnDisplayPolicy(context));
+ params.getPolicy());
}
private DozeTriggers createDozeTriggers(Context context, SensorManager sensorManager,
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
index f72bff5d6..a0fdb9d 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
@@ -21,6 +21,7 @@
import android.view.Display;
import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.util.wakelock.SettableWakeLock;
import com.android.systemui.util.wakelock.WakeLock;
/**
@@ -43,15 +44,14 @@
private final DozeParameters mParameters;
private int mPendingScreenState = Display.STATE_UNKNOWN;
- private boolean mWakeLockHeld;
- private WakeLock mWakeLock;
+ private SettableWakeLock mWakeLock;
public DozeScreenState(DozeMachine.Service service, Handler handler,
DozeParameters parameters, WakeLock wakeLock) {
mDozeService = service;
mHandler = handler;
mParameters = parameters;
- mWakeLock = wakeLock;
+ mWakeLock = new SettableWakeLock(wakeLock);
}
@Override
@@ -64,6 +64,7 @@
mHandler.removeCallbacks(mApplyPendingScreenState);
applyScreenState(screenState);
+ mWakeLock.setAcquired(false);
return;
}
@@ -84,9 +85,8 @@
boolean shouldDelayTransition = newState == DozeMachine.State.DOZE_AOD
&& mParameters.shouldControlScreenOff();
- if (!mWakeLockHeld && shouldDelayTransition) {
- mWakeLockHeld = true;
- mWakeLock.acquire();
+ if (shouldDelayTransition) {
+ mWakeLock.setAcquired(true);
}
if (!messagePending) {
@@ -118,10 +118,7 @@
if (DEBUG) Log.d(TAG, "setDozeScreenState(" + screenState + ")");
mDozeService.setDozeScreenState(screenState);
mPendingScreenState = Display.STATE_UNKNOWN;
- if (mWakeLockHeld) {
- mWakeLockHeld = false;
- mWakeLock.release();
- }
+ mWakeLock.setAcquired(false);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index aa26419..7339304 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -62,6 +62,7 @@
public void onDestroy() {
Dependency.get(PluginManager.class).removePluginListener(this);
super.onDestroy();
+ mDozeMachine = null;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index f7a258a..be3e322 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -85,7 +85,7 @@
mAllowPulseTriggers = allowPulseTriggers;
mDozeSensors = new DozeSensors(context, alarmManager, mSensorManager, dozeParameters,
config, wakeLock, this::onSensor, this::onProximityFar,
- new AlwaysOnDisplayPolicy(context));
+ dozeParameters.getPolicy());
mUiModeManager = mContext.getSystemService(UiModeManager.class);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 07b79a2..d2d9c4c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -59,9 +59,9 @@
@VisibleForTesting
protected DozeParameters(Context context) {
- mContext = context;
+ mContext = context.getApplicationContext();
mAmbientDisplayConfiguration = new AmbientDisplayConfiguration(mContext);
- mAlwaysOnPolicy = new AlwaysOnDisplayPolicy(context);
+ mAlwaysOnPolicy = new AlwaysOnDisplayPolicy(mContext);
mControlScreenOffAnimation = !getDisplayNeedsBlanking();
mPowerManager = mContext.getSystemService(PowerManager.class);
@@ -243,6 +243,10 @@
mDozeAlwaysOn = mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT);
}
+ public AlwaysOnDisplayPolicy getPolicy() {
+ return mAlwaysOnPolicy;
+ }
+
/**
* Parses a spec of the form `1,2,3,!5,*`. The resulting object will match numbers that are
* listed, will not match numbers that are listed with a ! prefix, and will match / not match
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
index 94ac4f62..669a8c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
@@ -82,6 +82,7 @@
mSlotWifi = mContext.getString(com.android.internal.R.string.status_bar_wifi);
mSlotEthernet = mContext.getString(com.android.internal.R.string.status_bar_ethernet);
mSlotVpn = mContext.getString(com.android.internal.R.string.status_bar_vpn);
+ mActivityEnabled = mContext.getResources().getBoolean(R.bool.config_showActivity);
mIconController = iconController;
mNetworkController = Dependency.get(NetworkController.class);
@@ -108,10 +109,6 @@
return isBranded ? R.drawable.stat_sys_branded_vpn : R.drawable.stat_sys_vpn_ic;
}
- private void updateActivityEnabled() {
- mActivityEnabled = mContext.getResources().getBoolean(R.bool.config_showActivity);
- }
-
/**
* From SecurityController
*/
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
index 6683636..b6039b6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
@@ -25,8 +25,10 @@
import static com.android.systemui.doze.DozeMachine.State.UNINITIALIZED;
import static com.android.systemui.utils.os.FakeHandler.Mode.QUEUEING;
+import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -41,6 +43,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.wakelock.WakeLock;
+import com.android.systemui.util.wakelock.WakeLockFake;
import com.android.systemui.utils.os.FakeHandler;
import org.junit.Before;
@@ -58,8 +61,7 @@
FakeHandler mHandlerFake;
@Mock
DozeParameters mDozeParameters;
- @Mock
- WakeLock mWakeLock;
+ WakeLockFake mWakeLock;
@Before
public void setUp() throws Exception {
@@ -68,6 +70,7 @@
when(mDozeParameters.getAlwaysOn()).thenReturn(true);
mServiceFake = new DozeServiceFake();
mHandlerFake = new FakeHandler(Looper.getMainLooper());
+ mWakeLock = new WakeLockFake();
mScreen = new DozeScreenState(mServiceFake, mHandlerFake, mDozeParameters, mWakeLock);
}
@@ -158,14 +161,29 @@
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mHandlerFake.dispatchQueuedMessages();
- reset(mWakeLock);
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
- verify(mWakeLock).acquire();
- verify(mWakeLock, never()).release();
+ assertThat(mWakeLock.isHeld(), is(true));
mHandlerFake.dispatchQueuedMessages();
- verify(mWakeLock).release();
+ assertThat(mWakeLock.isHeld(), is(false));
+ }
+
+ @Test
+ public void test_releasesWakeLock_abortingLowPowerDelayed() {
+ // Transition to low power mode will be delayed to let
+ // animations play at 60 fps.
+ when(mDozeParameters.shouldControlScreenOff()).thenReturn(true);
+ mHandlerFake.setMode(QUEUEING);
+
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mHandlerFake.dispatchQueuedMessages();
+
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+ assertThat(mWakeLock.isHeld(), is(true));
+ mScreen.transitionTo(DOZE_AOD, FINISH);
+
+ assertThat(mWakeLock.isHeld(), is(false));
}
}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java
index 2ed4516..ae14dfa 100644
--- a/services/core/java/com/android/server/BinderCallsStatsService.java
+++ b/services/core/java/com/android/server/BinderCallsStatsService.java
@@ -30,26 +30,58 @@
private static final String TAG = "BinderCallsStatsService";
- private static final String PERSIST_SYS_BINDER_CPU_STATS_TRACKING
- = "persist.sys.binder_cpu_stats_tracking";
+ private static final String PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING
+ = "persist.sys.binder_calls_detailed_tracking";
public static void start() {
BinderCallsStatsService service = new BinderCallsStatsService();
ServiceManager.addService("binder_calls_stats", service);
- // TODO Enable by default on eng/userdebug builds
- boolean trackingEnabledDefault = false;
- boolean trackingEnabled = SystemProperties.getBoolean(PERSIST_SYS_BINDER_CPU_STATS_TRACKING,
- trackingEnabledDefault);
+ boolean detailedTrackingEnabled = SystemProperties.getBoolean(
+ PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING, false);
- if (trackingEnabled) {
+ if (detailedTrackingEnabled) {
Slog.i(TAG, "Enabled CPU usage tracking for binder calls. Controlled by "
- + PERSIST_SYS_BINDER_CPU_STATS_TRACKING);
- BinderCallsStats.getInstance().setTrackingEnabled(true);
+ + PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING
+ + " or via dumpsys binder_calls_stats --enable-detailed-tracking");
+ BinderCallsStats.getInstance().setDetailedTracking(true);
}
}
+ public static void reset() {
+ Slog.i(TAG, "Resetting stats");
+ BinderCallsStats.getInstance().reset();
+ }
+
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (args != null) {
+ for (final String arg : args) {
+ if ("--reset".equals(arg)) {
+ reset();
+ pw.println("binder_calls_stats reset.");
+ return;
+ } else if ("--enable-detailed-tracking".equals(arg)) {
+ SystemProperties.set(PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING, "1");
+ BinderCallsStats.getInstance().setDetailedTracking(true);
+ pw.println("Detailed tracking enabled");
+ return;
+ } else if ("--disable-detailed-tracking".equals(arg)) {
+ SystemProperties.set(PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING, "");
+ BinderCallsStats.getInstance().setDetailedTracking(false);
+ pw.println("Detailed tracking disabled");
+ return;
+ } else if ("-h".equals(arg)) {
+ pw.println("binder_calls_stats commands:");
+ pw.println(" --reset: Reset stats");
+ pw.println(" --enable-detailed-tracking: Enables detailed tracking");
+ pw.println(" --disable-detailed-tracking: Disables detailed tracking");
+ return;
+ } else {
+ pw.println("Unknown option: " + arg);
+ return;
+ }
+ }
+ }
BinderCallsStats.getInstance().dump(pw);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 9045841..137e6ab 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -14542,6 +14542,10 @@
}
void setRunningRemoteAnimation(int pid, boolean runningRemoteAnimation) {
+ if (pid == Process.myPid()) {
+ Slog.wtf(TAG, "system can't run remote animation");
+ return;
+ }
synchronized (ActivityManagerService.this) {
final ProcessRecord pr;
synchronized (mPidsSelfLocked) {
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 762d4e5..c761754 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -82,6 +82,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Configuration;
+import android.content.res.ResourceId;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -538,25 +539,25 @@
}
Animation loadAnimationAttr(LayoutParams lp, int animAttr, int transit) {
- int anim = 0;
+ int resId = ResourceId.ID_NULL;
Context context = mContext;
if (animAttr >= 0) {
AttributeCache.Entry ent = getCachedAnimations(lp);
if (ent != null) {
context = ent.context;
- anim = ent.array.getResourceId(animAttr, 0);
+ resId = ent.array.getResourceId(animAttr, 0);
}
}
- anim = updateToTranslucentAnimIfNeeded(anim, transit);
- if (anim != 0) {
- return AnimationUtils.loadAnimation(context, anim);
+ resId = updateToTranslucentAnimIfNeeded(resId, transit);
+ if (ResourceId.isValid(resId)) {
+ return AnimationUtils.loadAnimation(context, resId);
}
return null;
}
Animation loadAnimationRes(LayoutParams lp, int resId) {
Context context = mContext;
- if (resId >= 0) {
+ if (ResourceId.isValid(resId)) {
AttributeCache.Entry ent = getCachedAnimations(lp);
if (ent != null) {
context = ent.context;
@@ -567,18 +568,12 @@
}
private Animation loadAnimationRes(String packageName, int resId) {
- int anim = 0;
- Context context = mContext;
- if (resId >= 0) {
+ if (ResourceId.isValid(resId)) {
AttributeCache.Entry ent = getCachedAnimations(packageName, resId);
if (ent != null) {
- context = ent.context;
- anim = resId;
+ return AnimationUtils.loadAnimation(ent.context, resId);
}
}
- if (anim != 0) {
- return AnimationUtils.loadAnimation(context, anim);
- }
return null;
}
diff --git a/tools/fonts/fontchain_linter.py b/tools/fonts/fontchain_linter.py
index ec40a222..ffca466 100755
--- a/tools/fonts/fontchain_linter.py
+++ b/tools/fonts/fontchain_linter.py
@@ -471,11 +471,20 @@
_emoji_zwj_sequences.update(parse_unicode_datafile(
path.join(ucd_path, 'additions', 'emoji-zwj-sequences.txt')))
+ exclusions = parse_unicode_datafile(path.join(ucd_path, 'additions', 'emoji-exclusions.txt'))
+ _emoji_sequences = remove_emoji_exclude(_emoji_sequences, exclusions)
+ _emoji_zwj_sequences = remove_emoji_exclude(_emoji_zwj_sequences, exclusions)
+ _emoji_variation_sequences = remove_emoji_variation_exclude(_emoji_variation_sequences, exclusions)
+
+def remove_emoji_variation_exclude(source, items):
+ return source.difference(items.keys())
+
+def remove_emoji_exclude(source, items):
+ return {k: v for k, v in source.items() if k not in items}
def flag_sequence(territory_code):
return tuple(0x1F1E6 + ord(ch) - ord('A') for ch in territory_code)
-
UNSUPPORTED_FLAGS = frozenset({
flag_sequence('BL'), flag_sequence('BQ'), flag_sequence('DG'),
flag_sequence('EA'), flag_sequence('EH'), flag_sequence('FK'),
@@ -522,8 +531,6 @@
ZWJ_IDENTICALS = {
# KISS
(0x1F469, 0x200D, 0x2764, 0x200D, 0x1F48B, 0x200D, 0x1F468): 0x1F48F,
- # COUPLE WITH HEART
- (0x1F469, 0x200D, 0x2764, 0x200D, 0x1F468): 0x1F491,
# FAMILY
(0x1F468, 0x200D, 0x1F469, 0x200D, 0x1F466): 0x1F46A,
}
@@ -576,6 +583,8 @@
(0x1F9DD, FEMALE_SIGN), # ELF
(0x1F9DE, FEMALE_SIGN), # GENIE
(0x1F9DF, FEMALE_SIGN), # ZOMBIE
+ (0X1F9B8, FEMALE_SIGN), # SUPERVILLAIN
+ (0x1F9B9, FEMALE_SIGN), # SUPERHERO
]
def is_fitzpatrick_modifier(cp):