Merge "Wire "Action + Ctrl + D" to moveToNextDisplay" into main
diff --git a/core/api/current.txt b/core/api/current.txt
index 911e7de..a8b9e33 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -11240,6 +11240,7 @@
method public void removeCategory(String);
method public void removeExtra(String);
method public void removeFlags(int);
+ method @FlaggedApi("android.security.prevent_intent_redirect") public void removeLaunchSecurityProtection();
method @NonNull public android.content.Intent replaceExtras(@NonNull android.content.Intent);
method @NonNull public android.content.Intent replaceExtras(@Nullable android.os.Bundle);
method public android.content.ComponentName resolveActivity(@NonNull android.content.pm.PackageManager);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index e7f4dbc..ed6b3d4a 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -237,6 +237,7 @@
import com.android.internal.os.RuntimeInit;
import com.android.internal.os.SafeZipPathValidatorCallback;
import com.android.internal.os.SomeArgs;
+import com.android.internal.os.logging.MetricsLoggerWrapper;
import com.android.internal.policy.DecorView;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastPrintWriter;
@@ -7675,6 +7676,16 @@
}
}
});
+
+ // Register callback to report native memory metrics post GC cleanup
+ if (Flags.reportPostgcMemoryMetrics() &&
+ com.android.libcore.readonly.Flags.postCleanupApis()) {
+ VMRuntime.addPostCleanupCallback(new Runnable() {
+ @Override public void run() {
+ MetricsLoggerWrapper.logPostGcMemorySnapshot();
+ }
+ });
+ }
}
@UnsupportedAppUsage
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index e882bb5..081ce31 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -345,6 +345,15 @@
*/
public AppCompatTaskInfo appCompatTaskInfo = AppCompatTaskInfo.create();
+ /**
+ * The top activity's main window frame if it doesn't match the top activity bounds.
+ * {@code null}, otherwise.
+ *
+ * @hide
+ */
+ @Nullable
+ public Rect topActivityMainWindowFrame;
+
TaskInfo() {
// Do nothing
}
@@ -477,7 +486,8 @@
&& Objects.equals(capturedLink, that.capturedLink)
&& capturedLinkTimestamp == that.capturedLinkTimestamp
&& requestedVisibleTypes == that.requestedVisibleTypes
- && appCompatTaskInfo.equalsForTaskOrganizer(that.appCompatTaskInfo);
+ && appCompatTaskInfo.equalsForTaskOrganizer(that.appCompatTaskInfo)
+ && Objects.equals(topActivityMainWindowFrame, that.topActivityMainWindowFrame);
}
/**
@@ -553,6 +563,7 @@
capturedLinkTimestamp = source.readLong();
requestedVisibleTypes = source.readInt();
appCompatTaskInfo = source.readTypedObject(AppCompatTaskInfo.CREATOR);
+ topActivityMainWindowFrame = source.readTypedObject(Rect.CREATOR);
}
/**
@@ -606,6 +617,7 @@
dest.writeLong(capturedLinkTimestamp);
dest.writeInt(requestedVisibleTypes);
dest.writeTypedObject(appCompatTaskInfo, flags);
+ dest.writeTypedObject(topActivityMainWindowFrame, flags);
}
@Override
@@ -649,6 +661,7 @@
+ " capturedLinkTimestamp=" + capturedLinkTimestamp
+ " requestedVisibleTypes=" + requestedVisibleTypes
+ " appCompatTaskInfo=" + appCompatTaskInfo
+ + " topActivityMainWindowFrame=" + topActivityMainWindowFrame
+ "}";
}
}
diff --git a/core/java/android/app/metrics.aconfig b/core/java/android/app/metrics.aconfig
new file mode 100644
index 0000000..488f1c7
--- /dev/null
+++ b/core/java/android/app/metrics.aconfig
@@ -0,0 +1,10 @@
+package: "android.app"
+container: "system"
+
+flag {
+ namespace: "system_performance"
+ name: "report_postgc_memory_metrics"
+ is_exported: false
+ description: "Controls whether to report memory metrics post GC cleanup"
+ bug: "331243037"
+}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index f798523..e8cec70 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -20,6 +20,7 @@
import static android.content.ContentProvider.maybeAddUserId;
import static android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE;
import static android.security.Flags.FLAG_FRP_ENFORCEMENT;
+import static android.security.Flags.FLAG_PREVENT_INTENT_REDIRECT;
import static android.security.Flags.preventIntentRedirect;
import android.Manifest;
@@ -12297,6 +12298,20 @@
mExtras.setIsIntentExtra();
}
+ /**
+ * When an intent comes from another app or component as an embedded extra intent, the system
+ * creates a token to identify the creator of this foreign intent. If this token is missing or
+ * invalid, the system will block the launch of this intent. If it contains a valid token, the
+ * system will perform verification against the creator to block launching target it has no
+ * permission to launch or block it from granting URI access to the tagert it cannot access.
+ * This method provides a way to opt out this feature.
+ */
+ @FlaggedApi(FLAG_PREVENT_INTENT_REDIRECT)
+ public void removeLaunchSecurityProtection() {
+ mExtendedFlags &= ~EXTENDED_FLAG_MISSING_CREATOR_OR_INVALID_TOKEN;
+ removeCreatorTokenInfo();
+ }
+
public void writeToParcel(Parcel out, int flags) {
out.writeString8(mAction);
Uri.writeToParcel(out, mData);
diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java
index ddcb5c6..6c3c285 100644
--- a/core/java/android/os/BatteryUsageStats.java
+++ b/core/java/android/os/BatteryUsageStats.java
@@ -24,6 +24,8 @@
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BatteryStatsHistory;
import com.android.internal.os.BatteryStatsHistoryIterator;
import com.android.internal.os.MonotonicClock;
@@ -43,7 +45,9 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* Contains a snapshot of battery attribution data, on a per-subsystem and per-UID basis.
@@ -126,6 +130,12 @@
// Max window size. CursorWindow uses only as much memory as needed.
private static final long BATTERY_CONSUMER_CURSOR_WINDOW_SIZE = 20_000_000; // bytes
+ /**
+ * Used by tests to ensure all BatteryUsageStats instances are closed.
+ */
+ @VisibleForTesting
+ public static boolean DEBUG_INSTANCE_COUNT;
+
private static final int STATSD_PULL_ATOM_MAX_BYTES = 45000;
private static final int[] UID_USAGE_TIME_PROCESS_STATES = {
@@ -153,7 +163,7 @@
private final List<UserBatteryConsumer> mUserBatteryConsumers;
private final AggregateBatteryConsumer[] mAggregateBatteryConsumers;
private final BatteryStatsHistory mBatteryStatsHistory;
- private BatteryConsumer.BatteryConsumerDataLayout mBatteryConsumerDataLayout;
+ private final BatteryConsumer.BatteryConsumerDataLayout mBatteryConsumerDataLayout;
private CursorWindow mBatteryConsumersCursorWindow;
private BatteryUsageStats(@NonNull Builder builder) {
@@ -873,6 +883,7 @@
@Override
public void close() throws IOException {
+ onCursorWindowReleased(mBatteryConsumersCursorWindow);
mBatteryConsumersCursorWindow.close();
mBatteryConsumersCursorWindow = null;
}
@@ -880,6 +891,7 @@
@Override
protected void finalize() throws Throwable {
if (mBatteryConsumersCursorWindow != null) {
+ // Do not decrement sOpenCusorWindowCount. All instances should be closed explicitly
mBatteryConsumersCursorWindow.close();
}
super.finalize();
@@ -934,6 +946,7 @@
boolean includesPowerStateData, double minConsumedPowerThreshold) {
mBatteryConsumersCursorWindow =
new CursorWindow(null, BATTERY_CONSUMER_CURSOR_WINDOW_SIZE);
+ onCursorWindowAllocated(mBatteryConsumersCursorWindow);
mBatteryConsumerDataLayout = BatteryConsumer.createBatteryConsumerDataLayout(
customPowerComponentNames, includePowerModels, includeProcessStateData,
includeScreenStateData, includesPowerStateData);
@@ -996,6 +1009,7 @@
*/
public void discard() {
mBatteryConsumersCursorWindow.close();
+ onCursorWindowReleased(mBatteryConsumersCursorWindow);
}
/**
@@ -1264,4 +1278,50 @@
}
}
}
+
+ @GuardedBy("BatteryUsageStats.class")
+ private static Map<CursorWindow, Exception> sInstances;
+
+ private static void onCursorWindowAllocated(CursorWindow window) {
+ if (!DEBUG_INSTANCE_COUNT) {
+ return;
+ }
+
+ synchronized (BatteryUsageStats.class) {
+ if (sInstances == null) {
+ sInstances = new HashMap<>();
+ }
+ sInstances.put(window, new Exception());
+ }
+ }
+
+ private static void onCursorWindowReleased(CursorWindow window) {
+ if (!DEBUG_INSTANCE_COUNT) {
+ return;
+ }
+
+ synchronized (BatteryUsageStats.class) {
+ sInstances.remove(window);
+ }
+ }
+
+ /**
+ * Used by tests to ensure all BatteryUsageStats instances are closed.
+ */
+ @VisibleForTesting
+ public static void assertAllInstancesClosed() {
+ if (!DEBUG_INSTANCE_COUNT) {
+ throw new IllegalStateException("DEBUG_INSTANCE_COUNT is false");
+ }
+
+ synchronized (BatteryUsageStats.class) {
+ if (!sInstances.isEmpty()) {
+ Exception callSite = sInstances.entrySet().iterator().next().getValue();
+ int count = sInstances.size();
+ sInstances.clear();
+ throw new IllegalStateException(
+ "Instances of BatteryUsageStats not closed: " + count, callSite);
+ }
+ }
+ }
}
diff --git a/core/java/android/security/forensic/ForensicEvent.aidl b/core/java/android/security/forensic/ForensicEvent.aidl
new file mode 100644
index 0000000..a321fb0
--- /dev/null
+++ b/core/java/android/security/forensic/ForensicEvent.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2024 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.security.forensic;
+
+/** {@hide} */
+parcelable ForensicEvent;
diff --git a/core/java/android/security/forensic/ForensicEvent.java b/core/java/android/security/forensic/ForensicEvent.java
new file mode 100644
index 0000000..9cbc5ec
--- /dev/null
+++ b/core/java/android/security/forensic/ForensicEvent.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2024 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.security.forensic;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.security.Flags;
+import android.util.ArrayMap;
+
+import java.util.Map;
+
+/**
+ * A class that represents a forensic event.
+ * @hide
+ */
+@FlaggedApi(Flags.FLAG_AFL_API)
+public final class ForensicEvent implements Parcelable {
+ private static final String TAG = "ForensicEvent";
+
+ @NonNull
+ private final String mType;
+
+ @NonNull
+ private final Map<String, String> mKeyValuePairs;
+
+ public static final @NonNull Parcelable.Creator<ForensicEvent> CREATOR =
+ new Parcelable.Creator<>() {
+ public ForensicEvent createFromParcel(Parcel in) {
+ return new ForensicEvent(in);
+ }
+
+ public ForensicEvent[] newArray(int size) {
+ return new ForensicEvent[size];
+ }
+ };
+
+ public ForensicEvent(@NonNull String type, @NonNull Map<String, String> keyValuePairs) {
+ mType = type;
+ mKeyValuePairs = keyValuePairs;
+ }
+
+ private ForensicEvent(@NonNull Parcel in) {
+ mType = in.readString();
+ mKeyValuePairs = new ArrayMap<>(in.readInt());
+ in.readMap(mKeyValuePairs, getClass().getClassLoader(), String.class, String.class);
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel out, int flags) {
+ out.writeString(mType);
+ out.writeInt(mKeyValuePairs.size());
+ out.writeMap(mKeyValuePairs);
+ }
+
+ @FlaggedApi(Flags.FLAG_AFL_API)
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ return "ForensicEvent{"
+ + "mType=" + mType
+ + ", mKeyValuePairs=" + mKeyValuePairs
+ + '}';
+ }
+}
diff --git a/core/java/android/security/forensic/IBackupTransport.aidl b/core/java/android/security/forensic/IBackupTransport.aidl
new file mode 100644
index 0000000..c2cbc83
--- /dev/null
+++ b/core/java/android/security/forensic/IBackupTransport.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2024 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.security.forensic;
+import android.security.forensic.ForensicEvent;
+
+import com.android.internal.infra.AndroidFuture;
+
+/** {@hide} */
+oneway interface IBackupTransport {
+ /**
+ * Initialize the server side.
+ */
+ void initialize(in AndroidFuture<int> resultFuture);
+
+ /**
+ * Send forensic logging data to the backup destination.
+ * The data is a list of ForensicEvent.
+ * The ForensicEvent is an abstract class that represents
+ * different type of events.
+ */
+ void addData(in List<ForensicEvent> events, in AndroidFuture<int> resultFuture);
+
+ /**
+ * Release the binder to the server.
+ */
+ void release(in AndroidFuture<int> resultFuture);
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java
index 07aa720..b56aadd 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistory.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistory.java
@@ -1770,6 +1770,10 @@
@GuardedBy("this")
private void writeHistoryItem(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
+ if (cur.eventCode != HistoryItem.EVENT_NONE && cur.eventTag.string == null) {
+ Slog.wtfStack(TAG, "Event " + Integer.toHexString(cur.eventCode) + " without a name");
+ }
+
if (mTracer != null && mTracer.tracingEnabled()) {
recordTraceEvents(cur.eventCode, cur.eventTag);
recordTraceCounters(mTraceLastState, cur.states, STATE1_TRACE_MASK,
@@ -2266,6 +2270,7 @@
private int writeHistoryTag(HistoryTag tag) {
if (tag.string == null) {
Slog.wtfStack(TAG, "writeHistoryTag called with null name");
+ tag.string = "";
}
final int stringLength = tag.string.length();
diff --git a/core/java/com/android/internal/os/LongArrayMultiStateCounter.java b/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
index dfb2884..489721f 100644
--- a/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
+++ b/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
@@ -105,7 +105,7 @@
public void setValues(long[] array) {
if (array.length != mLength) {
throw new IllegalArgumentException(
- "Invalid array length: " + mLength + ", expected: " + mLength);
+ "Invalid array length: " + array.length + ", expected: " + mLength);
}
native_setValues(mNativeObject, array);
}
@@ -116,7 +116,7 @@
public void getValues(long[] array) {
if (array.length != mLength) {
throw new IllegalArgumentException(
- "Invalid array length: " + mLength + ", expected: " + mLength);
+ "Invalid array length: " + array.length + ", expected: " + mLength);
}
native_getValues(mNativeObject, array);
}
@@ -347,6 +347,11 @@
throw new IllegalArgumentException(
"State: " + state + ", outside the range: [0-" + mStateCount + "]");
}
+ if (longArrayContainer.mLength != mLength) {
+ throw new IllegalArgumentException(
+ "Invalid array length: " + longArrayContainer.mLength
+ + ", expected: " + mLength);
+ }
native_getCounts(mNativeObject, longArrayContainer.mNativeObject, state);
}
diff --git a/services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java b/core/java/com/android/internal/os/ProcfsMemoryUtil.java
similarity index 60%
rename from services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java
rename to core/java/com/android/internal/os/ProcfsMemoryUtil.java
index 6cb6dc0..382f6c4 100644
--- a/services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java
+++ b/core/java/com/android/internal/os/ProcfsMemoryUtil.java
@@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.stats.pull;
+package com.android.internal.os;
-import static android.os.Process.PROC_OUT_STRING;
+import static android.os.Process.*;
import android.annotation.Nullable;
import android.os.Process;
@@ -23,6 +23,7 @@
public final class ProcfsMemoryUtil {
private static final int[] CMDLINE_OUT = new int[] { PROC_OUT_STRING };
+ private static final int[] OOM_SCORE_ADJ_OUT = new int[] { PROC_NEWLINE_TERM | PROC_OUT_LONG };
private static final String[] STATUS_KEYS = new String[] {
"Uid:",
"VmHWM:",
@@ -38,17 +39,34 @@
private ProcfsMemoryUtil() {}
/**
- * Reads memory stats of a process from procfs. Returns values of the VmHWM, VmRss, AnonRSS,
- * VmSwap, RssShmem fields in /proc/pid/status in kilobytes or null if not available.
+ * Reads memory stats of a process from procfs.
+ *
+ * Returns values of the VmHWM, VmRss, AnonRSS, VmSwap, RssShmem fields in
+ * /proc/pid/status in kilobytes or null if not available.
*/
@Nullable
public static MemorySnapshot readMemorySnapshotFromProcfs(int pid) {
+ return readMemorySnapshotFromProcfs("/proc/" + pid + "/status");
+ }
+
+ /**
+ * Reads memory stats of the current process from procfs.
+ *
+ * Returns values of the VmHWM, VmRss, AnonRSS, VmSwap, RssShmem fields in
+ * /proc/self/status in kilobytes or null if not available.
+ */
+ @Nullable
+ public static MemorySnapshot readMemorySnapshotFromProcfs() {
+ return readMemorySnapshotFromProcfs("/proc/self/status");
+ }
+
+ private static MemorySnapshot readMemorySnapshotFromProcfs(String path) {
long[] output = new long[STATUS_KEYS.length];
output[0] = -1;
output[3] = -1;
output[4] = -1;
output[5] = -1;
- Process.readProcLines("/proc/" + pid + "/status", STATUS_KEYS, output);
+ Process.readProcLines(path, STATUS_KEYS, output);
if (output[0] == -1 || output[3] == -1 || output[4] == -1 || output[5] == -1) {
// Could not open or parse file.
return null;
@@ -70,14 +88,54 @@
* if the file is not available.
*/
public static String readCmdlineFromProcfs(int pid) {
+ return readCmdlineFromProcfs("/proc/" + pid + "/cmdline");
+ }
+
+ /**
+ * Reads cmdline of the current process from procfs.
+ *
+ * Returns content of /proc/pid/cmdline (e.g. /system/bin/statsd) or an empty string
+ * if the file is not available.
+ */
+ public static String readCmdlineFromProcfs() {
+ return readCmdlineFromProcfs("/proc/self/cmdline");
+ }
+
+ private static String readCmdlineFromProcfs(String path) {
String[] cmdline = new String[1];
- if (!Process.readProcFile("/proc/" + pid + "/cmdline", CMDLINE_OUT, cmdline, null, null)) {
+ if (!Process.readProcFile(path, CMDLINE_OUT, cmdline, null, null)) {
return "";
}
return cmdline[0];
}
/**
+ * Reads oom_score_adj of a process from procfs
+ *
+ * Returns content of /proc/pid/oom_score_adj. Defaults to 0 if reading fails.
+ */
+ public static int readOomScoreAdjFromProcfs(int pid) {
+ return readOomScoreAdjFromProcfs("/proc/" + pid + "/oom_score_adj");
+ }
+
+ /**
+ * Reads oom_score_adj of the current process from procfs
+ *
+ * Returns content of /proc/pid/oom_score_adj. Defaults to 0 if reading fails.
+ */
+ public static int readOomScoreAdjFromProcfs() {
+ return readOomScoreAdjFromProcfs("/proc/self/oom_score_adj");
+ }
+
+ private static int readOomScoreAdjFromProcfs(String path) {
+ long[] oom_score_adj = new long[1];
+ if (Process.readProcFile(path, OOM_SCORE_ADJ_OUT, null, oom_score_adj, null)) {
+ return (int)oom_score_adj[0];
+ }
+ return 0;
+ }
+
+ /**
* Scans all /proc/pid/cmdline entries and returns a mapping between pid and cmdline.
*/
public static SparseArray<String> getProcessCmdlines() {
@@ -109,7 +167,7 @@
/** Reads and parses selected entries of /proc/vmstat. */
@Nullable
- static VmStat readVmStat() {
+ public static VmStat readVmStat() {
long[] vmstat = new long[VMSTAT_KEYS.length];
vmstat[0] = -1;
Process.readProcLines("/proc/vmstat", VMSTAT_KEYS, vmstat);
@@ -121,7 +179,7 @@
return result;
}
- static final class VmStat {
+ public static final class VmStat {
public int oomKillCount;
}
}
diff --git a/core/java/com/android/internal/os/logging/MetricsLoggerWrapper.java b/core/java/com/android/internal/os/logging/MetricsLoggerWrapper.java
index b42ea7d..e2237f6 100644
--- a/core/java/com/android/internal/os/logging/MetricsLoggerWrapper.java
+++ b/core/java/com/android/internal/os/logging/MetricsLoggerWrapper.java
@@ -16,9 +16,15 @@
package com.android.internal.os.logging;
+import android.app.Application;
+import android.os.Process;
+import android.util.Log;
import android.view.WindowManager.LayoutParams;
+import com.android.internal.os.ProcfsMemoryUtil;
import com.android.internal.util.FrameworkStatsLog;
+import java.util.Collection;
+import libcore.util.NativeAllocationRegistry;
/**
* Used to wrap different logging calls in one, so that client side code base is clean and more
@@ -49,4 +55,46 @@
}
}
}
+
+ public static void logPostGcMemorySnapshot() {
+ if (!com.android.libcore.Flags.nativeMetrics()) {
+ return;
+ }
+ int pid = Process.myPid();
+ String processName = Application.getProcessName();
+ Collection<NativeAllocationRegistry.Metrics> metrics =
+ NativeAllocationRegistry.getMetrics();
+ int nMetrics = metrics.size();
+
+ String[] classNames = new String[nMetrics];
+ long[] mallocedCount = new long[nMetrics];
+ long[] mallocedBytes = new long[nMetrics];
+ long[] nonmallocedCount = new long[nMetrics];
+ long[] nonmallocedBytes = new long[nMetrics];
+
+ int i = 0;
+ for (NativeAllocationRegistry.Metrics m : metrics) {
+ classNames[i] = m.getClassName();
+ mallocedCount[i] = m.getMallocedCount();
+ mallocedBytes[i] = m.getMallocedBytes();
+ nonmallocedCount[i] = m.getNonmallocedCount();
+ nonmallocedBytes[i] = m.getNonmallocedBytes();
+ i++;
+ }
+
+ ProcfsMemoryUtil.MemorySnapshot m = ProcfsMemoryUtil.readMemorySnapshotFromProcfs();
+ int oom_score_adj = ProcfsMemoryUtil.readOomScoreAdjFromProcfs();
+ FrameworkStatsLog.write(FrameworkStatsLog.POSTGC_MEMORY_SNAPSHOT,
+ m.uid, processName, pid,
+ oom_score_adj,
+ m.rssInKilobytes,
+ m.anonRssInKilobytes,
+ m.swapInKilobytes,
+ m.anonRssInKilobytes + m.swapInKilobytes,
+ classNames,
+ mallocedCount,
+ mallocedBytes,
+ nonmallocedCount,
+ nonmallocedBytes);
+ }
}
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4198171..42ac90dd 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -7175,4 +7175,7 @@
<string name="identity_check_settings_action"></string>
<!-- Package for opening identity check settings page [CHAR LIMIT=NONE] [DO NOT TRANSLATE] -->
<string name="identity_check_settings_package_name">com\u002eandroid\u002esettings</string>
+
+ <!-- The name of the service for forensic backup transport. -->
+ <string name="config_forensicBackupTransport" translatable="false"></string>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 0b2b345..dfee85a 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -5636,4 +5636,7 @@
<!-- Identity check strings -->
<java-symbol type="string" name="identity_check_settings_action" />
<java-symbol type="string" name="identity_check_settings_package_name" />
+
+ <!-- Forensic backup transport -->
+ <java-symbol type="string" name="config_forensicBackupTransport" />
</resources>
diff --git a/data/fonts/Android.bp b/data/fonts/Android.bp
index 4edf52b..0964aab 100644
--- a/data/fonts/Android.bp
+++ b/data/fonts/Android.bp
@@ -53,22 +53,9 @@
name: "use_var_font",
}
-soong_config_module_type {
- name: "prebuilt_fonts_xml",
- module_type: "prebuilt_etc",
- config_namespace: "noto_sans_cjk_config",
- bool_variables: ["use_var_font"],
- properties: ["src"],
-}
-
-prebuilt_fonts_xml {
+prebuilt_etc {
name: "fonts.xml",
src: "fonts.xml",
- soong_config_variables: {
- use_var_font: {
- src: "fonts_cjkvf.xml",
- },
- },
}
prebuilt_etc {
diff --git a/data/fonts/font_fallback.xml b/data/fonts/font_fallback.xml
deleted file mode 100644
index ae50da1..0000000
--- a/data/fonts/font_fallback.xml
+++ /dev/null
@@ -1,950 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- In this file, all fonts without names are added to the default list.
- Fonts are chosen based on a match: full BCP-47 language tag including
- script, then just language, and finally order (the first font containing
- the glyph).
-
- Order of appearance is also the tiebreaker for weight matching. This is
- the reason why the 900 weights of Roboto precede the 700 weights - we
- prefer the former when an 800 weight is requested. Since bold spans
- effectively add 300 to the weight, this ensures that 900 is the bold
- paired with the 500 weight, ensuring adequate contrast.
-
-
- The font_fallback.xml defines the list of font used by the system.
-
- `familyset` node:
- A `familyset` element must be a root node of the font_fallback.xml. No attributes are allowed
- to `familyset` node.
- The `familyset` node can contains `family` and `alias` nodes. Any other nodes will be ignored.
-
- `family` node:
- A `family` node defines a single font family definition.
- A font family is a set of fonts for drawing text in various styles such as weight, slant.
- There are three types of families, default family, named family and locale fallback family.
-
- The default family is a special family node appeared the first node of the `familyset` node.
- The default family is used as first priority fallback.
- Only `name` attribute can be used for default family node. If the `name` attribute is
- specified, This family will also works as named family.
-
- The named family is a family that has name attribute. The named family defines a new fallback.
- For example, if the name attribute is "serif", it creates serif fallback. Developers can
- access the fallback by using Typeface#create API.
- The named family can not have attribute other than `name` attribute. The `name` attribute
- cannot be empty.
-
- The locale fallback family is a font family that is used for fallback. The fallback family is
- used when the named family or default family cannot be used. The locale fallback family can
- have `lang` attribute and `variant` attribute. The `lang` attribute is an optional comma
- separated BCP-47i language tag. The `variant` is an optional attribute that can be one one
- `element`, `compact`. If a `variant` attribute is not specified, it is treated as default.
-
- `alias` node:
- An `alias` node defines a alias of named family with changing weight offset. An `alias` node
- can have mandatory `name` and `to` attribute and optional `weight` attribute. This `alias`
- defines new fallback that has the name of specified `name` attribute. The fallback list is
- the same to the fallback that of the name specified with `to` attribute. If `weight` attribute
- is specified, the base weight offset is shifted to the specified value. For example, if the
- `weight` is 500, the output text is drawn with 500 of weight.
-
- `font` node:
- A `font` node defines a single font definition. There are two types of fonts, static font and
- variable font.
-
- A static font can have `weight`, `style`, `index` and `postScriptName` attributes. A `weight`
- is a mandatory attribute that defines the weight of the font. Any number between 0 to 1000 is
- valid. A `style` is a mandatory attribute that defines the style of the font. A 'style'
- attribute can be `normal` or `italic`. An `index` is an optional attribute that defines the
- index of the font collection. If this is not specified, it is treated as 0. If the font file
- is not a font collection, this attribute is ignored. A `postScriptName` attribute is an
- optional attribute. A PostScript name is used for identifying target of system font update.
- If this is not specified, the system assumes the filename is same to PostScript name of the
- font file. For example, if the font file is "Roboto-Regular.ttf", the system assume the
- PostScript name of this font is "Roboto-Regular".
-
- A variable font can be only defined for the variable font file. A variable font can have
- `axis` child nodes for specifying axis values. A variable font can have all attribute of
- static font and can have additional `supportedAxes` attribute. A `supportedAxes` attribute
- is a comma separated supported axis tags. As of Android V, only `wght` and `ital` axes can
- be specified.
-
- If `supportedAxes` attribute is not specified, this `font` node works as static font of the
- single instance of variable font specified with `axis` children.
-
- If `supportedAxes` attribute is specified, the system dynamically create font instance for the
- given weight and style value. If `wght` is specified in `supportedAxes` attribute the `weight`
- attribute and `axis` child that has `wght` tag become optional and ignored because it is
- determined by system at runtime. Similarly, if `ital` is specified in `supportedAxes`
- attribute, the `style` attribute and `axis` child that has `ital` tag become optional and
- ignored.
-
- `axis` node:
- An `axis` node defines a font variation value for a tag. An `axis` node can have two mandatory
- attributes, `tag` and `value`. If the font is variable font and the same tag `axis` node is
- specified in `supportedAxes` attribute, the style value works like a default instance.
--->
-<familyset>
- <!-- first font is default -->
- <family name="sans-serif">
- <font supportedAxes="wght,ital">Roboto-Regular.ttf
- <axis tag="wdth" stylevalue="100" />
- </font>
- </family>
-
-
- <!-- Note that aliases must come after the fonts they reference. -->
- <alias name="sans-serif-thin" to="sans-serif" weight="100" />
- <alias name="sans-serif-light" to="sans-serif" weight="300" />
- <alias name="sans-serif-medium" to="sans-serif" weight="500" />
- <alias name="sans-serif-black" to="sans-serif" weight="900" />
- <alias name="arial" to="sans-serif" />
- <alias name="helvetica" to="sans-serif" />
- <alias name="tahoma" to="sans-serif" />
- <alias name="verdana" to="sans-serif" />
-
- <family name="sans-serif-condensed">
- <font supportedAxes="wght,ital">Roboto-Regular.ttf
- <axis tag="wdth" stylevalue="75" />
- </font>
- </family>
- <alias name="sans-serif-condensed-light" to="sans-serif-condensed" weight="300" />
- <alias name="sans-serif-condensed-medium" to="sans-serif-condensed" weight="500" />
-
- <family name="serif">
- <font weight="400" style="normal" postScriptName="NotoSerif">NotoSerif-Regular.ttf</font>
- <font weight="700" style="normal">NotoSerif-Bold.ttf</font>
- <font weight="400" style="italic">NotoSerif-Italic.ttf</font>
- <font weight="700" style="italic">NotoSerif-BoldItalic.ttf</font>
- </family>
- <alias name="serif-bold" to="serif" weight="700" />
- <alias name="times" to="serif" />
- <alias name="times new roman" to="serif" />
- <alias name="palatino" to="serif" />
- <alias name="georgia" to="serif" />
- <alias name="baskerville" to="serif" />
- <alias name="goudy" to="serif" />
- <alias name="fantasy" to="serif" />
- <alias name="ITC Stone Serif" to="serif" />
-
- <family name="monospace">
- <font weight="400" style="normal">DroidSansMono.ttf</font>
- </family>
- <alias name="sans-serif-monospace" to="monospace" />
- <alias name="monaco" to="monospace" />
-
- <family name="serif-monospace">
- <font weight="400" style="normal" postScriptName="CutiveMono-Regular">CutiveMono.ttf</font>
- </family>
- <alias name="courier" to="serif-monospace" />
- <alias name="courier new" to="serif-monospace" />
-
- <family name="casual">
- <font weight="400" style="normal" postScriptName="ComingSoon-Regular">ComingSoon.ttf</font>
- </family>
-
- <family name="cursive">
- <font supportedAxes="wght">DancingScript-Regular.ttf</font>
- </family>
-
- <family name="sans-serif-smallcaps">
- <font weight="400" style="normal">CarroisGothicSC-Regular.ttf</font>
- </family>
-
- <family name="source-sans-pro">
- <font weight="400" style="normal">SourceSansPro-Regular.ttf</font>
- <font weight="400" style="italic">SourceSansPro-Italic.ttf</font>
- <font weight="600" style="normal">SourceSansPro-SemiBold.ttf</font>
- <font weight="600" style="italic">SourceSansPro-SemiBoldItalic.ttf</font>
- <font weight="700" style="normal">SourceSansPro-Bold.ttf</font>
- <font weight="700" style="italic">SourceSansPro-BoldItalic.ttf</font>
- </family>
- <alias name="source-sans-pro-semi-bold" to="source-sans-pro" weight="600"/>
-
- <family name="roboto-flex">
- <font supportedAxes="wght">RobotoFlex-Regular.ttf
- <axis tag="wdth" stylevalue="100" />
- </font>
- </family>
-
- <!-- fallback fonts -->
- <family lang="und-Arab" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoNaskhArabic">
- NotoNaskhArabic-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoNaskhArabic-Bold.ttf</font>
- </family>
- <family lang="und-Arab" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoNaskhArabicUI">
- NotoNaskhArabicUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoNaskhArabicUI-Bold.ttf</font>
- </family>
- <family lang="und-Ethi">
- <font postScriptName="NotoSansEthiopic-Regular" supportedAxes="wght">
- NotoSansEthiopic-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifEthiopic-Regular" supportedAxes="wght">
- NotoSerifEthiopic-VF.ttf
- </font>
- </family>
- <family lang="und-Hebr">
- <font weight="400" style="normal" postScriptName="NotoSansHebrew">
- NotoSansHebrew-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansHebrew-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifHebrew-Regular.ttf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifHebrew-Bold.ttf</font>
- </family>
- <family lang="und-Thai" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansThai">NotoSansThai-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansThai-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">
- NotoSerifThai-Regular.ttf
- </font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifThai-Bold.ttf</font>
- </family>
- <family lang="und-Thai" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansThaiUI">
- NotoSansThaiUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansThaiUI-Bold.ttf</font>
- </family>
- <family lang="und-Armn">
- <font postScriptName="NotoSansArmenian-Regular" supportedAxes="wght">
- NotoSansArmenian-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifArmenian-Regular" supportedAxes="wght">
- NotoSerifArmenian-VF.ttf
- </font>
- </family>
- <family lang="und-Geor,und-Geok">
- <font postScriptName="NotoSansGeorgian-Regular" supportedAxes="wght">
- NotoSansGeorgian-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifGeorgian-Regular" supportedAxes="wght">
- NotoSerifGeorgian-VF.ttf
- </font>
- </family>
- <family lang="und-Deva" variant="elegant">
- <font postScriptName="NotoSansDevanagari-Regular" supportedAxes="wght">
- NotoSansDevanagari-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifDevanagari-Regular" supportedAxes="wght">
- NotoSerifDevanagari-VF.ttf
- </font>
- </family>
- <family lang="und-Deva" variant="compact">
- <font postScriptName="NotoSansDevanagariUI-Regular" supportedAxes="wght">
- NotoSansDevanagariUI-VF.ttf
- </font>
- </family>
-
- <!-- All scripts of India should come after Devanagari, due to shared
- danda characters.
- -->
- <family lang="und-Gujr" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansGujarati">
- NotoSansGujarati-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansGujarati-Bold.ttf</font>
- <font style="normal" fallbackFor="serif" postScriptName="NotoSerifGujarati-Regular"
- supportedAxes="wght">
- NotoSerifGujarati-VF.ttf
- </font>
- </family>
- <family lang="und-Gujr" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansGujaratiUI">
- NotoSansGujaratiUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansGujaratiUI-Bold.ttf</font>
- </family>
- <family lang="und-Guru" variant="elegant">
- <font postScriptName="NotoSansGurmukhi-Regular" supportedAxes="wght">
- NotoSansGurmukhi-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifGurmukhi-Regular" supportedAxes="wght">
- NotoSerifGurmukhi-VF.ttf
- </font>
- </family>
- <family lang="und-Guru" variant="compact">
- <font postScriptName="NotoSansGurmukhiUI-Regular" supportedAxes="wght">
- NotoSansGurmukhiUI-VF.ttf
- </font>
- </family>
- <family lang="und-Taml" variant="elegant">
- <font postScriptName="NotoSansTamil-Regular" supportedAxes="wght">
- NotoSansTamil-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifTamil-Regular" supportedAxes="wght">
- NotoSerifTamil-VF.ttf
- </font>
- </family>
- <family lang="und-Taml" variant="compact">
- <font postScriptName="NotoSansTamilUI-Regular" supportedAxes="wght">
- NotoSansTamilUI-VF.ttf
- </font>
- </family>
- <family lang="und-Mlym" variant="elegant">
- <font postScriptName="NotoSansMalayalam-Regular" supportedAxes="wght">
- NotoSansMalayalam-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifMalayalam-Regular" supportedAxes="wght">
- NotoSerifMalayalam-VF.ttf
- </font>
- </family>
- <family lang="und-Mlym" variant="compact">
- <font postScriptName="NotoSansMalayalamUI-Regular" supportedAxes="wght">
- NotoSansMalayalamUI-VF.ttf
- </font>
- </family>
- <family lang="und-Beng" variant="elegant">
- <font postScriptName="NotoSansBengali-Regular" supportedAxes="wght">
- NotoSansBengali-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifBengali-Regular" supportedAxes="wght">
- NotoSerifBengali-VF.ttf
- </font>
- </family>
- <family lang="und-Beng" variant="compact">
- <font postScriptName="NotoSansBengaliUI-Regular" supportedAxes="wght">
- NotoSansBengaliUI-VF.ttf
- </font>
- </family>
- <family lang="und-Telu" variant="elegant">
- <font postScriptName="NotoSansTelugu-Regular" supportedAxes="wght">
- NotoSansTelugu-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifTelugu-Regular" supportedAxes="wght">
- NotoSerifTelugu-VF.ttf
- </font>
- </family>
- <family lang="und-Telu" variant="compact">
- <font postScriptName="NotoSansTeluguUI-Regular" supportedAxes="wght">
- NotoSansTeluguUI-VF.ttf
- </font>
- </family>
- <family lang="und-Knda" variant="elegant">
- <font postScriptName="NotoSansKannada-Regular" supportedAxes="wght">
- NotoSansKannada-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifKannada-Regular" supportedAxes="wght">
- NotoSerifKannada-VF.ttf
- </font>
- </family>
- <family lang="und-Knda" variant="compact">
- <font postScriptName="NotoSansKannadaUI-Regular" supportedAxes="wght">
- NotoSansKannadaUI-VF.ttf
- </font>
- </family>
- <family lang="und-Orya" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansOriya">NotoSansOriya-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansOriya-Bold.ttf</font>
- </family>
- <family lang="und-Orya" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansOriyaUI">
- NotoSansOriyaUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansOriyaUI-Bold.ttf</font>
- </family>
- <family lang="und-Sinh" variant="elegant">
- <font postScriptName="NotoSansSinhala-Regular" supportedAxes="wght">
- NotoSansSinhala-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifSinhala-Regular" supportedAxes="wght">
- NotoSerifSinhala-VF.ttf
- </font>
- </family>
- <family lang="und-Sinh" variant="compact">
- <font postScriptName="NotoSansSinhalaUI-Regular" supportedAxes="wght">
- NotoSansSinhalaUI-VF.ttf
- </font>
- </family>
- <!-- TODO: NotoSansKhmer uses non-standard wght value, so cannot use auto-adjustment. -->
- <family lang="und-Khmr" variant="elegant">
- <font weight="100" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="26.0"/>
- </font>
- <font weight="200" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="39.0"/>
- </font>
- <font weight="300" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="58.0"/>
- </font>
- <font weight="400" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="90.0"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="108.0"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="128.0"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="151.0"/>
- </font>
- <font weight="800" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="169.0"/>
- </font>
- <font weight="900" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="190.0"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifKhmer-Regular.otf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifKhmer-Bold.otf</font>
- </family>
- <family lang="und-Khmr" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansKhmerUI">
- NotoSansKhmerUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansKhmerUI-Bold.ttf</font>
- </family>
- <family lang="und-Laoo" variant="elegant">
- <font weight="400" style="normal">NotoSansLao-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansLao-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">
- NotoSerifLao-Regular.ttf
- </font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifLao-Bold.ttf</font>
- </family>
- <family lang="und-Laoo" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansLaoUI">NotoSansLaoUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansLaoUI-Bold.ttf</font>
- </family>
- <family lang="und-Mymr" variant="elegant">
- <font weight="400" style="normal">NotoSansMyanmar-Regular.otf</font>
- <font weight="500" style="normal">NotoSansMyanmar-Medium.otf</font>
- <font weight="700" style="normal">NotoSansMyanmar-Bold.otf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifMyanmar-Regular.otf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifMyanmar-Bold.otf</font>
- </family>
- <family lang="und-Mymr" variant="compact">
- <font weight="400" style="normal">NotoSansMyanmarUI-Regular.otf</font>
- <font weight="500" style="normal">NotoSansMyanmarUI-Medium.otf</font>
- <font weight="700" style="normal">NotoSansMyanmarUI-Bold.otf</font>
- </family>
- <family lang="und-Thaa">
- <font weight="400" style="normal" postScriptName="NotoSansThaana">
- NotoSansThaana-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansThaana-Bold.ttf</font>
- </family>
- <family lang="und-Cham">
- <font weight="400" style="normal" postScriptName="NotoSansCham">NotoSansCham-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansCham-Bold.ttf</font>
- </family>
- <family lang="und-Ahom">
- <font weight="400" style="normal">NotoSansAhom-Regular.otf</font>
- </family>
- <family lang="und-Adlm">
- <font postScriptName="NotoSansAdlam-Regular" supportedAxes="wght">
- NotoSansAdlam-VF.ttf
- </font>
- </family>
- <family lang="und-Avst">
- <font weight="400" style="normal" postScriptName="NotoSansAvestan">
- NotoSansAvestan-Regular.ttf
- </font>
- </family>
- <family lang="und-Bali">
- <font weight="400" style="normal" postScriptName="NotoSansBalinese">
- NotoSansBalinese-Regular.ttf
- </font>
- </family>
- <family lang="und-Bamu">
- <font weight="400" style="normal" postScriptName="NotoSansBamum">NotoSansBamum-Regular.ttf
- </font>
- </family>
- <family lang="und-Batk">
- <font weight="400" style="normal" postScriptName="NotoSansBatak">NotoSansBatak-Regular.ttf
- </font>
- </family>
- <family lang="und-Brah">
- <font weight="400" style="normal" postScriptName="NotoSansBrahmi">
- NotoSansBrahmi-Regular.ttf
- </font>
- </family>
- <family lang="und-Bugi">
- <font weight="400" style="normal" postScriptName="NotoSansBuginese">
- NotoSansBuginese-Regular.ttf
- </font>
- </family>
- <family lang="und-Buhd">
- <font weight="400" style="normal" postScriptName="NotoSansBuhid">NotoSansBuhid-Regular.ttf
- </font>
- </family>
- <family lang="und-Cans">
- <font weight="400" style="normal">
- NotoSansCanadianAboriginal-Regular.ttf
- </font>
- </family>
- <family lang="und-Cari">
- <font weight="400" style="normal" postScriptName="NotoSansCarian">
- NotoSansCarian-Regular.ttf
- </font>
- </family>
- <family lang="und-Cakm">
- <font weight="400" style="normal">NotoSansChakma-Regular.otf</font>
- </family>
- <family lang="und-Cher">
- <font weight="400" style="normal">NotoSansCherokee-Regular.ttf</font>
- </family>
- <family lang="und-Copt">
- <font weight="400" style="normal" postScriptName="NotoSansCoptic">
- NotoSansCoptic-Regular.ttf
- </font>
- </family>
- <family lang="und-Xsux">
- <font weight="400" style="normal" postScriptName="NotoSansCuneiform">
- NotoSansCuneiform-Regular.ttf
- </font>
- </family>
- <family lang="und-Cprt">
- <font weight="400" style="normal" postScriptName="NotoSansCypriot">
- NotoSansCypriot-Regular.ttf
- </font>
- </family>
- <family lang="und-Dsrt">
- <font weight="400" style="normal" postScriptName="NotoSansDeseret">
- NotoSansDeseret-Regular.ttf
- </font>
- </family>
- <family lang="und-Egyp">
- <font weight="400" style="normal" postScriptName="NotoSansEgyptianHieroglyphs">
- NotoSansEgyptianHieroglyphs-Regular.ttf
- </font>
- </family>
- <family lang="und-Elba">
- <font weight="400" style="normal">NotoSansElbasan-Regular.otf</font>
- </family>
- <family lang="und-Glag">
- <font weight="400" style="normal" postScriptName="NotoSansGlagolitic">
- NotoSansGlagolitic-Regular.ttf
- </font>
- </family>
- <family lang="und-Goth">
- <font weight="400" style="normal" postScriptName="NotoSansGothic">
- NotoSansGothic-Regular.ttf
- </font>
- </family>
- <family lang="und-Hano">
- <font weight="400" style="normal" postScriptName="NotoSansHanunoo">
- NotoSansHanunoo-Regular.ttf
- </font>
- </family>
- <family lang="und-Armi">
- <font weight="400" style="normal" postScriptName="NotoSansImperialAramaic">
- NotoSansImperialAramaic-Regular.ttf
- </font>
- </family>
- <family lang="und-Phli">
- <font weight="400" style="normal" postScriptName="NotoSansInscriptionalPahlavi">
- NotoSansInscriptionalPahlavi-Regular.ttf
- </font>
- </family>
- <family lang="und-Prti">
- <font weight="400" style="normal" postScriptName="NotoSansInscriptionalParthian">
- NotoSansInscriptionalParthian-Regular.ttf
- </font>
- </family>
- <family lang="und-Java">
- <font weight="400" style="normal">NotoSansJavanese-Regular.otf</font>
- </family>
- <family lang="und-Kthi">
- <font weight="400" style="normal" postScriptName="NotoSansKaithi">
- NotoSansKaithi-Regular.ttf
- </font>
- </family>
- <family lang="und-Kali">
- <font weight="400" style="normal" postScriptName="NotoSansKayahLi">
- NotoSansKayahLi-Regular.ttf
- </font>
- </family>
- <family lang="und-Khar">
- <font weight="400" style="normal" postScriptName="NotoSansKharoshthi">
- NotoSansKharoshthi-Regular.ttf
- </font>
- </family>
- <family lang="und-Lepc">
- <font weight="400" style="normal" postScriptName="NotoSansLepcha">
- NotoSansLepcha-Regular.ttf
- </font>
- </family>
- <family lang="und-Limb">
- <font weight="400" style="normal" postScriptName="NotoSansLimbu">NotoSansLimbu-Regular.ttf
- </font>
- </family>
- <family lang="und-Linb">
- <font weight="400" style="normal" postScriptName="NotoSansLinearB">
- NotoSansLinearB-Regular.ttf
- </font>
- </family>
- <family lang="und-Lisu">
- <font weight="400" style="normal" postScriptName="NotoSansLisu">NotoSansLisu-Regular.ttf
- </font>
- </family>
- <family lang="und-Lyci">
- <font weight="400" style="normal" postScriptName="NotoSansLycian">
- NotoSansLycian-Regular.ttf
- </font>
- </family>
- <family lang="und-Lydi">
- <font weight="400" style="normal" postScriptName="NotoSansLydian">
- NotoSansLydian-Regular.ttf
- </font>
- </family>
- <family lang="und-Mand">
- <font weight="400" style="normal" postScriptName="NotoSansMandaic">
- NotoSansMandaic-Regular.ttf
- </font>
- </family>
- <family lang="und-Mtei">
- <font weight="400" style="normal" postScriptName="NotoSansMeeteiMayek">
- NotoSansMeeteiMayek-Regular.ttf
- </font>
- </family>
- <family lang="und-Talu">
- <font weight="400" style="normal" postScriptName="NotoSansNewTaiLue">
- NotoSansNewTaiLue-Regular.ttf
- </font>
- </family>
- <family lang="und-Nkoo">
- <font weight="400" style="normal" postScriptName="NotoSansNKo">NotoSansNKo-Regular.ttf
- </font>
- </family>
- <family lang="und-Ogam">
- <font weight="400" style="normal" postScriptName="NotoSansOgham">NotoSansOgham-Regular.ttf
- </font>
- </family>
- <family lang="und-Olck">
- <font weight="400" style="normal" postScriptName="NotoSansOlChiki">
- NotoSansOlChiki-Regular.ttf
- </font>
- </family>
- <family lang="und-Ital">
- <font weight="400" style="normal" postScriptName="NotoSansOldItalic">
- NotoSansOldItalic-Regular.ttf
- </font>
- </family>
- <family lang="und-Xpeo">
- <font weight="400" style="normal" postScriptName="NotoSansOldPersian">
- NotoSansOldPersian-Regular.ttf
- </font>
- </family>
- <family lang="und-Sarb">
- <font weight="400" style="normal" postScriptName="NotoSansOldSouthArabian">
- NotoSansOldSouthArabian-Regular.ttf
- </font>
- </family>
- <family lang="und-Orkh">
- <font weight="400" style="normal" postScriptName="NotoSansOldTurkic">
- NotoSansOldTurkic-Regular.ttf
- </font>
- </family>
- <family lang="und-Osge">
- <font weight="400" style="normal">NotoSansOsage-Regular.ttf</font>
- </family>
- <family lang="und-Osma">
- <font weight="400" style="normal" postScriptName="NotoSansOsmanya">
- NotoSansOsmanya-Regular.ttf
- </font>
- </family>
- <family lang="und-Phnx">
- <font weight="400" style="normal" postScriptName="NotoSansPhoenician">
- NotoSansPhoenician-Regular.ttf
- </font>
- </family>
- <family lang="und-Rjng">
- <font weight="400" style="normal" postScriptName="NotoSansRejang">
- NotoSansRejang-Regular.ttf
- </font>
- </family>
- <family lang="und-Runr">
- <font weight="400" style="normal" postScriptName="NotoSansRunic">NotoSansRunic-Regular.ttf
- </font>
- </family>
- <family lang="und-Samr">
- <font weight="400" style="normal" postScriptName="NotoSansSamaritan">
- NotoSansSamaritan-Regular.ttf
- </font>
- </family>
- <family lang="und-Saur">
- <font weight="400" style="normal" postScriptName="NotoSansSaurashtra">
- NotoSansSaurashtra-Regular.ttf
- </font>
- </family>
- <family lang="und-Shaw">
- <font weight="400" style="normal" postScriptName="NotoSansShavian">
- NotoSansShavian-Regular.ttf
- </font>
- </family>
- <family lang="und-Sund">
- <font weight="400" style="normal" postScriptName="NotoSansSundanese">
- NotoSansSundanese-Regular.ttf
- </font>
- </family>
- <family lang="und-Sylo">
- <font weight="400" style="normal" postScriptName="NotoSansSylotiNagri">
- NotoSansSylotiNagri-Regular.ttf
- </font>
- </family>
- <!-- Esrangela should precede Eastern and Western Syriac, since it's our default form. -->
- <family lang="und-Syre">
- <font weight="400" style="normal" postScriptName="NotoSansSyriacEstrangela">
- NotoSansSyriacEstrangela-Regular.ttf
- </font>
- </family>
- <family lang="und-Syrn">
- <font weight="400" style="normal" postScriptName="NotoSansSyriacEastern">
- NotoSansSyriacEastern-Regular.ttf
- </font>
- </family>
- <family lang="und-Syrj">
- <font weight="400" style="normal" postScriptName="NotoSansSyriacWestern">
- NotoSansSyriacWestern-Regular.ttf
- </font>
- </family>
- <family lang="und-Tglg">
- <font weight="400" style="normal" postScriptName="NotoSansTagalog">
- NotoSansTagalog-Regular.ttf
- </font>
- </family>
- <family lang="und-Tagb">
- <font weight="400" style="normal" postScriptName="NotoSansTagbanwa">
- NotoSansTagbanwa-Regular.ttf
- </font>
- </family>
- <family lang="und-Lana">
- <font weight="400" style="normal" postScriptName="NotoSansTaiTham">
- NotoSansTaiTham-Regular.ttf
- </font>
- </family>
- <family lang="und-Tavt">
- <font weight="400" style="normal" postScriptName="NotoSansTaiViet">
- NotoSansTaiViet-Regular.ttf
- </font>
- </family>
- <family lang="und-Tibt">
- <font postScriptName="NotoSerifTibetan-Regular" supportedAxes="wght">
- NotoSerifTibetan-VF.ttf
- </font>
- </family>
- <family lang="und-Tfng">
- <font weight="400" style="normal">NotoSansTifinagh-Regular.otf</font>
- </family>
- <family lang="und-Ugar">
- <font weight="400" style="normal" postScriptName="NotoSansUgaritic">
- NotoSansUgaritic-Regular.ttf
- </font>
- </family>
- <family lang="und-Vaii">
- <font weight="400" style="normal" postScriptName="NotoSansVai">NotoSansVai-Regular.ttf
- </font>
- </family>
- <family>
- <font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted.ttf</font>
- </family>
- <family lang="zh-Hans">
- <font weight="400" style="normal" index="2" postScriptName="NotoSansCJKjp-Regular">
- NotoSansCJK-Regular.ttc
- </font>
- <font weight="400" style="normal" index="2" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <family lang="zh-Hant,zh-Bopo">
- <font weight="400" style="normal" index="3" postScriptName="NotoSansCJKjp-Regular">
- NotoSansCJK-Regular.ttc
- </font>
- <font weight="400" style="normal" index="3" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <family lang="ja">
- <font weight="400" style="normal" index="0" postScriptName="NotoSansCJKjp-Regular">
- NotoSansCJK-Regular.ttc
- </font>
- <font weight="400" style="normal" index="0" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <family lang="ja">
- <font postScriptName="NotoSerifHentaigana-ExtraLight" supportedAxes="wght">
- NotoSerifHentaigana.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- </family>
- <family lang="ko">
- <font weight="400" style="normal" index="1" postScriptName="NotoSansCJKjp-Regular">
- NotoSansCJK-Regular.ttc
- </font>
- <font weight="400" style="normal" index="1" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <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>
- <!--
- Tai Le, Yi, Mongolian, and Phags-pa are intentionally kept last, to make sure they don't
- override the East Asian punctuation for Chinese.
- -->
- <family lang="und-Tale">
- <font weight="400" style="normal" postScriptName="NotoSansTaiLe">NotoSansTaiLe-Regular.ttf
- </font>
- </family>
- <family lang="und-Yiii">
- <font weight="400" style="normal" postScriptName="NotoSansYi">NotoSansYi-Regular.ttf</font>
- </family>
- <family lang="und-Mong">
- <font weight="400" style="normal" postScriptName="NotoSansMongolian">
- NotoSansMongolian-Regular.ttf
- </font>
- </family>
- <family lang="und-Phag">
- <font weight="400" style="normal" postScriptName="NotoSansPhagsPa">
- NotoSansPhagsPa-Regular.ttf
- </font>
- </family>
- <family lang="und-Hluw">
- <font weight="400" style="normal">NotoSansAnatolianHieroglyphs-Regular.otf</font>
- </family>
- <family lang="und-Bass">
- <font weight="400" style="normal">NotoSansBassaVah-Regular.otf</font>
- </family>
- <family lang="und-Bhks">
- <font weight="400" style="normal">NotoSansBhaiksuki-Regular.otf</font>
- </family>
- <family lang="und-Hatr">
- <font weight="400" style="normal">NotoSansHatran-Regular.otf</font>
- </family>
- <family lang="und-Lina">
- <font weight="400" style="normal">NotoSansLinearA-Regular.otf</font>
- </family>
- <family lang="und-Mani">
- <font weight="400" style="normal">NotoSansManichaean-Regular.otf</font>
- </family>
- <family lang="und-Marc">
- <font weight="400" style="normal">NotoSansMarchen-Regular.otf</font>
- </family>
- <family lang="und-Merc">
- <font weight="400" style="normal">NotoSansMeroitic-Regular.otf</font>
- </family>
- <family lang="und-Plrd">
- <font weight="400" style="normal">NotoSansMiao-Regular.otf</font>
- </family>
- <family lang="und-Mroo">
- <font weight="400" style="normal">NotoSansMro-Regular.otf</font>
- </family>
- <family lang="und-Mult">
- <font weight="400" style="normal">NotoSansMultani-Regular.otf</font>
- </family>
- <family lang="und-Nbat">
- <font weight="400" style="normal">NotoSansNabataean-Regular.otf</font>
- </family>
- <family lang="und-Newa">
- <font weight="400" style="normal">NotoSansNewa-Regular.otf</font>
- </family>
- <family lang="und-Narb">
- <font weight="400" style="normal">NotoSansOldNorthArabian-Regular.otf</font>
- </family>
- <family lang="und-Perm">
- <font weight="400" style="normal">NotoSansOldPermic-Regular.otf</font>
- </family>
- <family lang="und-Hmng">
- <font weight="400" style="normal">NotoSansPahawhHmong-Regular.otf</font>
- </family>
- <family lang="und-Palm">
- <font weight="400" style="normal">NotoSansPalmyrene-Regular.otf</font>
- </family>
- <family lang="und-Pauc">
- <font weight="400" style="normal">NotoSansPauCinHau-Regular.otf</font>
- </family>
- <family lang="und-Shrd">
- <font weight="400" style="normal">NotoSansSharada-Regular.otf</font>
- </family>
- <family lang="und-Sora">
- <font weight="400" style="normal">NotoSansSoraSompeng-Regular.otf</font>
- </family>
- <family lang="und-Gong">
- <font weight="400" style="normal">NotoSansGunjalaGondi-Regular.otf</font>
- </family>
- <family lang="und-Rohg">
- <font weight="400" style="normal">NotoSansHanifiRohingya-Regular.otf</font>
- </family>
- <family lang="und-Khoj">
- <font weight="400" style="normal">NotoSansKhojki-Regular.otf</font>
- </family>
- <family lang="und-Gonm">
- <font weight="400" style="normal">NotoSansMasaramGondi-Regular.otf</font>
- </family>
- <family lang="und-Wcho">
- <font weight="400" style="normal">NotoSansWancho-Regular.otf</font>
- </family>
- <family lang="und-Wara">
- <font weight="400" style="normal">NotoSansWarangCiti-Regular.otf</font>
- </family>
- <family lang="und-Gran">
- <font weight="400" style="normal">NotoSansGrantha-Regular.ttf</font>
- </family>
- <family lang="und-Modi">
- <font weight="400" style="normal">NotoSansModi-Regular.ttf</font>
- </family>
- <family lang="und-Dogr">
- <font weight="400" style="normal">NotoSerifDogra-Regular.ttf</font>
- </family>
- <family lang="und-Medf">
- <font postScriptName="NotoSansMedefaidrin-Regular" supportedAxes="wght">
- NotoSansMedefaidrin-VF.ttf
- </font>
- </family>
- <family lang="und-Soyo">
- <font postScriptName="NotoSansSoyombo-Regular" supportedAxes="wght">
- NotoSansSoyombo-VF.ttf
- </font>
- </family>
- <family lang="und-Takr">
- <font postScriptName="NotoSansTakri-Regular" supportedAxes="wght">
- NotoSansTakri-VF.ttf
- </font>
- </family>
- <family lang="und-Hmnp">
- <font postScriptName="NotoSerifHmongNyiakeng-Regular" supportedAxes="wght">
- NotoSerifNyiakengPuachueHmong-VF.ttf
- </font>
- </family>
- <family lang="und-Yezi">
- <font postScriptName="NotoSerifYezidi-Regular" supportedAxes="wght">
- NotoSerifYezidi-VF.ttf
- </font>
- </family>
-</familyset>
diff --git a/data/fonts/font_fallback_cjkvf.xml b/data/fonts/font_fallback_cjkvf.xml
deleted file mode 100644
index 407d704..0000000
--- a/data/fonts/font_fallback_cjkvf.xml
+++ /dev/null
@@ -1,966 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- In this file, all fonts without names are added to the default list.
- Fonts are chosen based on a match: full BCP-47 language tag including
- script, then just language, and finally order (the first font containing
- the glyph).
-
- Order of appearance is also the tiebreaker for weight matching. This is
- the reason why the 900 weights of Roboto precede the 700 weights - we
- prefer the former when an 800 weight is requested. Since bold spans
- effectively add 300 to the weight, this ensures that 900 is the bold
- paired with the 500 weight, ensuring adequate contrast.
-
-
- The font_fallback.xml defines the list of font used by the system.
-
- `familyset` node:
- A `familyset` element must be a root node of the font_fallback.xml. No attributes are allowed
- to `familyset` node.
- The `familyset` node can contains `family` and `alias` nodes. Any other nodes will be ignored.
-
- `family` node:
- A `family` node defines a single font family definition.
- A font family is a set of fonts for drawing text in various styles such as weight, slant.
- There are three types of families, default family, named family and locale fallback family.
-
- The default family is a special family node appeared the first node of the `familyset` node.
- The default family is used as first priority fallback.
- Only `name` attribute can be used for default family node. If the `name` attribute is
- specified, This family will also works as named family.
-
- The named family is a family that has name attribute. The named family defines a new fallback.
- For example, if the name attribute is "serif", it creates serif fallback. Developers can
- access the fallback by using Typeface#create API.
- The named family can not have attribute other than `name` attribute. The `name` attribute
- cannot be empty.
-
- The locale fallback family is a font family that is used for fallback. The fallback family is
- used when the named family or default family cannot be used. The locale fallback family can
- have `lang` attribute and `variant` attribute. The `lang` attribute is an optional comma
- separated BCP-47i language tag. The `variant` is an optional attribute that can be one one
- `element`, `compact`. If a `variant` attribute is not specified, it is treated as default.
-
- `alias` node:
- An `alias` node defines a alias of named family with changing weight offset. An `alias` node
- can have mandatory `name` and `to` attribute and optional `weight` attribute. This `alias`
- defines new fallback that has the name of specified `name` attribute. The fallback list is
- the same to the fallback that of the name specified with `to` attribute. If `weight` attribute
- is specified, the base weight offset is shifted to the specified value. For example, if the
- `weight` is 500, the output text is drawn with 500 of weight.
-
- `font` node:
- A `font` node defines a single font definition. There are two types of fonts, static font and
- variable font.
-
- A static font can have `weight`, `style`, `index` and `postScriptName` attributes. A `weight`
- is a mandatory attribute that defines the weight of the font. Any number between 0 to 1000 is
- valid. A `style` is a mandatory attribute that defines the style of the font. A 'style'
- attribute can be `normal` or `italic`. An `index` is an optional attribute that defines the
- index of the font collection. If this is not specified, it is treated as 0. If the font file
- is not a font collection, this attribute is ignored. A `postScriptName` attribute is an
- optional attribute. A PostScript name is used for identifying target of system font update.
- If this is not specified, the system assumes the filename is same to PostScript name of the
- font file. For example, if the font file is "Roboto-Regular.ttf", the system assume the
- PostScript name of this font is "Roboto-Regular".
-
- A variable font can be only defined for the variable font file. A variable font can have
- `axis` child nodes for specifying axis values. A variable font can have all attribute of
- static font and can have additional `supportedAxes` attribute. A `supportedAxes` attribute
- is a comma separated supported axis tags. As of Android V, only `wght` and `ital` axes can
- be specified.
-
- If `supportedAxes` attribute is not specified, this `font` node works as static font of the
- single instance of variable font specified with `axis` children.
-
- If `supportedAxes` attribute is specified, the system dynamically create font instance for the
- given weight and style value. If `wght` is specified in `supportedAxes` attribute the `weight`
- attribute and `axis` child that has `wght` tag become optional and ignored because it is
- determined by system at runtime. Similarly, if `ital` is specified in `supportedAxes`
- attribute, the `style` attribute and `axis` child that has `ital` tag become optional and
- ignored.
-
- `axis` node:
- An `axis` node defines a font variation value for a tag. An `axis` node can have two mandatory
- attributes, `tag` and `value`. If the font is variable font and the same tag `axis` node is
- specified in `supportedAxes` attribute, the style value works like a default instance.
--->
-<familyset>
- <!-- first font is default -->
- <family name="sans-serif">
- <font supportedAxes="wght,ital">Roboto-Regular.ttf
- <axis tag="wdth" stylevalue="100" />
- </font>
- </family>
-
-
- <!-- Note that aliases must come after the fonts they reference. -->
- <alias name="sans-serif-thin" to="sans-serif" weight="100" />
- <alias name="sans-serif-light" to="sans-serif" weight="300" />
- <alias name="sans-serif-medium" to="sans-serif" weight="500" />
- <alias name="sans-serif-black" to="sans-serif" weight="900" />
- <alias name="arial" to="sans-serif" />
- <alias name="helvetica" to="sans-serif" />
- <alias name="tahoma" to="sans-serif" />
- <alias name="verdana" to="sans-serif" />
-
- <family name="sans-serif-condensed">
- <font supportedAxes="wght,ital">Roboto-Regular.ttf
- <axis tag="wdth" stylevalue="75" />
- </font>
- </family>
- <alias name="sans-serif-condensed-light" to="sans-serif-condensed" weight="300" />
- <alias name="sans-serif-condensed-medium" to="sans-serif-condensed" weight="500" />
-
- <family name="serif">
- <font weight="400" style="normal" postScriptName="NotoSerif">NotoSerif-Regular.ttf</font>
- <font weight="700" style="normal">NotoSerif-Bold.ttf</font>
- <font weight="400" style="italic">NotoSerif-Italic.ttf</font>
- <font weight="700" style="italic">NotoSerif-BoldItalic.ttf</font>
- </family>
- <alias name="serif-bold" to="serif" weight="700" />
- <alias name="times" to="serif" />
- <alias name="times new roman" to="serif" />
- <alias name="palatino" to="serif" />
- <alias name="georgia" to="serif" />
- <alias name="baskerville" to="serif" />
- <alias name="goudy" to="serif" />
- <alias name="fantasy" to="serif" />
- <alias name="ITC Stone Serif" to="serif" />
-
- <family name="monospace">
- <font weight="400" style="normal">DroidSansMono.ttf</font>
- </family>
- <alias name="sans-serif-monospace" to="monospace" />
- <alias name="monaco" to="monospace" />
-
- <family name="serif-monospace">
- <font weight="400" style="normal" postScriptName="CutiveMono-Regular">CutiveMono.ttf</font>
- </family>
- <alias name="courier" to="serif-monospace" />
- <alias name="courier new" to="serif-monospace" />
-
- <family name="casual">
- <font weight="400" style="normal" postScriptName="ComingSoon-Regular">ComingSoon.ttf</font>
- </family>
-
- <family name="cursive">
- <font supportedAxes="wght">DancingScript-Regular.ttf</font>
- </family>
-
- <family name="sans-serif-smallcaps">
- <font weight="400" style="normal">CarroisGothicSC-Regular.ttf</font>
- </family>
-
- <family name="source-sans-pro">
- <font weight="400" style="normal">SourceSansPro-Regular.ttf</font>
- <font weight="400" style="italic">SourceSansPro-Italic.ttf</font>
- <font weight="600" style="normal">SourceSansPro-SemiBold.ttf</font>
- <font weight="600" style="italic">SourceSansPro-SemiBoldItalic.ttf</font>
- <font weight="700" style="normal">SourceSansPro-Bold.ttf</font>
- <font weight="700" style="italic">SourceSansPro-BoldItalic.ttf</font>
- </family>
- <alias name="source-sans-pro-semi-bold" to="source-sans-pro" weight="600"/>
-
- <family name="roboto-flex">
- <font supportedAxes="wght">RobotoFlex-Regular.ttf
- <axis tag="wdth" stylevalue="100" />
- </font>
- </family>
-
- <!-- fallback fonts -->
- <family lang="und-Arab" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoNaskhArabic">
- NotoNaskhArabic-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoNaskhArabic-Bold.ttf</font>
- </family>
- <family lang="und-Arab" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoNaskhArabicUI">
- NotoNaskhArabicUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoNaskhArabicUI-Bold.ttf</font>
- </family>
- <family lang="und-Ethi">
- <font postScriptName="NotoSansEthiopic-Regular" supportedAxes="wght">
- NotoSansEthiopic-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifEthiopic-Regular" supportedAxes="wght">
- NotoSerifEthiopic-VF.ttf
- </font>
- </family>
- <family lang="und-Hebr">
- <font weight="400" style="normal" postScriptName="NotoSansHebrew">
- NotoSansHebrew-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansHebrew-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifHebrew-Regular.ttf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifHebrew-Bold.ttf</font>
- </family>
- <family lang="und-Thai" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansThai">NotoSansThai-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansThai-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">
- NotoSerifThai-Regular.ttf
- </font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifThai-Bold.ttf</font>
- </family>
- <family lang="und-Thai" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansThaiUI">
- NotoSansThaiUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansThaiUI-Bold.ttf</font>
- </family>
- <family lang="und-Armn">
- <font postScriptName="NotoSansArmenian-Regular" supportedAxes="wght">
- NotoSansArmenian-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifArmenian-Regular" supportedAxes="wght">
- NotoSerifArmenian-VF.ttf
- </font>
- </family>
- <family lang="und-Geor,und-Geok">
- <font postScriptName="NotoSansGeorgian-Regular" supportedAxes="wght">
- NotoSansGeorgian-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifGeorgian-Regular" supportedAxes="wght">
- NotoSerifGeorgian-VF.ttf
- </font>
- </family>
- <family lang="und-Deva" variant="elegant">
- <font postScriptName="NotoSansDevanagari-Regular" supportedAxes="wght">
- NotoSansDevanagari-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifDevanagari-Regular" supportedAxes="wght">
- NotoSerifDevanagari-VF.ttf
- </font>
- </family>
- <family lang="und-Deva" variant="compact">
- <font postScriptName="NotoSansDevanagariUI-Regular" supportedAxes="wght">
- NotoSansDevanagariUI-VF.ttf
- </font>
- </family>
-
- <!-- All scripts of India should come after Devanagari, due to shared
- danda characters.
- -->
- <family lang="und-Gujr" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansGujarati">
- NotoSansGujarati-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansGujarati-Bold.ttf</font>
- <font style="normal" fallbackFor="serif" postScriptName="NotoSerifGujarati-Regular"
- supportedAxes="wght">
- NotoSerifGujarati-VF.ttf
- </font>
- </family>
- <family lang="und-Gujr" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansGujaratiUI">
- NotoSansGujaratiUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansGujaratiUI-Bold.ttf</font>
- </family>
- <family lang="und-Guru" variant="elegant">
- <font postScriptName="NotoSansGurmukhi-Regular" supportedAxes="wght">
- NotoSansGurmukhi-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifGurmukhi-Regular" supportedAxes="wght">
- NotoSerifGurmukhi-VF.ttf
- </font>
- </family>
- <family lang="und-Guru" variant="compact">
- <font postScriptName="NotoSansGurmukhiUI-Regular" supportedAxes="wght">
- NotoSansGurmukhiUI-VF.ttf
- </font>
- </family>
- <family lang="und-Taml" variant="elegant">
- <font postScriptName="NotoSansTamil-Regular" supportedAxes="wght">
- NotoSansTamil-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifTamil-Regular" supportedAxes="wght">
- NotoSerifTamil-VF.ttf
- </font>
- </family>
- <family lang="und-Taml" variant="compact">
- <font postScriptName="NotoSansTamilUI-Regular" supportedAxes="wght">
- NotoSansTamilUI-VF.ttf
- </font>
- </family>
- <family lang="und-Mlym" variant="elegant">
- <font postScriptName="NotoSansMalayalam-Regular" supportedAxes="wght">
- NotoSansMalayalam-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifMalayalam-Regular" supportedAxes="wght">
- NotoSerifMalayalam-VF.ttf
- </font>
- </family>
- <family lang="und-Mlym" variant="compact">
- <font postScriptName="NotoSansMalayalamUI-Regular" supportedAxes="wght">
- NotoSansMalayalamUI-VF.ttf
- </font>
- </family>
- <family lang="und-Beng" variant="elegant">
- <font postScriptName="NotoSansBengali-Regular" supportedAxes="wght">
- NotoSansBengali-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifBengali-Regular" supportedAxes="wght">
- NotoSerifBengali-VF.ttf
- </font>
- </family>
- <family lang="und-Beng" variant="compact">
- <font postScriptName="NotoSansBengaliUI-Regular" supportedAxes="wght">
- NotoSansBengaliUI-VF.ttf
- </font>
- </family>
- <family lang="und-Telu" variant="elegant">
- <font postScriptName="NotoSansTelugu-Regular" supportedAxes="wght">
- NotoSansTelugu-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifTelugu-Regular" supportedAxes="wght">
- NotoSerifTelugu-VF.ttf
- </font>
- </family>
- <family lang="und-Telu" variant="compact">
- <font postScriptName="NotoSansTeluguUI-Regular" supportedAxes="wght">
- NotoSansTeluguUI-VF.ttf
- </font>
- </family>
- <family lang="und-Knda" variant="elegant">
- <font postScriptName="NotoSansKannada-Regular" supportedAxes="wght">
- NotoSansKannada-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifKannada-Regular" supportedAxes="wght">
- NotoSerifKannada-VF.ttf
- </font>
- </family>
- <family lang="und-Knda" variant="compact">
- <font postScriptName="NotoSansKannadaUI-Regular" supportedAxes="wght">
- NotoSansKannadaUI-VF.ttf
- </font>
- </family>
- <family lang="und-Orya" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansOriya">NotoSansOriya-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansOriya-Bold.ttf</font>
- </family>
- <family lang="und-Orya" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansOriyaUI">
- NotoSansOriyaUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansOriyaUI-Bold.ttf</font>
- </family>
- <family lang="und-Sinh" variant="elegant">
- <font postScriptName="NotoSansSinhala-Regular" supportedAxes="wght">
- NotoSansSinhala-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifSinhala-Regular" supportedAxes="wght">
- NotoSerifSinhala-VF.ttf
- </font>
- </family>
- <family lang="und-Sinh" variant="compact">
- <font postScriptName="NotoSansSinhalaUI-Regular" supportedAxes="wght">
- NotoSansSinhalaUI-VF.ttf
- </font>
- </family>
- <!-- TODO: NotoSansKhmer uses non-standard wght value, so cannot use auto-adjustment. -->
- <family lang="und-Khmr" variant="elegant">
- <font weight="100" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="26.0"/>
- </font>
- <font weight="200" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="39.0"/>
- </font>
- <font weight="300" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="58.0"/>
- </font>
- <font weight="400" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="90.0"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="108.0"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="128.0"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="151.0"/>
- </font>
- <font weight="800" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="169.0"/>
- </font>
- <font weight="900" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="190.0"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifKhmer-Regular.otf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifKhmer-Bold.otf</font>
- </family>
- <family lang="und-Khmr" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansKhmerUI">
- NotoSansKhmerUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansKhmerUI-Bold.ttf</font>
- </family>
- <family lang="und-Laoo" variant="elegant">
- <font weight="400" style="normal">NotoSansLao-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansLao-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">
- NotoSerifLao-Regular.ttf
- </font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifLao-Bold.ttf</font>
- </family>
- <family lang="und-Laoo" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansLaoUI">NotoSansLaoUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansLaoUI-Bold.ttf</font>
- </family>
- <family lang="und-Mymr" variant="elegant">
- <font weight="400" style="normal">NotoSansMyanmar-Regular.otf</font>
- <font weight="500" style="normal">NotoSansMyanmar-Medium.otf</font>
- <font weight="700" style="normal">NotoSansMyanmar-Bold.otf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifMyanmar-Regular.otf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifMyanmar-Bold.otf</font>
- </family>
- <family lang="und-Mymr" variant="compact">
- <font weight="400" style="normal">NotoSansMyanmarUI-Regular.otf</font>
- <font weight="500" style="normal">NotoSansMyanmarUI-Medium.otf</font>
- <font weight="700" style="normal">NotoSansMyanmarUI-Bold.otf</font>
- </family>
- <family lang="und-Thaa">
- <font weight="400" style="normal" postScriptName="NotoSansThaana">
- NotoSansThaana-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansThaana-Bold.ttf</font>
- </family>
- <family lang="und-Cham">
- <font weight="400" style="normal" postScriptName="NotoSansCham">NotoSansCham-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansCham-Bold.ttf</font>
- </family>
- <family lang="und-Ahom">
- <font weight="400" style="normal">NotoSansAhom-Regular.otf</font>
- </family>
- <family lang="und-Adlm">
- <font postScriptName="NotoSansAdlam-Regular" supportedAxes="wght">
- NotoSansAdlam-VF.ttf
- </font>
- </family>
- <family lang="und-Avst">
- <font weight="400" style="normal" postScriptName="NotoSansAvestan">
- NotoSansAvestan-Regular.ttf
- </font>
- </family>
- <family lang="und-Bali">
- <font weight="400" style="normal" postScriptName="NotoSansBalinese">
- NotoSansBalinese-Regular.ttf
- </font>
- </family>
- <family lang="und-Bamu">
- <font weight="400" style="normal" postScriptName="NotoSansBamum">NotoSansBamum-Regular.ttf
- </font>
- </family>
- <family lang="und-Batk">
- <font weight="400" style="normal" postScriptName="NotoSansBatak">NotoSansBatak-Regular.ttf
- </font>
- </family>
- <family lang="und-Brah">
- <font weight="400" style="normal" postScriptName="NotoSansBrahmi">
- NotoSansBrahmi-Regular.ttf
- </font>
- </family>
- <family lang="und-Bugi">
- <font weight="400" style="normal" postScriptName="NotoSansBuginese">
- NotoSansBuginese-Regular.ttf
- </font>
- </family>
- <family lang="und-Buhd">
- <font weight="400" style="normal" postScriptName="NotoSansBuhid">NotoSansBuhid-Regular.ttf
- </font>
- </family>
- <family lang="und-Cans">
- <font weight="400" style="normal">
- NotoSansCanadianAboriginal-Regular.ttf
- </font>
- </family>
- <family lang="und-Cari">
- <font weight="400" style="normal" postScriptName="NotoSansCarian">
- NotoSansCarian-Regular.ttf
- </font>
- </family>
- <family lang="und-Cakm">
- <font weight="400" style="normal">NotoSansChakma-Regular.otf</font>
- </family>
- <family lang="und-Cher">
- <font weight="400" style="normal">NotoSansCherokee-Regular.ttf</font>
- </family>
- <family lang="und-Copt">
- <font weight="400" style="normal" postScriptName="NotoSansCoptic">
- NotoSansCoptic-Regular.ttf
- </font>
- </family>
- <family lang="und-Xsux">
- <font weight="400" style="normal" postScriptName="NotoSansCuneiform">
- NotoSansCuneiform-Regular.ttf
- </font>
- </family>
- <family lang="und-Cprt">
- <font weight="400" style="normal" postScriptName="NotoSansCypriot">
- NotoSansCypriot-Regular.ttf
- </font>
- </family>
- <family lang="und-Dsrt">
- <font weight="400" style="normal" postScriptName="NotoSansDeseret">
- NotoSansDeseret-Regular.ttf
- </font>
- </family>
- <family lang="und-Egyp">
- <font weight="400" style="normal" postScriptName="NotoSansEgyptianHieroglyphs">
- NotoSansEgyptianHieroglyphs-Regular.ttf
- </font>
- </family>
- <family lang="und-Elba">
- <font weight="400" style="normal">NotoSansElbasan-Regular.otf</font>
- </family>
- <family lang="und-Glag">
- <font weight="400" style="normal" postScriptName="NotoSansGlagolitic">
- NotoSansGlagolitic-Regular.ttf
- </font>
- </family>
- <family lang="und-Goth">
- <font weight="400" style="normal" postScriptName="NotoSansGothic">
- NotoSansGothic-Regular.ttf
- </font>
- </family>
- <family lang="und-Hano">
- <font weight="400" style="normal" postScriptName="NotoSansHanunoo">
- NotoSansHanunoo-Regular.ttf
- </font>
- </family>
- <family lang="und-Armi">
- <font weight="400" style="normal" postScriptName="NotoSansImperialAramaic">
- NotoSansImperialAramaic-Regular.ttf
- </font>
- </family>
- <family lang="und-Phli">
- <font weight="400" style="normal" postScriptName="NotoSansInscriptionalPahlavi">
- NotoSansInscriptionalPahlavi-Regular.ttf
- </font>
- </family>
- <family lang="und-Prti">
- <font weight="400" style="normal" postScriptName="NotoSansInscriptionalParthian">
- NotoSansInscriptionalParthian-Regular.ttf
- </font>
- </family>
- <family lang="und-Java">
- <font weight="400" style="normal">NotoSansJavanese-Regular.otf</font>
- </family>
- <family lang="und-Kthi">
- <font weight="400" style="normal" postScriptName="NotoSansKaithi">
- NotoSansKaithi-Regular.ttf
- </font>
- </family>
- <family lang="und-Kali">
- <font weight="400" style="normal" postScriptName="NotoSansKayahLi">
- NotoSansKayahLi-Regular.ttf
- </font>
- </family>
- <family lang="und-Khar">
- <font weight="400" style="normal" postScriptName="NotoSansKharoshthi">
- NotoSansKharoshthi-Regular.ttf
- </font>
- </family>
- <family lang="und-Lepc">
- <font weight="400" style="normal" postScriptName="NotoSansLepcha">
- NotoSansLepcha-Regular.ttf
- </font>
- </family>
- <family lang="und-Limb">
- <font weight="400" style="normal" postScriptName="NotoSansLimbu">NotoSansLimbu-Regular.ttf
- </font>
- </family>
- <family lang="und-Linb">
- <font weight="400" style="normal" postScriptName="NotoSansLinearB">
- NotoSansLinearB-Regular.ttf
- </font>
- </family>
- <family lang="und-Lisu">
- <font weight="400" style="normal" postScriptName="NotoSansLisu">NotoSansLisu-Regular.ttf
- </font>
- </family>
- <family lang="und-Lyci">
- <font weight="400" style="normal" postScriptName="NotoSansLycian">
- NotoSansLycian-Regular.ttf
- </font>
- </family>
- <family lang="und-Lydi">
- <font weight="400" style="normal" postScriptName="NotoSansLydian">
- NotoSansLydian-Regular.ttf
- </font>
- </family>
- <family lang="und-Mand">
- <font weight="400" style="normal" postScriptName="NotoSansMandaic">
- NotoSansMandaic-Regular.ttf
- </font>
- </family>
- <family lang="und-Mtei">
- <font weight="400" style="normal" postScriptName="NotoSansMeeteiMayek">
- NotoSansMeeteiMayek-Regular.ttf
- </font>
- </family>
- <family lang="und-Talu">
- <font weight="400" style="normal" postScriptName="NotoSansNewTaiLue">
- NotoSansNewTaiLue-Regular.ttf
- </font>
- </family>
- <family lang="und-Nkoo">
- <font weight="400" style="normal" postScriptName="NotoSansNKo">NotoSansNKo-Regular.ttf
- </font>
- </family>
- <family lang="und-Ogam">
- <font weight="400" style="normal" postScriptName="NotoSansOgham">NotoSansOgham-Regular.ttf
- </font>
- </family>
- <family lang="und-Olck">
- <font weight="400" style="normal" postScriptName="NotoSansOlChiki">
- NotoSansOlChiki-Regular.ttf
- </font>
- </family>
- <family lang="und-Ital">
- <font weight="400" style="normal" postScriptName="NotoSansOldItalic">
- NotoSansOldItalic-Regular.ttf
- </font>
- </family>
- <family lang="und-Xpeo">
- <font weight="400" style="normal" postScriptName="NotoSansOldPersian">
- NotoSansOldPersian-Regular.ttf
- </font>
- </family>
- <family lang="und-Sarb">
- <font weight="400" style="normal" postScriptName="NotoSansOldSouthArabian">
- NotoSansOldSouthArabian-Regular.ttf
- </font>
- </family>
- <family lang="und-Orkh">
- <font weight="400" style="normal" postScriptName="NotoSansOldTurkic">
- NotoSansOldTurkic-Regular.ttf
- </font>
- </family>
- <family lang="und-Osge">
- <font weight="400" style="normal">NotoSansOsage-Regular.ttf</font>
- </family>
- <family lang="und-Osma">
- <font weight="400" style="normal" postScriptName="NotoSansOsmanya">
- NotoSansOsmanya-Regular.ttf
- </font>
- </family>
- <family lang="und-Phnx">
- <font weight="400" style="normal" postScriptName="NotoSansPhoenician">
- NotoSansPhoenician-Regular.ttf
- </font>
- </family>
- <family lang="und-Rjng">
- <font weight="400" style="normal" postScriptName="NotoSansRejang">
- NotoSansRejang-Regular.ttf
- </font>
- </family>
- <family lang="und-Runr">
- <font weight="400" style="normal" postScriptName="NotoSansRunic">NotoSansRunic-Regular.ttf
- </font>
- </family>
- <family lang="und-Samr">
- <font weight="400" style="normal" postScriptName="NotoSansSamaritan">
- NotoSansSamaritan-Regular.ttf
- </font>
- </family>
- <family lang="und-Saur">
- <font weight="400" style="normal" postScriptName="NotoSansSaurashtra">
- NotoSansSaurashtra-Regular.ttf
- </font>
- </family>
- <family lang="und-Shaw">
- <font weight="400" style="normal" postScriptName="NotoSansShavian">
- NotoSansShavian-Regular.ttf
- </font>
- </family>
- <family lang="und-Sund">
- <font weight="400" style="normal" postScriptName="NotoSansSundanese">
- NotoSansSundanese-Regular.ttf
- </font>
- </family>
- <family lang="und-Sylo">
- <font weight="400" style="normal" postScriptName="NotoSansSylotiNagri">
- NotoSansSylotiNagri-Regular.ttf
- </font>
- </family>
- <!-- Esrangela should precede Eastern and Western Syriac, since it's our default form. -->
- <family lang="und-Syre">
- <font weight="400" style="normal" postScriptName="NotoSansSyriacEstrangela">
- NotoSansSyriacEstrangela-Regular.ttf
- </font>
- </family>
- <family lang="und-Syrn">
- <font weight="400" style="normal" postScriptName="NotoSansSyriacEastern">
- NotoSansSyriacEastern-Regular.ttf
- </font>
- </family>
- <family lang="und-Syrj">
- <font weight="400" style="normal" postScriptName="NotoSansSyriacWestern">
- NotoSansSyriacWestern-Regular.ttf
- </font>
- </family>
- <family lang="und-Tglg">
- <font weight="400" style="normal" postScriptName="NotoSansTagalog">
- NotoSansTagalog-Regular.ttf
- </font>
- </family>
- <family lang="und-Tagb">
- <font weight="400" style="normal" postScriptName="NotoSansTagbanwa">
- NotoSansTagbanwa-Regular.ttf
- </font>
- </family>
- <family lang="und-Lana">
- <font weight="400" style="normal" postScriptName="NotoSansTaiTham">
- NotoSansTaiTham-Regular.ttf
- </font>
- </family>
- <family lang="und-Tavt">
- <font weight="400" style="normal" postScriptName="NotoSansTaiViet">
- NotoSansTaiViet-Regular.ttf
- </font>
- </family>
- <family lang="und-Tibt">
- <font postScriptName="NotoSerifTibetan-Regular" supportedAxes="wght">
- NotoSerifTibetan-VF.ttf
- </font>
- </family>
- <family lang="und-Tfng">
- <font weight="400" style="normal">NotoSansTifinagh-Regular.otf</font>
- </family>
- <family lang="und-Ugar">
- <font weight="400" style="normal" postScriptName="NotoSansUgaritic">
- NotoSansUgaritic-Regular.ttf
- </font>
- </family>
- <family lang="und-Vaii">
- <font weight="400" style="normal" postScriptName="NotoSansVai">NotoSansVai-Regular.ttf
- </font>
- </family>
- <family>
- <font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted.ttf</font>
- </family>
- <family lang="zh-Hans">
- <font weight="400" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular"
- supportedAxes="wght">
- NotoSansCJK-Regular.ttc
- <!-- The default instance of NotoSansCJK-Regular.ttc is wght=100, so specify wght=400
- for making regular style as default. -->
- <axis tag="wght" stylevalue="400" />
- </font>
- <font weight="400" style="normal" index="2" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <family lang="zh-Hant,zh-Bopo">
- <font weight="400" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular"
- supportedAxes="wght">
- NotoSansCJK-Regular.ttc
- <!-- The default instance of NotoSansCJK-Regular.ttc is wght=100, so specify wght=400
- for making regular style as default. -->
- <axis tag="wght" stylevalue="400" />
- </font>
- <font weight="400" style="normal" index="3" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <family lang="ja">
- <font weight="400" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular"
- supportedAxes="wght">
- NotoSansCJK-Regular.ttc
- <!-- The default instance of NotoSansCJK-Regular.ttc is wght=100, so specify wght=400
- for making regular style as default. -->
- <axis tag="wght" stylevalue="400" />
- </font>
- <font weight="400" style="normal" index="0" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <family lang="ja">
- <font postScriptName="NotoSerifHentaigana-ExtraLight" supportedAxes="wght">
- NotoSerifHentaigana.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- </family>
- <family lang="ko">
- <font weight="400" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular"
- supportedAxes="wght">
- NotoSansCJK-Regular.ttc
- <!-- The default instance of NotoSansCJK-Regular.ttc is wght=100, so specify wght=400
- for making regular style as default. -->
- <axis tag="wght" stylevalue="400" />
- </font>
- <font weight="400" style="normal" index="1" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <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>
- <!--
- Tai Le, Yi, Mongolian, and Phags-pa are intentionally kept last, to make sure they don't
- override the East Asian punctuation for Chinese.
- -->
- <family lang="und-Tale">
- <font weight="400" style="normal" postScriptName="NotoSansTaiLe">NotoSansTaiLe-Regular.ttf
- </font>
- </family>
- <family lang="und-Yiii">
- <font weight="400" style="normal" postScriptName="NotoSansYi">NotoSansYi-Regular.ttf</font>
- </family>
- <family lang="und-Mong">
- <font weight="400" style="normal" postScriptName="NotoSansMongolian">
- NotoSansMongolian-Regular.ttf
- </font>
- </family>
- <family lang="und-Phag">
- <font weight="400" style="normal" postScriptName="NotoSansPhagsPa">
- NotoSansPhagsPa-Regular.ttf
- </font>
- </family>
- <family lang="und-Hluw">
- <font weight="400" style="normal">NotoSansAnatolianHieroglyphs-Regular.otf</font>
- </family>
- <family lang="und-Bass">
- <font weight="400" style="normal">NotoSansBassaVah-Regular.otf</font>
- </family>
- <family lang="und-Bhks">
- <font weight="400" style="normal">NotoSansBhaiksuki-Regular.otf</font>
- </family>
- <family lang="und-Hatr">
- <font weight="400" style="normal">NotoSansHatran-Regular.otf</font>
- </family>
- <family lang="und-Lina">
- <font weight="400" style="normal">NotoSansLinearA-Regular.otf</font>
- </family>
- <family lang="und-Mani">
- <font weight="400" style="normal">NotoSansManichaean-Regular.otf</font>
- </family>
- <family lang="und-Marc">
- <font weight="400" style="normal">NotoSansMarchen-Regular.otf</font>
- </family>
- <family lang="und-Merc">
- <font weight="400" style="normal">NotoSansMeroitic-Regular.otf</font>
- </family>
- <family lang="und-Plrd">
- <font weight="400" style="normal">NotoSansMiao-Regular.otf</font>
- </family>
- <family lang="und-Mroo">
- <font weight="400" style="normal">NotoSansMro-Regular.otf</font>
- </family>
- <family lang="und-Mult">
- <font weight="400" style="normal">NotoSansMultani-Regular.otf</font>
- </family>
- <family lang="und-Nbat">
- <font weight="400" style="normal">NotoSansNabataean-Regular.otf</font>
- </family>
- <family lang="und-Newa">
- <font weight="400" style="normal">NotoSansNewa-Regular.otf</font>
- </family>
- <family lang="und-Narb">
- <font weight="400" style="normal">NotoSansOldNorthArabian-Regular.otf</font>
- </family>
- <family lang="und-Perm">
- <font weight="400" style="normal">NotoSansOldPermic-Regular.otf</font>
- </family>
- <family lang="und-Hmng">
- <font weight="400" style="normal">NotoSansPahawhHmong-Regular.otf</font>
- </family>
- <family lang="und-Palm">
- <font weight="400" style="normal">NotoSansPalmyrene-Regular.otf</font>
- </family>
- <family lang="und-Pauc">
- <font weight="400" style="normal">NotoSansPauCinHau-Regular.otf</font>
- </family>
- <family lang="und-Shrd">
- <font weight="400" style="normal">NotoSansSharada-Regular.otf</font>
- </family>
- <family lang="und-Sora">
- <font weight="400" style="normal">NotoSansSoraSompeng-Regular.otf</font>
- </family>
- <family lang="und-Gong">
- <font weight="400" style="normal">NotoSansGunjalaGondi-Regular.otf</font>
- </family>
- <family lang="und-Rohg">
- <font weight="400" style="normal">NotoSansHanifiRohingya-Regular.otf</font>
- </family>
- <family lang="und-Khoj">
- <font weight="400" style="normal">NotoSansKhojki-Regular.otf</font>
- </family>
- <family lang="und-Gonm">
- <font weight="400" style="normal">NotoSansMasaramGondi-Regular.otf</font>
- </family>
- <family lang="und-Wcho">
- <font weight="400" style="normal">NotoSansWancho-Regular.otf</font>
- </family>
- <family lang="und-Wara">
- <font weight="400" style="normal">NotoSansWarangCiti-Regular.otf</font>
- </family>
- <family lang="und-Gran">
- <font weight="400" style="normal">NotoSansGrantha-Regular.ttf</font>
- </family>
- <family lang="und-Modi">
- <font weight="400" style="normal">NotoSansModi-Regular.ttf</font>
- </family>
- <family lang="und-Dogr">
- <font weight="400" style="normal">NotoSerifDogra-Regular.ttf</font>
- </family>
- <family lang="und-Medf">
- <font postScriptName="NotoSansMedefaidrin-Regular" supportedAxes="wght">
- NotoSansMedefaidrin-VF.ttf
- </font>
- </family>
- <family lang="und-Soyo">
- <font postScriptName="NotoSansSoyombo-Regular" supportedAxes="wght">
- NotoSansSoyombo-VF.ttf
- </font>
- </family>
- <family lang="und-Takr">
- <font postScriptName="NotoSansTakri-Regular" supportedAxes="wght">
- NotoSansTakri-VF.ttf
- </font>
- </family>
- <family lang="und-Hmnp">
- <font postScriptName="NotoSerifHmongNyiakeng-Regular" supportedAxes="wght">
- NotoSerifNyiakengPuachueHmong-VF.ttf
- </font>
- </family>
- <family lang="und-Yezi">
- <font postScriptName="NotoSerifYezidi-Regular" supportedAxes="wght">
- NotoSerifYezidi-VF.ttf
- </font>
- </family>
-</familyset>
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index d1aa8e9..8cbc300 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -1409,24 +1409,123 @@
<font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted.ttf</font>
</family>
<family lang="zh-Hans">
- <font weight="400" style="normal" index="2" postScriptName="NotoSansCJKjp-Regular">
+ <font weight="100" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="100"/>
+ </font>
+ <font weight="200" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="200"/>
+ </font>
+ <font weight="300" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="300"/>
+ </font>
+ <font weight="400" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="700"/>
+ </font>
+ <font weight="800" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="800"/>
+ </font>
+ <font weight="900" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="900"/>
</font>
<font weight="400" style="normal" index="2" fallbackFor="serif"
postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
</font>
</family>
<family lang="zh-Hant,zh-Bopo">
- <font weight="400" style="normal" index="3" postScriptName="NotoSansCJKjp-Regular">
+ <font weight="100" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="100"/>
+ </font>
+ <font weight="200" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="200"/>
+ </font>
+ <font weight="300" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="300"/>
+ </font>
+ <font weight="400" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="700"/>
+ </font>
+ <font weight="800" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="800"/>
+ </font>
+ <font weight="900" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="900"/>
</font>
<font weight="400" style="normal" index="3" fallbackFor="serif"
postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
</font>
</family>
<family lang="ja">
- <font weight="400" style="normal" index="0" postScriptName="NotoSansCJKjp-Regular">
+ <font weight="100" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="100"/>
+ </font>
+ <font weight="200" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="200"/>
+ </font>
+ <font weight="300" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="300"/>
+ </font>
+ <font weight="400" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="700"/>
+ </font>
+ <font weight="800" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="800"/>
+ </font>
+ <font weight="900" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="900"/>
</font>
<font weight="400" style="normal" index="0" fallbackFor="serif"
postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
@@ -1443,8 +1542,41 @@
</font>
</family>
<family lang="ko">
- <font weight="400" style="normal" index="1" postScriptName="NotoSansCJKjp-Regular">
+ <font weight="100" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="100"/>
+ </font>
+ <font weight="200" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="200"/>
+ </font>
+ <font weight="300" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="300"/>
+ </font>
+ <font weight="400" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="700"/>
+ </font>
+ <font weight="800" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="800"/>
+ </font>
+ <font weight="900" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="900"/>
</font>
<font weight="400" style="normal" index="1" fallbackFor="serif"
postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
diff --git a/data/fonts/fonts_cjkvf.xml b/data/fonts/fonts_cjkvf.xml
deleted file mode 100644
index 8cbc300..0000000
--- a/data/fonts/fonts_cjkvf.xml
+++ /dev/null
@@ -1,1795 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- DEPRECATED: This XML file is no longer a source of the font files installed
- in the system.
-
- For the device vendors: please add your font configurations to the
- platform/frameworks/base/data/font_fallback.xml and also add it to this XML
- file as much as possible for apps that reads this XML file.
-
- For the application developers: please stop reading this XML file and use
- android.graphics.fonts.SystemFonts#getAvailableFonts Java API or
- ASystemFontIterator_open NDK API for getting list of system installed
- font files.
-
- WARNING: Parsing of this file by third-party apps is not supported. The
- file, and the font files it refers to, will be renamed and/or moved out
- from their respective location in the next Android release, and/or the
- format or syntax of the file may change significantly. If you parse this
- file for information about system fonts, do it at your own risk. Your
- application will almost certainly break with the next major Android
- release.
-
- In this file, all fonts without names are added to the default list.
- Fonts are chosen based on a match: full BCP-47 language tag including
- script, then just language, and finally order (the first font containing
- the glyph).
-
- Order of appearance is also the tiebreaker for weight matching. This is
- the reason why the 900 weights of Roboto precede the 700 weights - we
- prefer the former when an 800 weight is requested. Since bold spans
- effectively add 300 to the weight, this ensures that 900 is the bold
- paired with the 500 weight, ensuring adequate contrast.
-
- TODO(rsheeter) update comment; ordering to match 800 to 900 is no longer required
--->
-<familyset version="23">
- <!-- first font is default -->
- <family name="sans-serif">
- <font weight="100" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="100" />
- </font>
- <font weight="200" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="200" />
- </font>
- <font weight="300" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="300" />
- </font>
- <font weight="400" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="400" />
- </font>
- <font weight="500" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="500" />
- </font>
- <font weight="600" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="600" />
- </font>
- <font weight="700" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="700" />
- </font>
- <font weight="800" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="800" />
- </font>
- <font weight="900" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="900" />
- </font>
- <font weight="100" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="100" />
- </font>
- <font weight="200" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="200" />
- </font>
- <font weight="300" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="300" />
- </font>
- <font weight="400" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="400" />
- </font>
- <font weight="500" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="500" />
- </font>
- <font weight="600" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="600" />
- </font>
- <font weight="700" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="700" />
- </font>
- <font weight="800" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="800" />
- </font>
- <font weight="900" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="900" />
- </font>
- </family>
-
-
- <!-- Note that aliases must come after the fonts they reference. -->
- <alias name="sans-serif-thin" to="sans-serif" weight="100" />
- <alias name="sans-serif-light" to="sans-serif" weight="300" />
- <alias name="sans-serif-medium" to="sans-serif" weight="500" />
- <alias name="sans-serif-black" to="sans-serif" weight="900" />
- <alias name="arial" to="sans-serif" />
- <alias name="helvetica" to="sans-serif" />
- <alias name="tahoma" to="sans-serif" />
- <alias name="verdana" to="sans-serif" />
-
- <family name="sans-serif-condensed">
- <font weight="100" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="100" />
- </font>
- <font weight="200" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="200" />
- </font>
- <font weight="300" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="300" />
- </font>
- <font weight="400" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="400" />
- </font>
- <font weight="500" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="500" />
- </font>
- <font weight="600" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="600" />
- </font>
- <font weight="700" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="700" />
- </font>
- <font weight="800" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="800" />
- </font>
- <font weight="900" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="900" />
- </font>
- <font weight="100" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="100" />
- </font>
- <font weight="200" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="200" />
- </font>
- <font weight="300" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="300" />
- </font>
- <font weight="400" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="400" />
- </font>
- <font weight="500" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="500" />
- </font>
- <font weight="600" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="600" />
- </font>
- <font weight="700" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="700" />
- </font>
- <font weight="800" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="800" />
- </font>
- <font weight="900" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="900" />
- </font>
- </family>
- <alias name="sans-serif-condensed-light" to="sans-serif-condensed" weight="300" />
- <alias name="sans-serif-condensed-medium" to="sans-serif-condensed" weight="500" />
-
- <family name="serif">
- <font weight="400" style="normal" postScriptName="NotoSerif">NotoSerif-Regular.ttf</font>
- <font weight="700" style="normal">NotoSerif-Bold.ttf</font>
- <font weight="400" style="italic">NotoSerif-Italic.ttf</font>
- <font weight="700" style="italic">NotoSerif-BoldItalic.ttf</font>
- </family>
- <alias name="serif-bold" to="serif" weight="700" />
- <alias name="times" to="serif" />
- <alias name="times new roman" to="serif" />
- <alias name="palatino" to="serif" />
- <alias name="georgia" to="serif" />
- <alias name="baskerville" to="serif" />
- <alias name="goudy" to="serif" />
- <alias name="fantasy" to="serif" />
- <alias name="ITC Stone Serif" to="serif" />
-
- <family name="monospace">
- <font weight="400" style="normal">DroidSansMono.ttf</font>
- </family>
- <alias name="sans-serif-monospace" to="monospace" />
- <alias name="monaco" to="monospace" />
-
- <family name="serif-monospace">
- <font weight="400" style="normal" postScriptName="CutiveMono-Regular">CutiveMono.ttf</font>
- </family>
- <alias name="courier" to="serif-monospace" />
- <alias name="courier new" to="serif-monospace" />
-
- <family name="casual">
- <font weight="400" style="normal" postScriptName="ComingSoon-Regular">ComingSoon.ttf</font>
- </family>
-
- <family name="cursive">
- <font weight="400" style="normal">DancingScript-Regular.ttf
- <axis tag="wght" stylevalue="400" />
- </font>
- <font weight="700" style="normal">DancingScript-Regular.ttf
- <axis tag="wght" stylevalue="700" />
- </font>
- </family>
-
- <family name="sans-serif-smallcaps">
- <font weight="400" style="normal">CarroisGothicSC-Regular.ttf</font>
- </family>
-
- <family name="source-sans-pro">
- <font weight="400" style="normal">SourceSansPro-Regular.ttf</font>
- <font weight="400" style="italic">SourceSansPro-Italic.ttf</font>
- <font weight="600" style="normal">SourceSansPro-SemiBold.ttf</font>
- <font weight="600" style="italic">SourceSansPro-SemiBoldItalic.ttf</font>
- <font weight="700" style="normal">SourceSansPro-Bold.ttf</font>
- <font weight="700" style="italic">SourceSansPro-BoldItalic.ttf</font>
- </family>
- <alias name="source-sans-pro-semi-bold" to="source-sans-pro" weight="600"/>
-
- <family name="roboto-flex">
- <font weight="100" style="normal">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="100" />
- </font>
- <font weight="200" style="normal">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="200" />
- </font>
- <font weight="300" style="normal">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="300" />
- </font>
- <font weight="400" style="normal">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="400" />
- </font>
- <font weight="500" style="normal">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="500" />
- </font>
- <font weight="600" style="normal">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="600" />
- </font>
- <font weight="700" style="normal">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="700" />
- </font>
- <font weight="800" style="normal">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="800" />
- </font>
- <font weight="900" style="normal">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="900" />
- </font>
- <font weight="100" style="italic">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="-10" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="100" />
- </font>
- <font weight="200" style="italic">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="-10" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="200" />
- </font>
- <font weight="300" style="italic">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="-10" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="300" />
- </font>
- <font weight="400" style="italic">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="-10" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="400" />
- </font>
- <font weight="500" style="italic">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="-10" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="500" />
- </font>
- <font weight="600" style="italic">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="-10" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="600" />
- </font>
- <font weight="700" style="italic">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="-10" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="700" />
- </font>
- <font weight="800" style="italic">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="-10" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="800" />
- </font>
- <font weight="900" style="italic">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="-10" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="900" />
- </font>
- </family>
-
- <!-- fallback fonts -->
- <family lang="und-Arab" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoNaskhArabic">
- NotoNaskhArabic-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoNaskhArabic-Bold.ttf</font>
- </family>
- <family lang="und-Arab" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoNaskhArabicUI">
- NotoNaskhArabicUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoNaskhArabicUI-Bold.ttf</font>
- </family>
- <family lang="und-Ethi">
- <font weight="400" style="normal" postScriptName="NotoSansEthiopic-Regular">
- NotoSansEthiopic-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansEthiopic-Regular">
- NotoSansEthiopic-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansEthiopic-Regular">
- NotoSansEthiopic-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansEthiopic-Regular">
- NotoSansEthiopic-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifEthiopic-Regular">NotoSerifEthiopic-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifEthiopic-Regular">NotoSerifEthiopic-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifEthiopic-Regular">NotoSerifEthiopic-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifEthiopic-Regular">NotoSerifEthiopic-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Hebr">
- <font weight="400" style="normal" postScriptName="NotoSansHebrew">
- NotoSansHebrew-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansHebrew-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifHebrew-Regular.ttf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifHebrew-Bold.ttf</font>
- </family>
- <family lang="und-Thai" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansThai">NotoSansThai-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansThai-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">
- NotoSerifThai-Regular.ttf
- </font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifThai-Bold.ttf</font>
- </family>
- <family lang="und-Thai" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansThaiUI">
- NotoSansThaiUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansThaiUI-Bold.ttf</font>
- </family>
- <family lang="und-Armn">
- <font weight="400" style="normal" postScriptName="NotoSansArmenian-Regular">
- NotoSansArmenian-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansArmenian-Regular">
- NotoSansArmenian-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansArmenian-Regular">
- NotoSansArmenian-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansArmenian-Regular">
- NotoSansArmenian-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifArmenian-Regular">NotoSerifArmenian-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifArmenian-Regular">NotoSerifArmenian-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifArmenian-Regular">NotoSerifArmenian-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifArmenian-Regular">NotoSerifArmenian-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Geor,und-Geok">
- <font weight="400" style="normal" postScriptName="NotoSansGeorgian-Regular">
- NotoSansGeorgian-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansGeorgian-Regular">
- NotoSansGeorgian-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansGeorgian-Regular">
- NotoSansGeorgian-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansGeorgian-Regular">
- NotoSansGeorgian-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGeorgian-Regular">NotoSerifGeorgian-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGeorgian-Regular">NotoSerifGeorgian-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGeorgian-Regular">NotoSerifGeorgian-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGeorgian-Regular">NotoSerifGeorgian-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Deva" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansDevanagari-Regular">
- NotoSansDevanagari-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansDevanagari-Regular">
- NotoSansDevanagari-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansDevanagari-Regular">
- NotoSansDevanagari-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansDevanagari-Regular">
- NotoSansDevanagari-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifDevanagari-Regular">NotoSerifDevanagari-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifDevanagari-Regular">NotoSerifDevanagari-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifDevanagari-Regular">NotoSerifDevanagari-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifDevanagari-Regular">NotoSerifDevanagari-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Deva" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansDevanagariUI-Regular">
- NotoSansDevanagariUI-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansDevanagariUI-Regular">
- NotoSansDevanagariUI-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansDevanagariUI-Regular">
- NotoSansDevanagariUI-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansDevanagariUI-Regular">
- NotoSansDevanagariUI-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
-
- <!-- All scripts of India should come after Devanagari, due to shared
- danda characters.
- -->
- <family lang="und-Gujr" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansGujarati">
- NotoSansGujarati-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansGujarati-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGujarati-Regular">NotoSerifGujarati-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGujarati-Regular">NotoSerifGujarati-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGujarati-Regular">NotoSerifGujarati-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGujarati-Regular">NotoSerifGujarati-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Gujr" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansGujaratiUI">
- NotoSansGujaratiUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansGujaratiUI-Bold.ttf</font>
- </family>
- <family lang="und-Guru" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansGurmukhi-Regular">
- NotoSansGurmukhi-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansGurmukhi-Regular">
- NotoSansGurmukhi-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansGurmukhi-Regular">
- NotoSansGurmukhi-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansGurmukhi-Regular">
- NotoSansGurmukhi-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGurmukhi-Regular">NotoSerifGurmukhi-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGurmukhi-Regular">NotoSerifGurmukhi-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGurmukhi-Regular">NotoSerifGurmukhi-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGurmukhi-Regular">NotoSerifGurmukhi-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Guru" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansGurmukhiUI-Regular">
- NotoSansGurmukhiUI-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansGurmukhiUI-Regular">
- NotoSansGurmukhiUI-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansGurmukhiUI-Regular">
- NotoSansGurmukhiUI-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansGurmukhiUI-Regular">
- NotoSansGurmukhiUI-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Taml" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansTamil-Regular">
- NotoSansTamil-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansTamil-Regular">
- NotoSansTamil-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansTamil-Regular">
- NotoSansTamil-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansTamil-Regular">
- NotoSansTamil-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifTamil-Regular">NotoSerifTamil-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifTamil-Regular">NotoSerifTamil-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifTamil-Regular">NotoSerifTamil-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifTamil-Regular">NotoSerifTamil-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Taml" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansTamilUI-Regular">
- NotoSansTamilUI-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansTamilUI-Regular">
- NotoSansTamilUI-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansTamilUI-Regular">
- NotoSansTamilUI-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansTamilUI-Regular">
- NotoSansTamilUI-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Mlym" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansMalayalam-Regular">
- NotoSansMalayalam-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansMalayalam-Regular">
- NotoSansMalayalam-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansMalayalam-Regular">
- NotoSansMalayalam-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansMalayalam-Regular">
- NotoSansMalayalam-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifMalayalam-Regular">NotoSerifMalayalam-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifMalayalam-Regular">NotoSerifMalayalam-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifMalayalam-Regular">NotoSerifMalayalam-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifMalayalam-Regular">NotoSerifMalayalam-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Mlym" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansMalayalamUI-Regular">
- NotoSansMalayalamUI-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansMalayalamUI-Regular">
- NotoSansMalayalamUI-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansMalayalamUI-Regular">
- NotoSansMalayalamUI-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansMalayalamUI-Regular">
- NotoSansMalayalamUI-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Beng" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansBengali-Regular">
- NotoSansBengali-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansBengali-Regular">
- NotoSansBengali-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansBengali-Regular">
- NotoSansBengali-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansBengali-Regular">
- NotoSansBengali-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifBengali-Regular">NotoSerifBengali-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifBengali-Regular">NotoSerifBengali-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifBengali-Regular">NotoSerifBengali-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifBengali-Regular">NotoSerifBengali-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Beng" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansBengaliUI-Regular">
- NotoSansBengaliUI-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansBengaliUI-Regular">
- NotoSansBengaliUI-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansBengaliUI-Regular">
- NotoSansBengaliUI-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansBengaliUI-Regular">
- NotoSansBengaliUI-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Telu" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansTelugu-Regular">
- NotoSansTelugu-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansTelugu-Regular">
- NotoSansTelugu-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansTelugu-Regular">
- NotoSansTelugu-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansTelugu-Regular">
- NotoSansTelugu-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifTelugu-Regular">NotoSerifTelugu-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifTelugu-Regular">NotoSerifTelugu-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifTelugu-Regular">NotoSerifTelugu-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifTelugu-Regular">NotoSerifTelugu-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Telu" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansTeluguUI-Regular">
- NotoSansTeluguUI-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansTeluguUI-Regular">
- NotoSansTeluguUI-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansTeluguUI-Regular">
- NotoSansTeluguUI-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansTeluguUI-Regular">
- NotoSansTeluguUI-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Knda" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansKannada-Regular">
- NotoSansKannada-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansKannada-Regular">
- NotoSansKannada-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansKannada-Regular">
- NotoSansKannada-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansKannada-Regular">
- NotoSansKannada-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifKannada-Regular">NotoSerifKannada-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifKannada-Regular">NotoSerifKannada-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifKannada-Regular">NotoSerifKannada-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifKannada-Regular">NotoSerifKannada-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Knda" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansKannadaUI-Regular">
- NotoSansKannadaUI-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansKannadaUI-Regular">
- NotoSansKannadaUI-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansKannadaUI-Regular">
- NotoSansKannadaUI-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansKannadaUI-Regular">
- NotoSansKannadaUI-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Orya" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansOriya">NotoSansOriya-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansOriya-Bold.ttf</font>
- </family>
- <family lang="und-Orya" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansOriyaUI">
- NotoSansOriyaUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansOriyaUI-Bold.ttf</font>
- </family>
- <family lang="und-Sinh" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansSinhala-Regular">
- NotoSansSinhala-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansSinhala-Regular">
- NotoSansSinhala-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansSinhala-Regular">
- NotoSansSinhala-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansSinhala-Regular">
- NotoSansSinhala-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifSinhala-Regular">NotoSerifSinhala-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifSinhala-Regular">NotoSerifSinhala-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifSinhala-Regular">NotoSerifSinhala-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifSinhala-Regular">NotoSerifSinhala-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Sinh" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansSinhalaUI-Regular">
- NotoSansSinhalaUI-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansSinhalaUI-Regular">
- NotoSansSinhalaUI-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansSinhalaUI-Regular">
- NotoSansSinhalaUI-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansSinhalaUI-Regular">
- NotoSansSinhalaUI-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Khmr" variant="elegant">
- <font weight="100" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="26.0"/>
- </font>
- <font weight="200" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="39.0"/>
- </font>
- <font weight="300" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="58.0"/>
- </font>
- <font weight="400" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="90.0"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="108.0"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="128.0"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="151.0"/>
- </font>
- <font weight="800" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="169.0"/>
- </font>
- <font weight="900" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="190.0"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifKhmer-Regular.otf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifKhmer-Bold.otf</font>
- </family>
- <family lang="und-Khmr" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansKhmerUI">
- NotoSansKhmerUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansKhmerUI-Bold.ttf</font>
- </family>
- <family lang="und-Laoo" variant="elegant">
- <font weight="400" style="normal">NotoSansLao-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansLao-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">
- NotoSerifLao-Regular.ttf
- </font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifLao-Bold.ttf</font>
- </family>
- <family lang="und-Laoo" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansLaoUI">NotoSansLaoUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansLaoUI-Bold.ttf</font>
- </family>
- <family lang="und-Mymr" variant="elegant">
- <font weight="400" style="normal">NotoSansMyanmar-Regular.otf</font>
- <font weight="500" style="normal">NotoSansMyanmar-Medium.otf</font>
- <font weight="700" style="normal">NotoSansMyanmar-Bold.otf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifMyanmar-Regular.otf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifMyanmar-Bold.otf</font>
- </family>
- <family lang="und-Mymr" variant="compact">
- <font weight="400" style="normal">NotoSansMyanmarUI-Regular.otf</font>
- <font weight="500" style="normal">NotoSansMyanmarUI-Medium.otf</font>
- <font weight="700" style="normal">NotoSansMyanmarUI-Bold.otf</font>
- </family>
- <family lang="und-Thaa">
- <font weight="400" style="normal" postScriptName="NotoSansThaana">
- NotoSansThaana-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansThaana-Bold.ttf</font>
- </family>
- <family lang="und-Cham">
- <font weight="400" style="normal" postScriptName="NotoSansCham">NotoSansCham-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansCham-Bold.ttf</font>
- </family>
- <family lang="und-Ahom">
- <font weight="400" style="normal">NotoSansAhom-Regular.otf</font>
- </family>
- <family lang="und-Adlm">
- <font weight="400" style="normal" postScriptName="NotoSansAdlam-Regular">
- NotoSansAdlam-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansAdlam-Regular">
- NotoSansAdlam-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansAdlam-Regular">
- NotoSansAdlam-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansAdlam-Regular">
- NotoSansAdlam-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Avst">
- <font weight="400" style="normal" postScriptName="NotoSansAvestan">
- NotoSansAvestan-Regular.ttf
- </font>
- </family>
- <family lang="und-Bali">
- <font weight="400" style="normal" postScriptName="NotoSansBalinese">
- NotoSansBalinese-Regular.ttf
- </font>
- </family>
- <family lang="und-Bamu">
- <font weight="400" style="normal" postScriptName="NotoSansBamum">NotoSansBamum-Regular.ttf
- </font>
- </family>
- <family lang="und-Batk">
- <font weight="400" style="normal" postScriptName="NotoSansBatak">NotoSansBatak-Regular.ttf
- </font>
- </family>
- <family lang="und-Brah">
- <font weight="400" style="normal" postScriptName="NotoSansBrahmi">
- NotoSansBrahmi-Regular.ttf
- </font>
- </family>
- <family lang="und-Bugi">
- <font weight="400" style="normal" postScriptName="NotoSansBuginese">
- NotoSansBuginese-Regular.ttf
- </font>
- </family>
- <family lang="und-Buhd">
- <font weight="400" style="normal" postScriptName="NotoSansBuhid">NotoSansBuhid-Regular.ttf
- </font>
- </family>
- <family lang="und-Cans">
- <font weight="400" style="normal">
- NotoSansCanadianAboriginal-Regular.ttf
- </font>
- </family>
- <family lang="und-Cari">
- <font weight="400" style="normal" postScriptName="NotoSansCarian">
- NotoSansCarian-Regular.ttf
- </font>
- </family>
- <family lang="und-Cakm">
- <font weight="400" style="normal">NotoSansChakma-Regular.otf</font>
- </family>
- <family lang="und-Cher">
- <font weight="400" style="normal">NotoSansCherokee-Regular.ttf</font>
- </family>
- <family lang="und-Copt">
- <font weight="400" style="normal" postScriptName="NotoSansCoptic">
- NotoSansCoptic-Regular.ttf
- </font>
- </family>
- <family lang="und-Xsux">
- <font weight="400" style="normal" postScriptName="NotoSansCuneiform">
- NotoSansCuneiform-Regular.ttf
- </font>
- </family>
- <family lang="und-Cprt">
- <font weight="400" style="normal" postScriptName="NotoSansCypriot">
- NotoSansCypriot-Regular.ttf
- </font>
- </family>
- <family lang="und-Dsrt">
- <font weight="400" style="normal" postScriptName="NotoSansDeseret">
- NotoSansDeseret-Regular.ttf
- </font>
- </family>
- <family lang="und-Egyp">
- <font weight="400" style="normal" postScriptName="NotoSansEgyptianHieroglyphs">
- NotoSansEgyptianHieroglyphs-Regular.ttf
- </font>
- </family>
- <family lang="und-Elba">
- <font weight="400" style="normal">NotoSansElbasan-Regular.otf</font>
- </family>
- <family lang="und-Glag">
- <font weight="400" style="normal" postScriptName="NotoSansGlagolitic">
- NotoSansGlagolitic-Regular.ttf
- </font>
- </family>
- <family lang="und-Goth">
- <font weight="400" style="normal" postScriptName="NotoSansGothic">
- NotoSansGothic-Regular.ttf
- </font>
- </family>
- <family lang="und-Hano">
- <font weight="400" style="normal" postScriptName="NotoSansHanunoo">
- NotoSansHanunoo-Regular.ttf
- </font>
- </family>
- <family lang="und-Armi">
- <font weight="400" style="normal" postScriptName="NotoSansImperialAramaic">
- NotoSansImperialAramaic-Regular.ttf
- </font>
- </family>
- <family lang="und-Phli">
- <font weight="400" style="normal" postScriptName="NotoSansInscriptionalPahlavi">
- NotoSansInscriptionalPahlavi-Regular.ttf
- </font>
- </family>
- <family lang="und-Prti">
- <font weight="400" style="normal" postScriptName="NotoSansInscriptionalParthian">
- NotoSansInscriptionalParthian-Regular.ttf
- </font>
- </family>
- <family lang="und-Java">
- <font weight="400" style="normal">NotoSansJavanese-Regular.otf</font>
- </family>
- <family lang="und-Kthi">
- <font weight="400" style="normal" postScriptName="NotoSansKaithi">
- NotoSansKaithi-Regular.ttf
- </font>
- </family>
- <family lang="und-Kali">
- <font weight="400" style="normal" postScriptName="NotoSansKayahLi">
- NotoSansKayahLi-Regular.ttf
- </font>
- </family>
- <family lang="und-Khar">
- <font weight="400" style="normal" postScriptName="NotoSansKharoshthi">
- NotoSansKharoshthi-Regular.ttf
- </font>
- </family>
- <family lang="und-Lepc">
- <font weight="400" style="normal" postScriptName="NotoSansLepcha">
- NotoSansLepcha-Regular.ttf
- </font>
- </family>
- <family lang="und-Limb">
- <font weight="400" style="normal" postScriptName="NotoSansLimbu">NotoSansLimbu-Regular.ttf
- </font>
- </family>
- <family lang="und-Linb">
- <font weight="400" style="normal" postScriptName="NotoSansLinearB">
- NotoSansLinearB-Regular.ttf
- </font>
- </family>
- <family lang="und-Lisu">
- <font weight="400" style="normal" postScriptName="NotoSansLisu">NotoSansLisu-Regular.ttf
- </font>
- </family>
- <family lang="und-Lyci">
- <font weight="400" style="normal" postScriptName="NotoSansLycian">
- NotoSansLycian-Regular.ttf
- </font>
- </family>
- <family lang="und-Lydi">
- <font weight="400" style="normal" postScriptName="NotoSansLydian">
- NotoSansLydian-Regular.ttf
- </font>
- </family>
- <family lang="und-Mand">
- <font weight="400" style="normal" postScriptName="NotoSansMandaic">
- NotoSansMandaic-Regular.ttf
- </font>
- </family>
- <family lang="und-Mtei">
- <font weight="400" style="normal" postScriptName="NotoSansMeeteiMayek">
- NotoSansMeeteiMayek-Regular.ttf
- </font>
- </family>
- <family lang="und-Talu">
- <font weight="400" style="normal" postScriptName="NotoSansNewTaiLue">
- NotoSansNewTaiLue-Regular.ttf
- </font>
- </family>
- <family lang="und-Nkoo">
- <font weight="400" style="normal" postScriptName="NotoSansNKo">NotoSansNKo-Regular.ttf
- </font>
- </family>
- <family lang="und-Ogam">
- <font weight="400" style="normal" postScriptName="NotoSansOgham">NotoSansOgham-Regular.ttf
- </font>
- </family>
- <family lang="und-Olck">
- <font weight="400" style="normal" postScriptName="NotoSansOlChiki">
- NotoSansOlChiki-Regular.ttf
- </font>
- </family>
- <family lang="und-Ital">
- <font weight="400" style="normal" postScriptName="NotoSansOldItalic">
- NotoSansOldItalic-Regular.ttf
- </font>
- </family>
- <family lang="und-Xpeo">
- <font weight="400" style="normal" postScriptName="NotoSansOldPersian">
- NotoSansOldPersian-Regular.ttf
- </font>
- </family>
- <family lang="und-Sarb">
- <font weight="400" style="normal" postScriptName="NotoSansOldSouthArabian">
- NotoSansOldSouthArabian-Regular.ttf
- </font>
- </family>
- <family lang="und-Orkh">
- <font weight="400" style="normal" postScriptName="NotoSansOldTurkic">
- NotoSansOldTurkic-Regular.ttf
- </font>
- </family>
- <family lang="und-Osge">
- <font weight="400" style="normal">NotoSansOsage-Regular.ttf</font>
- </family>
- <family lang="und-Osma">
- <font weight="400" style="normal" postScriptName="NotoSansOsmanya">
- NotoSansOsmanya-Regular.ttf
- </font>
- </family>
- <family lang="und-Phnx">
- <font weight="400" style="normal" postScriptName="NotoSansPhoenician">
- NotoSansPhoenician-Regular.ttf
- </font>
- </family>
- <family lang="und-Rjng">
- <font weight="400" style="normal" postScriptName="NotoSansRejang">
- NotoSansRejang-Regular.ttf
- </font>
- </family>
- <family lang="und-Runr">
- <font weight="400" style="normal" postScriptName="NotoSansRunic">NotoSansRunic-Regular.ttf
- </font>
- </family>
- <family lang="und-Samr">
- <font weight="400" style="normal" postScriptName="NotoSansSamaritan">
- NotoSansSamaritan-Regular.ttf
- </font>
- </family>
- <family lang="und-Saur">
- <font weight="400" style="normal" postScriptName="NotoSansSaurashtra">
- NotoSansSaurashtra-Regular.ttf
- </font>
- </family>
- <family lang="und-Shaw">
- <font weight="400" style="normal" postScriptName="NotoSansShavian">
- NotoSansShavian-Regular.ttf
- </font>
- </family>
- <family lang="und-Sund">
- <font weight="400" style="normal" postScriptName="NotoSansSundanese">
- NotoSansSundanese-Regular.ttf
- </font>
- </family>
- <family lang="und-Sylo">
- <font weight="400" style="normal" postScriptName="NotoSansSylotiNagri">
- NotoSansSylotiNagri-Regular.ttf
- </font>
- </family>
- <!-- Esrangela should precede Eastern and Western Syriac, since it's our default form. -->
- <family lang="und-Syre">
- <font weight="400" style="normal" postScriptName="NotoSansSyriacEstrangela">
- NotoSansSyriacEstrangela-Regular.ttf
- </font>
- </family>
- <family lang="und-Syrn">
- <font weight="400" style="normal" postScriptName="NotoSansSyriacEastern">
- NotoSansSyriacEastern-Regular.ttf
- </font>
- </family>
- <family lang="und-Syrj">
- <font weight="400" style="normal" postScriptName="NotoSansSyriacWestern">
- NotoSansSyriacWestern-Regular.ttf
- </font>
- </family>
- <family lang="und-Tglg">
- <font weight="400" style="normal" postScriptName="NotoSansTagalog">
- NotoSansTagalog-Regular.ttf
- </font>
- </family>
- <family lang="und-Tagb">
- <font weight="400" style="normal" postScriptName="NotoSansTagbanwa">
- NotoSansTagbanwa-Regular.ttf
- </font>
- </family>
- <family lang="und-Lana">
- <font weight="400" style="normal" postScriptName="NotoSansTaiTham">
- NotoSansTaiTham-Regular.ttf
- </font>
- </family>
- <family lang="und-Tavt">
- <font weight="400" style="normal" postScriptName="NotoSansTaiViet">
- NotoSansTaiViet-Regular.ttf
- </font>
- </family>
- <family lang="und-Tibt">
- <font weight="400" style="normal" postScriptName="NotoSerifTibetan-Regular">
- NotoSerifTibetan-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSerifTibetan-Regular">
- NotoSerifTibetan-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSerifTibetan-Regular">
- NotoSerifTibetan-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSerifTibetan-Regular">
- NotoSerifTibetan-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Tfng">
- <font weight="400" style="normal">NotoSansTifinagh-Regular.otf</font>
- </family>
- <family lang="und-Ugar">
- <font weight="400" style="normal" postScriptName="NotoSansUgaritic">
- NotoSansUgaritic-Regular.ttf
- </font>
- </family>
- <family lang="und-Vaii">
- <font weight="400" style="normal" postScriptName="NotoSansVai">NotoSansVai-Regular.ttf
- </font>
- </family>
- <family>
- <font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted.ttf</font>
- </family>
- <family lang="zh-Hans">
- <font weight="100" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="100"/>
- </font>
- <font weight="200" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="200"/>
- </font>
- <font weight="300" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="300"/>
- </font>
- <font weight="400" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="800" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="800"/>
- </font>
- <font weight="900" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="900"/>
- </font>
- <font weight="400" style="normal" index="2" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <family lang="zh-Hant,zh-Bopo">
- <font weight="100" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="100"/>
- </font>
- <font weight="200" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="200"/>
- </font>
- <font weight="300" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="300"/>
- </font>
- <font weight="400" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="800" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="800"/>
- </font>
- <font weight="900" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="900"/>
- </font>
- <font weight="400" style="normal" index="3" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <family lang="ja">
- <font weight="100" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="100"/>
- </font>
- <font weight="200" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="200"/>
- </font>
- <font weight="300" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="300"/>
- </font>
- <font weight="400" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="800" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="800"/>
- </font>
- <font weight="900" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="900"/>
- </font>
- <font weight="400" style="normal" index="0" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <family lang="ja">
- <font weight="400" style="normal" postScriptName="NotoSerifHentaigana-ExtraLight">
- NotoSerifHentaigana.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSerifHentaigana-ExtraLight">
- NotoSerifHentaigana.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="ko">
- <font weight="100" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="100"/>
- </font>
- <font weight="200" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="200"/>
- </font>
- <font weight="300" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="300"/>
- </font>
- <font weight="400" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="800" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="800"/>
- </font>
- <font weight="900" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="900"/>
- </font>
- <font weight="400" style="normal" index="1" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <family lang="und-Zsye" ignore="true">
- <font weight="400" style="normal">NotoColorEmojiLegacy.ttf</font>
- </family>
- <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>
- <!--
- Tai Le, Yi, Mongolian, and Phags-pa are intentionally kept last, to make sure they don't
- override the East Asian punctuation for Chinese.
- -->
- <family lang="und-Tale">
- <font weight="400" style="normal" postScriptName="NotoSansTaiLe">NotoSansTaiLe-Regular.ttf
- </font>
- </family>
- <family lang="und-Yiii">
- <font weight="400" style="normal" postScriptName="NotoSansYi">NotoSansYi-Regular.ttf</font>
- </family>
- <family lang="und-Mong">
- <font weight="400" style="normal" postScriptName="NotoSansMongolian">
- NotoSansMongolian-Regular.ttf
- </font>
- </family>
- <family lang="und-Phag">
- <font weight="400" style="normal" postScriptName="NotoSansPhagsPa">
- NotoSansPhagsPa-Regular.ttf
- </font>
- </family>
- <family lang="und-Hluw">
- <font weight="400" style="normal">NotoSansAnatolianHieroglyphs-Regular.otf</font>
- </family>
- <family lang="und-Bass">
- <font weight="400" style="normal">NotoSansBassaVah-Regular.otf</font>
- </family>
- <family lang="und-Bhks">
- <font weight="400" style="normal">NotoSansBhaiksuki-Regular.otf</font>
- </family>
- <family lang="und-Hatr">
- <font weight="400" style="normal">NotoSansHatran-Regular.otf</font>
- </family>
- <family lang="und-Lina">
- <font weight="400" style="normal">NotoSansLinearA-Regular.otf</font>
- </family>
- <family lang="und-Mani">
- <font weight="400" style="normal">NotoSansManichaean-Regular.otf</font>
- </family>
- <family lang="und-Marc">
- <font weight="400" style="normal">NotoSansMarchen-Regular.otf</font>
- </family>
- <family lang="und-Merc">
- <font weight="400" style="normal">NotoSansMeroitic-Regular.otf</font>
- </family>
- <family lang="und-Plrd">
- <font weight="400" style="normal">NotoSansMiao-Regular.otf</font>
- </family>
- <family lang="und-Mroo">
- <font weight="400" style="normal">NotoSansMro-Regular.otf</font>
- </family>
- <family lang="und-Mult">
- <font weight="400" style="normal">NotoSansMultani-Regular.otf</font>
- </family>
- <family lang="und-Nbat">
- <font weight="400" style="normal">NotoSansNabataean-Regular.otf</font>
- </family>
- <family lang="und-Newa">
- <font weight="400" style="normal">NotoSansNewa-Regular.otf</font>
- </family>
- <family lang="und-Narb">
- <font weight="400" style="normal">NotoSansOldNorthArabian-Regular.otf</font>
- </family>
- <family lang="und-Perm">
- <font weight="400" style="normal">NotoSansOldPermic-Regular.otf</font>
- </family>
- <family lang="und-Hmng">
- <font weight="400" style="normal">NotoSansPahawhHmong-Regular.otf</font>
- </family>
- <family lang="und-Palm">
- <font weight="400" style="normal">NotoSansPalmyrene-Regular.otf</font>
- </family>
- <family lang="und-Pauc">
- <font weight="400" style="normal">NotoSansPauCinHau-Regular.otf</font>
- </family>
- <family lang="und-Shrd">
- <font weight="400" style="normal">NotoSansSharada-Regular.otf</font>
- </family>
- <family lang="und-Sora">
- <font weight="400" style="normal">NotoSansSoraSompeng-Regular.otf</font>
- </family>
- <family lang="und-Gong">
- <font weight="400" style="normal">NotoSansGunjalaGondi-Regular.otf</font>
- </family>
- <family lang="und-Rohg">
- <font weight="400" style="normal">NotoSansHanifiRohingya-Regular.otf</font>
- </family>
- <family lang="und-Khoj">
- <font weight="400" style="normal">NotoSansKhojki-Regular.otf</font>
- </family>
- <family lang="und-Gonm">
- <font weight="400" style="normal">NotoSansMasaramGondi-Regular.otf</font>
- </family>
- <family lang="und-Wcho">
- <font weight="400" style="normal">NotoSansWancho-Regular.otf</font>
- </family>
- <family lang="und-Wara">
- <font weight="400" style="normal">NotoSansWarangCiti-Regular.otf</font>
- </family>
- <family lang="und-Gran">
- <font weight="400" style="normal">NotoSansGrantha-Regular.ttf</font>
- </family>
- <family lang="und-Modi">
- <font weight="400" style="normal">NotoSansModi-Regular.ttf</font>
- </family>
- <family lang="und-Dogr">
- <font weight="400" style="normal">NotoSerifDogra-Regular.ttf</font>
- </family>
- <family lang="und-Medf">
- <font weight="400" style="normal" postScriptName="NotoSansMedefaidrin-Regular">
- NotoSansMedefaidrin-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansMedefaidrin-Regular">
- NotoSansMedefaidrin-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansMedefaidrin-Regular">
- NotoSansMedefaidrin-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansMedefaidrin-Regular">
- NotoSansMedefaidrin-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Soyo">
- <font weight="400" style="normal" postScriptName="NotoSansSoyombo-Regular">
- NotoSansSoyombo-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansSoyombo-Regular">
- NotoSansSoyombo-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansSoyombo-Regular">
- NotoSansSoyombo-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansSoyombo-Regular">
- NotoSansSoyombo-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Takr">
- <font weight="400" style="normal" postScriptName="NotoSansTakri-Regular">
- NotoSansTakri-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansTakri-Regular">
- NotoSansTakri-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansTakri-Regular">
- NotoSansTakri-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansTakri-Regular">
- NotoSansTakri-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Hmnp">
- <font weight="400" style="normal" postScriptName="NotoSerifHmongNyiakeng-Regular">
- NotoSerifNyiakengPuachueHmong-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSerifHmongNyiakeng-Regular">
- NotoSerifNyiakengPuachueHmong-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSerifHmongNyiakeng-Regular">
- NotoSerifNyiakengPuachueHmong-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSerifHmongNyiakeng-Regular">
- NotoSerifNyiakengPuachueHmong-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Yezi">
- <font weight="400" style="normal" postScriptName="NotoSerifYezidi-Regular">
- NotoSerifYezidi-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSerifYezidi-Regular">
- NotoSerifYezidi-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSerifYezidi-Regular">
- NotoSerifYezidi-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSerifYezidi-Regular">
- NotoSerifYezidi-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
-</familyset>
diff --git a/keystore/java/android/security/OWNERS b/keystore/java/android/security/OWNERS
index 32759b2..4305286 100644
--- a/keystore/java/android/security/OWNERS
+++ b/keystore/java/android/security/OWNERS
@@ -1,2 +1,2 @@
-per-file *.java,*.aidl = eranm@google.com,pgrafov@google.com,rubinxu@google.com
+per-file *.java,*.aidl = drysdale@google.com,jbires@google.com,pgrafov@google.com,rubinxu@google.com
per-file KeyStoreManager.java = mpgroover@google.com
diff --git a/keystore/tests/OWNERS b/keystore/tests/OWNERS
index 86c31f4..0f94ddc 100644
--- a/keystore/tests/OWNERS
+++ b/keystore/tests/OWNERS
@@ -1,4 +1,7 @@
+# Android HW Trust team
+drysdale@google.com
+jbires@google.com
+
# Android Enterprise security team
-eranm@google.com
pgrafov@google.com
rubinxu@google.com
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java
index 6ad2f08..220fc6f 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java
@@ -54,6 +54,7 @@
@NonNull
private final BackupIdler mBackupIdler = new BackupIdler();
private boolean mBackupIdlerScheduled;
+ private boolean mSaveEmbeddingState = false;
private final List<ParcelableTaskContainerData> mParcelableTaskContainerDataList =
new ArrayList<>();
@@ -71,11 +72,32 @@
}
}
+ void setAutoSaveEmbeddingState(boolean saveEmbeddingState) {
+ if (mSaveEmbeddingState == saveEmbeddingState) {
+ return;
+ }
+
+ Log.i(TAG, "Set save embedding state: " + saveEmbeddingState);
+ mSaveEmbeddingState = saveEmbeddingState;
+ if (!mSaveEmbeddingState) {
+ removeSavedState();
+ return;
+ }
+
+ if (!hasPendingStateToRestore() && !mController.getTaskContainers().isEmpty()) {
+ scheduleBackup();
+ }
+ }
/**
* Schedules a back-up request. It is no-op if there was a request scheduled and not yet
* completed.
*/
void scheduleBackup() {
+ if (!mSaveEmbeddingState) {
+ // TODO(b/289875940): enabled internally for broader testing.
+ return;
+ }
+
if (!mBackupIdlerScheduled) {
mBackupIdlerScheduled = true;
Looper.getMainLooper().getQueue().addIdleHandler(mBackupIdler);
@@ -128,7 +150,6 @@
final List<TaskFragmentInfo> infos = savedState.getParcelableArrayList(
KEY_RESTORE_TASK_FRAGMENTS_INFO, TaskFragmentInfo.class);
for (TaskFragmentInfo info : infos) {
- if (DEBUG) Log.d(TAG, "Retrieved: " + info);
mTaskFragmentInfos.put(info.getFragmentToken(), info);
mPresenter.updateTaskFragmentInfo(info);
}
@@ -140,6 +161,11 @@
if (DEBUG) Log.d(TAG, "Retrieved: " + info);
mTaskFragmentParentInfos.put(info.getTaskId(), info);
}
+
+ if (DEBUG) {
+ Log.d(TAG, "Retrieved task-fragment info: " + infos.size() + ", task info: "
+ + parentInfos.size());
+ }
}
void abortTaskContainerRebuilding(@NonNull WindowContainerTransaction wct) {
@@ -148,7 +174,6 @@
final TaskFragmentInfo info = mTaskFragmentInfos.valueAt(i);
mPresenter.deleteTaskFragment(wct, info.getFragmentToken());
}
-
removeSavedState();
}
@@ -190,6 +215,9 @@
final ArrayMap<String, EmbeddingRule> embeddingRuleMap = new ArrayMap<>();
for (EmbeddingRule rule : rules) {
embeddingRuleMap.put(rule.getTag(), rule);
+ if (DEBUG) {
+ Log.d(TAG, "Tag: " + rule.getTag() + " rule: " + rule);
+ }
}
boolean restoredAny = false;
@@ -201,7 +229,7 @@
// has unknown tag, unable to restore.
if (DEBUG) {
Log.d(TAG, "Rebuilding TaskContainer abort! Unknown Tag. Task#"
- + parcelableTaskContainerData.mTaskId);
+ + parcelableTaskContainerData.mTaskId + ", tags = " + tags);
}
continue;
}
@@ -217,7 +245,7 @@
final TaskContainer taskContainer = new TaskContainer(parcelableTaskContainerData,
mController, mTaskFragmentInfos);
- if (DEBUG) Log.d(TAG, "Created TaskContainer " + taskContainer);
+ if (DEBUG) Log.d(TAG, "Created TaskContainer " + taskContainer.getTaskId());
mController.addTaskContainer(taskContainer.getTaskId(), taskContainer);
for (ParcelableSplitContainerData splitData :
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 3368e2e..60e1a50 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -2886,6 +2886,18 @@
return getActiveSplitForContainer(container) != null;
}
+
+ @Override
+ public void setAutoSaveEmbeddingState(boolean saveEmbeddingState) {
+ if (!Flags.aeBackStackRestore()) {
+ return;
+ }
+
+ synchronized (mLock) {
+ mPresenter.setAutoSaveEmbeddingState(saveEmbeddingState);
+ }
+ }
+
void scheduleBackup() {
synchronized (mLock) {
mPresenter.scheduleBackup();
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index b498ee2..9a2f32e 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -183,6 +183,10 @@
}
}
+ void setAutoSaveEmbeddingState(boolean saveEmbeddingState) {
+ mBackupHelper.setAutoSaveEmbeddingState(saveEmbeddingState);
+ }
+
void scheduleBackup() {
mBackupHelper.scheduleBackup();
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
index b453f1d..6928409 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -48,8 +48,6 @@
import androidx.window.extensions.embedding.SplitAttributes.SplitType.ExpandContainersSplitType;
import androidx.window.extensions.embedding.SplitAttributes.SplitType.RatioSplitType;
-import com.android.window.flags.Flags;
-
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -634,11 +632,7 @@
// pin container.
updateAlwaysOnTopOverlayIfNecessary();
- // TODO(b/289875940): Making backup-restore as an opt-in solution, before the flag goes
- // to next-food.
- if (Flags.aeBackStackRestore()) {
- mSplitController.scheduleBackup();
- }
+ mSplitController.scheduleBackup();
}
private void updateAlwaysOnTopOverlayIfNecessary() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java
index 9ca9b73..4569cf3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java
@@ -26,6 +26,7 @@
import android.view.IRemoteAnimationFinishedCallback;
import android.view.IRemoteAnimationRunner;
import android.view.RemoteAnimationTarget;
+import android.view.SurfaceControl;
import android.window.IBackAnimationRunner;
import android.window.IOnBackInvokedCallback;
@@ -34,6 +35,8 @@
import com.android.internal.jank.InteractionJankMonitor;
import com.android.wm.shell.shared.annotations.ShellMainThread;
+import java.lang.ref.WeakReference;
+
/**
* Used to register the animation callback and runner, it will trigger result if gesture was finish
* before it received IBackAnimationRunner#onAnimationStart, so the controller could continue
@@ -101,6 +104,40 @@
return mCallback;
}
+ private Runnable mFinishedCallback;
+ private RemoteAnimationTarget[] mApps;
+ private IRemoteAnimationFinishedCallback mRemoteCallback;
+
+ private static class RemoteAnimationFinishedStub extends IRemoteAnimationFinishedCallback.Stub {
+ //the binder callback should not hold strong reference to it to avoid memory leak.
+ private WeakReference<BackAnimationRunner> mRunnerRef;
+
+ private RemoteAnimationFinishedStub(BackAnimationRunner runner) {
+ mRunnerRef = new WeakReference<>(runner);
+ }
+
+ @Override
+ public void onAnimationFinished() {
+ BackAnimationRunner runner = mRunnerRef.get();
+ if (runner == null) {
+ return;
+ }
+ if (runner.shouldMonitorCUJ(runner.mApps)) {
+ InteractionJankMonitor.getInstance().end(runner.mCujType);
+ }
+
+ runner.mFinishedCallback.run();
+ for (int i = runner.mApps.length - 1; i >= 0; --i) {
+ SurfaceControl sc = runner.mApps[i].leash;
+ if (sc != null && sc.isValid()) {
+ sc.release();
+ }
+ }
+ runner.mApps = null;
+ runner.mFinishedCallback = null;
+ }
+ }
+
/**
* Called from {@link IBackAnimationRunner}, it will deliver these
* {@link RemoteAnimationTarget}s to the corresponding runner.
@@ -108,16 +145,9 @@
void startAnimation(RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers,
RemoteAnimationTarget[] nonApps, Runnable finishedCallback) {
InteractionJankMonitor interactionJankMonitor = InteractionJankMonitor.getInstance();
- final IRemoteAnimationFinishedCallback callback =
- new IRemoteAnimationFinishedCallback.Stub() {
- @Override
- public void onAnimationFinished() {
- if (shouldMonitorCUJ(apps)) {
- interactionJankMonitor.end(mCujType);
- }
- finishedCallback.run();
- }
- };
+ mFinishedCallback = finishedCallback;
+ mApps = apps;
+ if (mRemoteCallback == null) mRemoteCallback = new RemoteAnimationFinishedStub(this);
mWaitingAnimation = false;
if (shouldMonitorCUJ(apps)) {
interactionJankMonitor.begin(
@@ -125,7 +155,7 @@
}
try {
getRunner().onAnimationStart(TRANSIT_OLD_UNSET, apps, wallpapers,
- nonApps, callback);
+ nonApps, mRemoteCallback);
} catch (RemoteException e) {
Log.w(TAG, "Failed call onAnimationStart", e);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index 09a4481..b505bee 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -422,7 +422,7 @@
interactionJankMonitor.begin(taskSurface, context, handler,
CUJ_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG_HOLD)
dragToDesktopTransitionHandler.startDragToDesktopTransition(
- taskInfo,
+ taskInfo.taskId,
dragToDesktopValueAnimator
)
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt
index 34c2f1e..d7d5519 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt
@@ -109,8 +109,8 @@
* after one of the "end" or "cancel" transitions is merged into this transition.
*/
fun startDragToDesktopTransition(
- taskInfo: RunningTaskInfo,
- dragToDesktopAnimator: MoveToDesktopAnimator
+ taskId: Int,
+ dragToDesktopAnimator: MoveToDesktopAnimator,
) {
if (inProgress) {
ProtoLog.v(
@@ -137,26 +137,23 @@
)
val wct = WindowContainerTransaction()
wct.sendPendingIntent(pendingIntent, launchHomeIntent, Bundle())
- // The home launch done above will result in an attempt to move the task to pip if
- // applicable, resulting in a broken state. Prevent that here.
- wct.setDoNotPip(taskInfo.token)
val startTransitionToken =
transitions.startTransition(TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP, wct, this)
transitionState =
- if (isSplitTask(taskInfo.taskId)) {
+ if (isSplitTask(taskId)) {
val otherTask =
- getOtherSplitTask(taskInfo.taskId)
+ getOtherSplitTask(taskId)
?: throw IllegalStateException("Expected split task to have a counterpart.")
TransitionState.FromSplit(
- draggedTaskId = taskInfo.taskId,
+ draggedTaskId = taskId,
dragAnimator = dragToDesktopAnimator,
startTransitionToken = startTransitionToken,
otherSplitTask = otherTask
)
} else {
TransitionState.FromFullscreen(
- draggedTaskId = taskInfo.taskId,
+ draggedTaskId = taskId,
dragAnimator = dragToDesktopAnimator,
startTransitionToken = startTransitionToken
)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
index b36b1f8..3e6d36c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
@@ -110,12 +110,12 @@
void registerSplitAnimationListener(@NonNull SplitInvocationListener listener,
@NonNull Executor executor);
- /** Called when device waking up finished. */
- void onFinishedWakingUp();
-
/** Called when device starts going to sleep (screen off). */
void onStartedGoingToSleep();
+ /** Called when device wakes up. */
+ void onStartedWakingUp();
+
/** Called when requested to go to fullscreen from the current active split app. */
void goToFullscreenFromSplit();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index a23b576..6398d31 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -471,14 +471,14 @@
mStageCoordinator.onKeyguardStateChanged(visible, occluded);
}
- public void onFinishedWakingUp() {
- mStageCoordinator.onFinishedWakingUp();
- }
-
public void onStartedGoingToSleep() {
mStageCoordinator.onStartedGoingToSleep();
}
+ public void onStartedWakingUp() {
+ mStageCoordinator.onStartedWakingUp();
+ }
+
public void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) {
mStageCoordinator.exitSplitScreenOnHide(exitSplitScreenOnHide);
}
@@ -1084,13 +1084,13 @@
}
@Override
- public void onFinishedWakingUp() {
- mMainExecutor.execute(SplitScreenController.this::onFinishedWakingUp);
+ public void onStartedGoingToSleep() {
+ mMainExecutor.execute(SplitScreenController.this::onStartedGoingToSleep);
}
@Override
- public void onStartedGoingToSleep() {
- mMainExecutor.execute(SplitScreenController.this::onStartedGoingToSleep);
+ public void onStartedWakingUp() {
+ mMainExecutor.execute(SplitScreenController.this::onStartedWakingUp);
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 9239fb7..7893267 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -1138,14 +1138,10 @@
"onKeyguardVisibilityChanged: active=%b occludingTaskRunning=%b",
active, occludingTaskRunning);
setDividerVisibility(!mKeyguardActive, null);
-
- if (active && occludingTaskRunning) {
- dismissSplitKeepingLastActiveStage(EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP);
- }
}
- void onFinishedWakingUp() {
- ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onFinishedWakingUp");
+ void onStartedWakingUp() {
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onStartedWakingUp");
if (mBreakOnNextWake) {
dismissSplitKeepingLastActiveStage(EXIT_REASON_DEVICE_FOLDED);
}
@@ -2431,6 +2427,10 @@
final int transitType = info.getType();
TransitionInfo.Change pipChange = null;
int closingSplitTaskId = -1;
+ // This array tracks if we are sending stages TO_BACK in this transition.
+ // TODO (b/349828130): Update for n apps
+ boolean[] stagesSentToBack = new boolean[2];
+
for (int iC = 0; iC < info.getChanges().size(); ++iC) {
final TransitionInfo.Change change = info.getChanges().get(iC);
if (change.getMode() == TRANSIT_CHANGE
@@ -2498,23 +2498,31 @@
}
continue;
}
+ final int taskId = taskInfo.taskId;
if (isOpeningType(change.getMode())) {
- if (!stage.containsTask(taskInfo.taskId)) {
+ if (!stage.containsTask(taskId)) {
Log.w(TAG, "Expected onTaskAppeared on " + stage + " to have been called"
- + " with " + taskInfo.taskId + " before startAnimation().");
- record.addRecord(stage, true, taskInfo.taskId);
+ + " with " + taskId + " before startAnimation().");
+ record.addRecord(stage, true, taskId);
}
} else if (change.getMode() == TRANSIT_CLOSE) {
- if (stage.containsTask(taskInfo.taskId)) {
- record.addRecord(stage, false, taskInfo.taskId);
+ if (stage.containsTask(taskId)) {
+ record.addRecord(stage, false, taskId);
Log.w(TAG, "Expected onTaskVanished on " + stage + " to have been called"
- + " with " + taskInfo.taskId + " before startAnimation().");
+ + " with " + taskId + " before startAnimation().");
}
}
if (isClosingType(change.getMode()) &&
- getStageOfTask(change.getTaskInfo().taskId) != STAGE_TYPE_UNDEFINED) {
- // If either one of the 2 stages is closing we're assuming we'll break split
- closingSplitTaskId = change.getTaskInfo().taskId;
+ getStageOfTask(taskId) != STAGE_TYPE_UNDEFINED) {
+
+ // Record which stages are getting sent to back
+ if (change.getMode() == TRANSIT_TO_BACK) {
+ stagesSentToBack[getStageOfTask(taskId)] = true;
+ }
+
+ // (For PiP transitions) If either one of the 2 stages is closing we're assuming
+ // we'll break split
+ closingSplitTaskId = taskId;
}
}
@@ -2540,6 +2548,21 @@
return true;
}
+ // If keyguard is active, check to see if we have our TO_BACK transitions in order.
+ // This array should either be all false (no split stages sent to back) or all true
+ // (all stages sent to back). In any other case (which can happen with SHOW_ABOVE_LOCKED
+ // apps) we should break split.
+ if (mKeyguardActive) {
+ boolean isFirstStageSentToBack = stagesSentToBack[0];
+ for (boolean b : stagesSentToBack) {
+ // Compare each boolean to the first one. If any are different, break split.
+ if (b != isFirstStageSentToBack) {
+ dismissSplitKeepingLastActiveStage(EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP);
+ break;
+ }
+ }
+ }
+
final ArraySet<StageTaskListener> dismissStages = record.getShouldDismissedStage();
if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0
|| dismissStages.size() == 1) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt
index 0bd3e08..79e16fe 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt
@@ -607,7 +607,7 @@
)
)
.thenReturn(token)
- handler.startDragToDesktopTransition(task, dragAnimator)
+ handler.startDragToDesktopTransition(task.taskId, dragAnimator)
return token
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index a6e33e5..a252a9d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -320,7 +320,7 @@
assertEquals(mStageCoordinator.mLastActiveStage, STAGE_TYPE_MAIN);
- mStageCoordinator.onFinishedWakingUp();
+ mStageCoordinator.onStartedWakingUp();
verify(mTaskOrganizer).startNewTransition(eq(TRANSIT_SPLIT_DISMISS), notNull());
}
diff --git a/libs/hwui/tests/common/scenes/WindowBlurKawase.cpp b/libs/hwui/tests/common/scenes/WindowBlurKawase.cpp
new file mode 100644
index 0000000..5905b32
--- /dev/null
+++ b/libs/hwui/tests/common/scenes/WindowBlurKawase.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+#include <SkBitmap.h>
+#include <SkBlendMode.h>
+#include <SkCanvas.h>
+#include <SkPaint.h>
+#include <SkRefCnt.h>
+#include <SkRuntimeEffect.h>
+#include <SkSurface.h>
+#include <include/gpu/ganesh/SkSurfaceGanesh.h>
+#include <math.h>
+
+#include "SkImageFilters.h"
+#include "TestSceneBase.h"
+#include "include/gpu/GpuTypes.h" // from Skia
+#include "tests/common/BitmapAllocationTestUtils.h"
+#include "utils/Color.h"
+
+class WindowBlurKawase;
+
+static TestScene::Registrar _WindowBlurKawase(TestScene::Info{
+ "windowblurkawase", "Draws window Kawase blur",
+ TestScene::simpleCreateScene<WindowBlurKawase>});
+
+/**
+ * Simulates the multi-pass Kawase blur algorithm in
+ * frameworks/native/libs/renderengine/skia/filters/WindowBlurKawaseFilter.cpp
+ */
+class WindowBlurKawase : public TestScene {
+private:
+ // Keep in sync with
+ // frameworks/native/libs/renderengine/skia/filters/KawaseBlurFilter.h
+ static constexpr uint32_t kMaxPasses = 4;
+ // Keep in sync with frameworks/native/libs/renderengine/skia/filters/BlurFilter.h
+ static constexpr float kInputScale = 0.25f;
+
+ static constexpr uint32_t kLoopLength = 500;
+ static constexpr uint32_t kMaxBlurRadius = 300;
+ sk_sp<SkRuntimeEffect> mBlurEffect;
+
+ sp<RenderNode> card;
+ sp<RenderNode> contentNode;
+
+public:
+ explicit WindowBlurKawase() {
+ SkString blurString(
+ "uniform shader child;"
+ "uniform float in_blurOffset;"
+
+ "half4 main(float2 xy) {"
+ "half4 c = child.eval(xy);"
+ "c += child.eval(xy + float2(+in_blurOffset, +in_blurOffset));"
+ "c += child.eval(xy + float2(+in_blurOffset, -in_blurOffset));"
+ "c += child.eval(xy + float2(-in_blurOffset, -in_blurOffset));"
+ "c += child.eval(xy + float2(-in_blurOffset, +in_blurOffset));"
+ "return half4(c.rgb * 0.2, 1.0);"
+ "}");
+
+ auto [blurEffect, error] = SkRuntimeEffect::MakeForShader(blurString);
+ if (!blurEffect) {
+ LOG_ALWAYS_FATAL("RuntimeShader error: %s", error.c_str());
+ }
+ mBlurEffect = std::move(blurEffect);
+ }
+
+ void createContent(int width, int height, Canvas& canvas) override {
+ contentNode = TestUtils::createNode(
+ 0, 0, width, height, [width, height](RenderProperties& props, Canvas& canvas) {
+ canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
+ Paint paint;
+ paint.setColor(Color::Red_500);
+ canvas.drawRect(0, 0, width / 2, height / 2, paint);
+ paint.setColor(Color::Blue_500);
+ canvas.drawRect(width / 2, height / 2, width, height, paint);
+ });
+
+ card = TestUtils::createNode(
+ 0, 0, width, height,
+ [this](RenderProperties& props, Canvas& canvas) { blurFrame(canvas, 0); });
+ canvas.drawRenderNode(card.get());
+ }
+
+ void doFrame(int frameNr) override {
+ int curFrame = frameNr % kLoopLength;
+ float blurRadius =
+ (sin((float)curFrame / kLoopLength * M_PI * 2) + 1) * 0.5 * kMaxBlurRadius;
+ TestUtils::recordNode(
+ *card, [this, blurRadius](Canvas& canvas) { blurFrame(canvas, blurRadius); });
+ }
+
+ void blurFrame(Canvas& canvas, float blurRadius) {
+ if (blurRadius == 0) {
+ canvas.drawRenderNode(contentNode.get());
+ return;
+ }
+
+ int width = canvas.width();
+ int height = canvas.height();
+ float tmpRadius = (float)blurRadius / 2.0f;
+ uint32_t numberOfPasses = std::min(kMaxPasses, (uint32_t)ceil(tmpRadius));
+ float radiusByPasses = tmpRadius / (float)numberOfPasses;
+
+ SkRuntimeShaderBuilder blurBuilder(mBlurEffect);
+
+ sp<RenderNode> node = contentNode;
+ for (int i = 0; i < numberOfPasses; i++) {
+ blurBuilder.uniform("in_blurOffset") = radiusByPasses * kInputScale * (i + 1);
+ sk_sp<SkImageFilter> blurFilter =
+ SkImageFilters::RuntimeShader(blurBuilder, radiusByPasses, "child", nullptr);
+ // Also downsample the image in the first pass.
+ float canvasScale = i == 0 ? kInputScale : 1;
+
+ // Apply the blur effect as an image filter.
+ node = TestUtils::createNode(
+ 0, 0, width * kInputScale, height * kInputScale,
+ [node, blurFilter, canvasScale](RenderProperties& props, Canvas& canvas) {
+ props.mutateLayerProperties().setImageFilter(blurFilter.get());
+ canvas.scale(canvasScale, canvasScale);
+ canvas.drawRenderNode(node.get());
+ });
+ }
+
+ // Finally upsample the image to its original size.
+ canvas.scale(1 / kInputScale, 1 / kInputScale);
+ canvas.drawRenderNode(node.get());
+ }
+};
diff --git a/libs/hwui/tests/common/scenes/WindowBlurSkia.cpp b/libs/hwui/tests/common/scenes/WindowBlurSkia.cpp
new file mode 100644
index 0000000..36e6d8f
--- /dev/null
+++ b/libs/hwui/tests/common/scenes/WindowBlurSkia.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+#include <SkBitmap.h>
+#include <SkBlendMode.h>
+#include <SkCanvas.h>
+#include <SkPaint.h>
+#include <SkRefCnt.h>
+#include <SkRuntimeEffect.h>
+#include <SkSurface.h>
+#include <include/gpu/ganesh/SkSurfaceGanesh.h>
+#include <math.h>
+
+#include "SkImageFilters.h"
+#include "TestSceneBase.h"
+#include "include/gpu/GpuTypes.h" // from Skia
+#include "tests/common/BitmapAllocationTestUtils.h"
+#include "utils/Color.h"
+
+class WindowBlurSkia;
+
+static TestScene::Registrar _WindowBlurSkia(TestScene::Info{
+ "windowblurskia", "Draws window Skia blur", TestScene::simpleCreateScene<WindowBlurSkia>});
+
+/**
+ * Simulates the Skia window blur in
+ * frameworks/native/libs/renderengine/skia/filters/GaussianBlurFilter.cpp
+ */
+class WindowBlurSkia : public TestScene {
+private:
+ // Keep in sync with frameworks/native/libs/renderengine/skia/filters/BlurFilter.h
+ static constexpr float kInputScale = 0.25f;
+
+ static constexpr uint32_t kLoopLength = 500;
+ static constexpr uint32_t kMaxBlurRadius = 300;
+
+ sp<RenderNode> card;
+ sp<RenderNode> contentNode;
+
+public:
+ void createContent(int width, int height, Canvas& canvas) override {
+ contentNode = TestUtils::createNode(
+ 0, 0, width, height, [width, height](RenderProperties& props, Canvas& canvas) {
+ canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
+ Paint paint;
+ paint.setColor(Color::Red_500);
+ canvas.drawRect(0, 0, width / 2, height / 2, paint);
+ paint.setColor(Color::Blue_500);
+ canvas.drawRect(width / 2, height / 2, width, height, paint);
+ });
+
+ card = TestUtils::createNode(
+ 0, 0, width, height,
+ [this](RenderProperties& props, Canvas& canvas) { blurFrame(canvas, 0); });
+ canvas.drawRenderNode(card.get());
+ }
+
+ void doFrame(int frameNr) override {
+ int curFrame = frameNr % kLoopLength;
+ float blurRadius =
+ (sin((float)curFrame / kLoopLength * M_PI * 2) + 1) * 0.5 * kMaxBlurRadius;
+ TestUtils::recordNode(
+ *card, [this, blurRadius](Canvas& canvas) { blurFrame(canvas, blurRadius); });
+ }
+
+ void blurFrame(Canvas& canvas, float blurRadius) {
+ if (blurRadius == 0) {
+ canvas.drawRenderNode(contentNode.get());
+ return;
+ }
+
+ int width = canvas.width();
+ int height = canvas.height();
+
+ // Downsample and blur the image with the Skia blur filter.
+ sp<RenderNode> node = contentNode;
+ sk_sp<SkImageFilter> blurFilter =
+ SkImageFilters::Blur(blurRadius, blurRadius, SkTileMode::kClamp, nullptr, nullptr);
+ node = TestUtils::createNode(
+ 0, 0, width * kInputScale, height * kInputScale,
+ [node, blurFilter](RenderProperties& props, Canvas& canvas) {
+ props.mutateLayerProperties().setImageFilter(blurFilter.get());
+ canvas.scale(kInputScale, kInputScale);
+ canvas.drawRenderNode(node.get());
+ });
+
+ // Upsample the image to its original size.
+ canvas.scale(1 / kInputScale, 1 / kInputScale);
+ canvas.drawRenderNode(node.get());
+ }
+};
diff --git a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceTypes.kt b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceTypes.kt
index ad996c7..b64f5dc 100644
--- a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceTypes.kt
+++ b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceTypes.kt
@@ -38,3 +38,11 @@
@StringRes override val title: Int = 0,
@StringRes override val summary: Int = 0,
) : TwoStatePreference
+
+/** A preference that provides a two-state toggleable option that can be used as a main switch. */
+open class MainSwitchPreference
+@JvmOverloads
+constructor(
+ override val key: String,
+ @StringRes override val title: Int = 0,
+) : TwoStatePreference
\ No newline at end of file
diff --git a/packages/SettingsLib/Preference/Android.bp b/packages/SettingsLib/Preference/Android.bp
index bff95ce..fb06be9 100644
--- a/packages/SettingsLib/Preference/Android.bp
+++ b/packages/SettingsLib/Preference/Android.bp
@@ -32,6 +32,7 @@
static_libs: [
"SettingsLibDataStore",
"SettingsLibMetadata",
+ "SettingsLibMainSwitchPreference",
"androidx.annotation_annotation",
"androidx.preference_preference",
"guava",
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindingFactory.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindingFactory.kt
index 4c2e1ba..43f2cb6 100644
--- a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindingFactory.kt
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindingFactory.kt
@@ -16,6 +16,7 @@
package com.android.settingslib.preference
+import com.android.settingslib.metadata.MainSwitchPreference
import com.android.settingslib.metadata.PreferenceGroup
import com.android.settingslib.metadata.PreferenceMetadata
import com.android.settingslib.metadata.SwitchPreference
@@ -36,6 +37,7 @@
is SwitchPreference -> SwitchPreferenceBinding.INSTANCE
is PreferenceGroup -> PreferenceGroupBinding.INSTANCE
is PreferenceScreenCreator -> PreferenceScreenBinding.INSTANCE
+ is MainSwitchPreference -> MainSwitchPreferenceBinding.INSTANCE
else -> DefaultPreferenceBinding
}
}
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindings.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindings.kt
index ede970e..d40a6f6 100644
--- a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindings.kt
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindings.kt
@@ -21,11 +21,13 @@
import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceScreen
import androidx.preference.SwitchPreferenceCompat
+import androidx.preference.TwoStatePreference
import com.android.settingslib.metadata.EXTRA_BINDING_SCREEN_KEY
import com.android.settingslib.metadata.PersistentPreference
import com.android.settingslib.metadata.PreferenceMetadata
import com.android.settingslib.metadata.PreferenceScreenMetadata
import com.android.settingslib.metadata.PreferenceTitleProvider
+import com.android.settingslib.widget.MainSwitchPreference
/** Binding of preference group associated with [PreferenceCategory]. */
interface PreferenceScreenBinding : PreferenceBinding {
@@ -64,23 +66,37 @@
}
}
-/** A boolean value type preference associated with [SwitchPreferenceCompat]. */
-interface SwitchPreferenceBinding : PreferenceBinding {
-
- override fun createWidget(context: Context): Preference = SwitchPreferenceCompat(context)
+/** A boolean value type preference associated with the abstract [TwoStatePreference]. */
+interface TwoStatePreferenceBinding : PreferenceBinding {
override fun bind(preference: Preference, metadata: PreferenceMetadata) {
super.bind(preference, metadata)
(metadata as? PersistentPreference<*>)
?.storage(preference.context)
?.getValue(metadata.key, Boolean::class.javaObjectType)
- ?.let { (preference as SwitchPreferenceCompat).isChecked = it }
+ ?.let { (preference as TwoStatePreference).isChecked = it }
}
+}
+
+/** A boolean value type preference associated with [SwitchPreferenceCompat]. */
+interface SwitchPreferenceBinding : TwoStatePreferenceBinding {
+
+ override fun createWidget(context: Context): Preference = SwitchPreferenceCompat(context)
companion object {
@JvmStatic val INSTANCE = object : SwitchPreferenceBinding {}
}
}
+/** A boolean value type preference associated with [MainSwitchPreference]. */
+interface MainSwitchPreferenceBinding : TwoStatePreferenceBinding {
+
+ override fun createWidget(context: Context): Preference = MainSwitchPreference(context)
+
+ companion object {
+ @JvmStatic val INSTANCE = object : MainSwitchPreferenceBinding {}
+ }
+}
+
/** Default [PreferenceBinding] for [Preference]. */
object DefaultPreferenceBinding : PreferenceBinding
diff --git a/packages/SettingsProvider/Android.bp b/packages/SettingsProvider/Android.bp
index 65b2275..00ae05c 100644
--- a/packages/SettingsProvider/Android.bp
+++ b/packages/SettingsProvider/Android.bp
@@ -76,6 +76,7 @@
"truth",
"Nene",
"Harrier",
+ "bedstead-enterprise",
],
libs: [
"android.test.base.stubs.system",
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java
index e86e727..9cce431 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java
@@ -20,6 +20,9 @@
import static android.provider.Settings.Secure.SYNC_PARENT_SOUNDS;
import static android.provider.Settings.System.RINGTONE;
+import static com.android.bedstead.enterprise.EnterpriseDeviceStateExtensionsKt.workProfile;
+import static com.android.bedstead.multiuser.MultiUserDeviceStateExtensionsKt.secondaryUser;
+
import static com.google.common.truth.Truth.assertThat;
import android.content.pm.PackageManager;
@@ -82,7 +85,7 @@
@RequireFeature(PackageManager.FEATURE_MANAGED_USERS)
@EnsureHasWorkProfile
public void testSettings_workProfile() throws Exception {
- UserReference profile = sDeviceState.workProfile();
+ UserReference profile = workProfile(sDeviceState);
// Settings.Global settings are shared between different users
assertSettingsShared(SPACE_GLOBAL, mPrimaryUser.id(), profile.id());
@@ -96,7 +99,7 @@
@RequireRunOnInitialUser
@EnsureHasSecondaryUser
public void testSettings_secondaryUser() throws Exception {
- UserReference secondaryUser = sDeviceState.secondaryUser();
+ UserReference secondaryUser = secondaryUser(sDeviceState);
// Settings.Global settings are shared between different users
assertSettingsShared(SPACE_GLOBAL, mPrimaryUser.id(), secondaryUser.id());
@@ -223,7 +226,7 @@
@RequireRunOnInitialUser
@EnsureHasSecondaryUser
public void testSettings_stopAndRestartSecondaryUser() throws Exception {
- UserReference secondaryUser = sDeviceState.secondaryUser();
+ UserReference secondaryUser = secondaryUser(sDeviceState);
assertSettingsDifferent(SPACE_SECURE, mPrimaryUser.id(), secondaryUser.id());
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 3c560fd..5f90b39 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -276,8 +276,6 @@
filegroup {
name: "SystemUI-tests-broken-robofiles-compile",
srcs: [
- "tests/src/**/*DeviceOnlyTest.java",
- "tests/src/**/*DeviceOnlyTest.kt",
"tests/src/**/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt",
"tests/src/**/systemui/accessibility/data/repository/AccessibilityQsShortcutsRepositoryImplForDeviceTest.kt",
"tests/src/**/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt",
@@ -293,7 +291,6 @@
"tests/src/**/systemui/keyguard/ResourceTrimmerTest.kt",
"tests/src/**/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt",
"tests/src/**/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt",
- "tests/src/**/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt",
"tests/src/**/systemui/media/controls/ui/controller/MediaHierarchyManagerTest.kt",
"tests/src/**/systemui/mediaprojection/taskswitcher/MediaProjectionTaskSwitcherCoreStartableTest.kt",
"tests/src/**/systemui/media/taptotransfer/receiver/FakeMediaTttChipControllerReceiver.kt",
@@ -303,14 +300,12 @@
"tests/src/**/systemui/screenshot/ActionIntentCreatorTest.kt",
"tests/src/**/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt",
"tests/src/**/systemui/screenshot/TakeScreenshotServiceTest.kt",
- "tests/src/**/systemui/statusbar/commandline/CommandRegistryTest.kt",
"tests/src/**/systemui/statusbar/notification/collection/TargetSdkResolverTest.kt",
"tests/src/**/systemui/statusbar/notification/icon/IconManagerTest.kt",
"tests/src/**/systemui/statusbar/notification/row/BigPictureIconManagerTest.kt",
"tests/src/**/systemui/statusbar/notification/row/NotificationSettingsControllerTest.kt",
"tests/src/**/systemui/statusbar/notification/stack/ui/view/NotificationStatsLoggerTest.kt",
"tests/src/**/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt",
- "tests/src/**/systemui/statusbar/policy/BatteryStateNotifierTest.kt",
"tests/src/**/systemui/statusbar/policy/FlashlightControllerImplTest.kt",
"tests/src/**/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt",
"tests/src/**/systemui/stylus/StylusUsiPowerStartableTest.kt",
@@ -449,27 +444,20 @@
"tests/src/**/systemui/media/dialog/MediaSwitchingControllerTest.java",
"tests/src/**/systemui/navigationbar/views/NavigationBarTest.java",
"tests/src/**/systemui/power/PowerNotificationWarningsTest.java",
- "tests/src/**/systemui/power/PowerUITest.java",
"tests/src/**/systemui/qs/QSFooterViewControllerTest.java",
"tests/src/**/systemui/qs/QSImplTest.java",
- "tests/src/**/systemui/qs/QSSecurityFooterTest.java",
- "tests/src/**/systemui/qs/tileimpl/QSTileImplTest.java",
"tests/src/**/systemui/qs/tiles/QuickAccessWalletTileTest.java",
"tests/src/**/systemui/shade/carrier/ShadeCarrierGroupControllerTest.java",
- "tests/src/**/systemui/shared/plugins/PluginActionManagerTest.java",
- "tests/src/**/systemui/statusbar/CommandQueueTest.java",
- "tests/src/**/systemui/statusbar/connectivity/CallbackHandlerTest.java",
"tests/src/**/systemui/statusbar/connectivity/NetworkControllerBaseTest.java",
- "tests/src/**/systemui/statusbar/KeyguardIndicationControllerTest.java",
- "tests/src/**/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java",
- "tests/src/**/systemui/statusbar/phone/ScrimControllerTest.java",
- "tests/src/**/systemui/statusbar/policy/RotationLockControllerImplTest.java",
- "tests/src/**/systemui/statusbar/policy/SecurityControllerTest.java",
- "tests/src/**/systemui/toast/ToastUITest.java",
"tests/src/**/systemui/statusbar/connectivity/NetworkControllerDataTest.java",
"tests/src/**/systemui/statusbar/connectivity/NetworkControllerEthernetTest.java",
"tests/src/**/systemui/statusbar/connectivity/NetworkControllerSignalTest.java",
"tests/src/**/systemui/statusbar/connectivity/NetworkControllerWifiTest.java",
+ "tests/src/**/systemui/statusbar/KeyguardIndicationControllerTest.java",
+ "tests/src/**/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java",
+ "tests/src/**/systemui/statusbar/phone/ScrimControllerTest.java",
+ "tests/src/**/systemui/statusbar/policy/RotationLockControllerImplTest.java",
+ "tests/src/**/systemui/toast/ToastUITest.java",
],
visibility: ["//visibility:private"],
}
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 0b18110..a984b7d 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -1148,6 +1148,13 @@
}
flag {
+ name: "media_controls_button_media3_placement"
+ namespace: "systemui"
+ description: "Use media3 API for action button placement preferences"
+ bug: "360196209"
+}
+
+flag {
name: "media_controls_drawables_reuse"
namespace: "systemui"
description: "Re-use created media drawables for media controls"
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekbarHapticPluginTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekbarHapticPluginTest.kt
index 855b6d0..587d3d9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekbarHapticPluginTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekbarHapticPluginTest.kt
@@ -20,6 +20,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.haptics.msdl.msdlPlayer
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
import com.android.systemui.statusbar.VibratorHelper
@@ -141,11 +142,7 @@
}
private fun createPlugin() {
- plugin =
- SeekbarHapticPlugin(
- vibratorHelper,
- kosmos.fakeSystemClock,
- )
+ plugin = SeekbarHapticPlugin(vibratorHelper, kosmos.msdlPlayer, kosmos.fakeSystemClock)
}
companion object {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt
index 28f88fe..3467382 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt
@@ -16,16 +16,26 @@
package com.android.systemui.haptics.slider
+import android.os.VibrationAttributes
import android.os.VibrationEffect
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.haptics.fakeVibratorHelper
+import com.android.systemui.haptics.msdl.fakeMSDLPlayer
+import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
import com.android.systemui.util.time.fakeSystemClock
+import com.google.android.msdl.data.model.MSDLToken
+import com.google.android.msdl.domain.InteractionProperties
+import com.google.common.truth.Truth.assertThat
import kotlin.math.max
import kotlin.test.assertEquals
import kotlin.test.assertTrue
+import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -35,6 +45,7 @@
class SliderHapticFeedbackProviderTest : SysuiTestCase() {
private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
private val config = SliderHapticFeedbackConfig()
@@ -44,7 +55,14 @@
private val dragTextureThresholdMillis =
lowTickDuration * config.numberOfLowTicks + config.deltaMillisForDragInterval
private val vibratorHelper = kosmos.fakeVibratorHelper
+ private val msdlPlayer = kosmos.fakeMSDLPlayer
private lateinit var sliderHapticFeedbackProvider: SliderHapticFeedbackProvider
+ private val pipeliningAttributes =
+ VibrationAttributes.Builder()
+ .setUsage(VibrationAttributes.USAGE_TOUCH)
+ .setFlags(VibrationAttributes.FLAG_PIPELINED_EFFECT)
+ .build()
+ private lateinit var dynamicProperties: InteractionProperties.DynamicVibrationScale
@Before
fun setup() {
@@ -54,13 +72,20 @@
sliderHapticFeedbackProvider =
SliderHapticFeedbackProvider(
vibratorHelper,
+ msdlPlayer,
dragVelocityProvider,
config,
kosmos.fakeSystemClock,
)
+ dynamicProperties =
+ InteractionProperties.DynamicVibrationScale(
+ sliderHapticFeedbackProvider.scaleOnEdgeCollision(config.maxVelocityToScale),
+ pipeliningAttributes,
+ )
}
@Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun playHapticAtLowerBookend_playsClick() =
with(kosmos) {
val vibration =
@@ -77,6 +102,18 @@
}
@Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playHapticAtLowerBookend_playsDragThresholdLimitToken() =
+ testScope.runTest {
+ sliderHapticFeedbackProvider.onLowerBookend()
+
+ assertThat(msdlPlayer.latestTokenPlayed)
+ .isEqualTo(MSDLToken.DRAG_THRESHOLD_INDICATOR_LIMIT)
+ assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(dynamicProperties)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun playHapticAtLowerBookend_twoTimes_playsClickOnlyOnce() =
with(kosmos) {
val vibration =
@@ -94,6 +131,20 @@
}
@Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playHapticAtLowerBookend_twoTimes_playsDragThresholdLimitTokenOnlyOnce() =
+ testScope.runTest {
+ sliderHapticFeedbackProvider.onLowerBookend()
+ sliderHapticFeedbackProvider.onLowerBookend()
+
+ assertThat(msdlPlayer.latestTokenPlayed)
+ .isEqualTo(MSDLToken.DRAG_THRESHOLD_INDICATOR_LIMIT)
+ assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(dynamicProperties)
+ assertThat(msdlPlayer.getHistory().size).isEqualTo(1)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun playHapticAtUpperBookend_playsClick() =
with(kosmos) {
val vibration =
@@ -110,6 +161,18 @@
}
@Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playHapticAtUpperBookend_playsDragThresholdLimitToken() =
+ testScope.runTest {
+ sliderHapticFeedbackProvider.onUpperBookend()
+
+ assertThat(msdlPlayer.latestTokenPlayed)
+ .isEqualTo(MSDLToken.DRAG_THRESHOLD_INDICATOR_LIMIT)
+ assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(dynamicProperties)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun playHapticAtUpperBookend_twoTimes_playsClickOnlyOnce() =
with(kosmos) {
val vibration =
@@ -127,6 +190,20 @@
}
@Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playHapticAtUpperBookend_twoTimes_playsDragThresholdLimitTokenOnlyOnce() =
+ testScope.runTest {
+ sliderHapticFeedbackProvider.onUpperBookend()
+ sliderHapticFeedbackProvider.onUpperBookend()
+
+ assertThat(msdlPlayer.latestTokenPlayed)
+ .isEqualTo(MSDLToken.DRAG_THRESHOLD_INDICATOR_LIMIT)
+ assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(dynamicProperties)
+ assertThat(msdlPlayer.getHistory().size).isEqualTo(1)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun playHapticAtProgress_onQuickSuccession_playsLowTicksOnce() =
with(kosmos) {
// GIVEN max velocity and slider progress
@@ -150,6 +227,31 @@
}
@Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playHapticAtProgress_onQuickSuccession_playsContinuousDragTokenOnce() =
+ with(kosmos) {
+ // GIVEN max velocity and slider progress
+ val progress = 1f
+ val expectedScale =
+ sliderHapticFeedbackProvider.scaleOnDragTexture(config.maxVelocityToScale, progress)
+ val expectedProperties =
+ InteractionProperties.DynamicVibrationScale(expectedScale, pipeliningAttributes)
+
+ // GIVEN system running for 1s
+ fakeSystemClock.advanceTime(1000)
+
+ // WHEN two calls to play occur immediately
+ sliderHapticFeedbackProvider.onProgress(progress)
+ sliderHapticFeedbackProvider.onProgress(progress)
+
+ // THEN the correct token plays once
+ assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.DRAG_INDICATOR_CONTINUOUS)
+ assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(expectedProperties)
+ assertThat(msdlPlayer.getHistory().size).isEqualTo(1)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun playHapticAtProgress_beforeNextDragThreshold_playsLowTicksOnce() =
with(kosmos) {
// GIVEN max velocity and a slider progress at half progress
@@ -175,6 +277,41 @@
}
@Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playHapticAtProgress_beforeNextDragThreshold_playsContinousDragTokenOnce() =
+ with(kosmos) {
+ // GIVEN max velocity and a slider progress at half progress
+ val firstProgress = 0.5f
+
+ // Given a second slider progress event smaller than the progress threshold
+ val secondProgress =
+ firstProgress + max(0f, config.deltaProgressForDragThreshold - 0.01f)
+
+ // GIVEN system running for 1s
+ fakeSystemClock.advanceTime(1000)
+
+ // WHEN two calls to play occur with the required threshold separation (time and
+ // progress)
+ sliderHapticFeedbackProvider.onProgress(firstProgress)
+ fakeSystemClock.advanceTime(dragTextureThresholdMillis.toLong())
+ sliderHapticFeedbackProvider.onProgress(secondProgress)
+
+ // THEN Only the first event plays the expected token and propertiesv
+ val expectedProperties =
+ InteractionProperties.DynamicVibrationScale(
+ sliderHapticFeedbackProvider.scaleOnDragTexture(
+ config.maxVelocityToScale,
+ firstProgress,
+ ),
+ pipeliningAttributes,
+ )
+ assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.DRAG_INDICATOR_CONTINUOUS)
+ assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(expectedProperties)
+ assertThat(msdlPlayer.getHistory().size).isEqualTo(1)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun playHapticAtProgress_afterNextDragThreshold_playsLowTicksTwice() =
with(kosmos) {
// GIVEN max velocity and a slider progress at half progress
@@ -200,6 +337,51 @@
}
@Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playHapticAtProgress_afterNextDragThreshold_playsContinuousDragTokenTwice() =
+ with(kosmos) {
+ // GIVEN max velocity and a slider progress at half progress
+ val firstProgress = 0.5f
+
+ // Given a second slider progress event beyond progress threshold
+ val secondProgress = firstProgress + config.deltaProgressForDragThreshold + 0.01f
+
+ // GIVEN system running for 1s
+ fakeSystemClock.advanceTime(1000)
+
+ // WHEN two calls to play occur with the required threshold separation (time and
+ // progress)
+ sliderHapticFeedbackProvider.onProgress(firstProgress)
+ fakeSystemClock.advanceTime(dragTextureThresholdMillis.toLong())
+ sliderHapticFeedbackProvider.onProgress(secondProgress)
+
+ // THEN the correct token plays twice with the correct properties
+ val firstProperties =
+ InteractionProperties.DynamicVibrationScale(
+ sliderHapticFeedbackProvider.scaleOnDragTexture(
+ config.maxVelocityToScale,
+ firstProgress,
+ ),
+ pipeliningAttributes,
+ )
+ val secondProperties =
+ InteractionProperties.DynamicVibrationScale(
+ sliderHapticFeedbackProvider.scaleOnDragTexture(
+ config.maxVelocityToScale,
+ secondProgress,
+ ),
+ pipeliningAttributes,
+ )
+
+ assertThat(msdlPlayer.getHistory().size).isEqualTo(2)
+ assertThat(msdlPlayer.tokensPlayed[0]).isEqualTo(MSDLToken.DRAG_INDICATOR_CONTINUOUS)
+ assertThat(msdlPlayer.propertiesPlayed[0]).isEqualTo(firstProperties)
+ assertThat(msdlPlayer.tokensPlayed[1]).isEqualTo(MSDLToken.DRAG_INDICATOR_CONTINUOUS)
+ assertThat(msdlPlayer.propertiesPlayed[1]).isEqualTo(secondProperties)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun playHapticAtLowerBookend_afterPlayingAtProgress_playsTwice() =
with(kosmos) {
// GIVEN max velocity and slider progress
@@ -233,6 +415,36 @@
}
@Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playHapticAtLowerBookend_afterPlayingAtProgress_playsTokensTwice() =
+ with(kosmos) {
+ // GIVEN max velocity and slider progress
+ val progress = 1f
+ val expectedProperties =
+ InteractionProperties.DynamicVibrationScale(
+ sliderHapticFeedbackProvider.scaleOnEdgeCollision(config.maxVelocityToScale),
+ pipeliningAttributes,
+ )
+
+ // GIVEN a vibration at the lower bookend followed by a request to vibrate at progress
+ sliderHapticFeedbackProvider.onLowerBookend()
+ sliderHapticFeedbackProvider.onProgress(progress)
+
+ // WHEN a vibration is to trigger again at the lower bookend
+ sliderHapticFeedbackProvider.onLowerBookend()
+
+ // THEN there are two bookend token vibrations
+ assertThat(msdlPlayer.getHistory().size).isEqualTo(2)
+ assertThat(msdlPlayer.tokensPlayed[0])
+ .isEqualTo(MSDLToken.DRAG_THRESHOLD_INDICATOR_LIMIT)
+ assertThat(msdlPlayer.propertiesPlayed[0]).isEqualTo(expectedProperties)
+ assertThat(msdlPlayer.tokensPlayed[1])
+ .isEqualTo(MSDLToken.DRAG_THRESHOLD_INDICATOR_LIMIT)
+ assertThat(msdlPlayer.propertiesPlayed[1]).isEqualTo(expectedProperties)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun playHapticAtUpperBookend_afterPlayingAtProgress_playsTwice() =
with(kosmos) {
// GIVEN max velocity and slider progress
@@ -265,6 +477,36 @@
)
}
+ @Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playHapticAtUpperBookend_afterPlayingAtProgress_playsTokensTwice() =
+ with(kosmos) {
+ // GIVEN max velocity and slider progress
+ val progress = 1f
+ val expectedProperties =
+ InteractionProperties.DynamicVibrationScale(
+ sliderHapticFeedbackProvider.scaleOnEdgeCollision(config.maxVelocityToScale),
+ pipeliningAttributes,
+ )
+
+ // GIVEN a vibration at the upper bookend followed by a request to vibrate at progress
+ sliderHapticFeedbackProvider.onUpperBookend()
+ sliderHapticFeedbackProvider.onProgress(progress)
+
+ // WHEN a vibration is to trigger again at the upper bookend
+ sliderHapticFeedbackProvider.onUpperBookend()
+
+ // THEN there are two bookend vibrations
+ assertThat(msdlPlayer.getHistory().size).isEqualTo(2)
+ assertThat(msdlPlayer.tokensPlayed[0])
+ .isEqualTo(MSDLToken.DRAG_THRESHOLD_INDICATOR_LIMIT)
+ assertThat(msdlPlayer.propertiesPlayed[0]).isEqualTo(expectedProperties)
+ assertThat(msdlPlayer.tokensPlayed[1])
+ .isEqualTo(MSDLToken.DRAG_THRESHOLD_INDICATOR_LIMIT)
+ assertThat(msdlPlayer.propertiesPlayed[1]).isEqualTo(expectedProperties)
+ }
+
+ @Test
fun dragTextureLastProgress_afterDragTextureHaptics_keepsLastDragTextureProgress() =
with(kosmos) {
// GIVEN max velocity and a slider progress at half progress
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/FakeScreenshotPolicy.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/FakeScreenshotPolicy.kt
deleted file mode 100644
index 28d53c7..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/FakeScreenshotPolicy.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2022 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 com.android.systemui.screenshot
-
-import com.android.systemui.screenshot.ScreenshotPolicy.DisplayContentInfo
-
-internal class FakeScreenshotPolicy : ScreenshotPolicy {
-
- private val userTypes = mutableMapOf<Int, Boolean>()
- private val contentInfo = mutableMapOf<Int, DisplayContentInfo?>()
-
- fun setManagedProfile(userId: Int, managedUser: Boolean) {
- userTypes[userId] = managedUser
- }
- override suspend fun isManagedProfile(userId: Int): Boolean {
- return userTypes[userId] ?: error("No managedProfile value set for userId $userId")
- }
-
- fun setDisplayContentInfo(userId: Int, contentInfo: DisplayContentInfo) {
- this.contentInfo[userId] = contentInfo
- }
-
- override suspend fun findPrimaryContent(displayId: Int): DisplayContentInfo {
- return contentInfo[displayId] ?: error("No DisplayContentInfo set for displayId $displayId")
- }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
index fb91c78..080f46f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
@@ -32,6 +32,7 @@
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.time.FakeSystemClock
+import com.google.android.msdl.domain.MSDLPlayer
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
@@ -46,34 +47,26 @@
import org.mockito.Mockito.never
import org.mockito.Mockito.notNull
import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
@SmallTest
@RunWith(AndroidTestingRunner::class)
class BrightnessSliderControllerTest : SysuiTestCase() {
- @Mock
- private lateinit var brightnessSliderView: BrightnessSliderView
- @Mock
- private lateinit var enforcedAdmin: RestrictedLockUtils.EnforcedAdmin
- @Mock
- private lateinit var mirrorController: BrightnessMirrorController
- @Mock
- private lateinit var mirror: ToggleSlider
- @Mock
- private lateinit var motionEvent: MotionEvent
- @Mock
- private lateinit var listener: ToggleSlider.Listener
- @Mock
- private lateinit var vibratorHelper: VibratorHelper
- @Mock
- private lateinit var activityStarter: ActivityStarter
+ @Mock private lateinit var brightnessSliderView: BrightnessSliderView
+ @Mock private lateinit var enforcedAdmin: RestrictedLockUtils.EnforcedAdmin
+ @Mock private lateinit var mirrorController: BrightnessMirrorController
+ @Mock private lateinit var mirror: ToggleSlider
+ @Mock private lateinit var motionEvent: MotionEvent
+ @Mock private lateinit var listener: ToggleSlider.Listener
+ @Mock private lateinit var vibratorHelper: VibratorHelper
+ @Mock private lateinit var msdlPlayer: MSDLPlayer
+ @Mock private lateinit var activityStarter: ActivityStarter
@Captor
private lateinit var seekBarChangeCaptor: ArgumentCaptor<SeekBar.OnSeekBarChangeListener>
- @Mock
- private lateinit var seekBar: SeekBar
+ @Mock private lateinit var seekBar: SeekBar
private val uiEventLogger = UiEventLoggerFake()
private var mFalsingManager: FalsingManagerFake = FalsingManagerFake()
private val systemClock = FakeSystemClock()
@@ -93,7 +86,7 @@
brightnessSliderView,
mFalsingManager,
uiEventLogger,
- SeekbarHapticPlugin(vibratorHelper, systemClock),
+ SeekbarHapticPlugin(vibratorHelper, msdlPlayer, systemClock),
activityStarter,
)
mController.init()
@@ -241,4 +234,4 @@
assertThat(uiEventLogger.numLogs()).isEqualTo(1)
assertThat(uiEventLogger.eventId(0)).isEqualTo(event.id)
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
index cfac486..ea5c29e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
@@ -24,7 +24,6 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -66,7 +65,6 @@
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider;
import com.android.systemui.statusbar.notification.domain.interactor.SeenNotificationsInteractor;
import com.android.systemui.statusbar.policy.HeadsUpManager;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.kotlin.JavaAdapter;
import com.android.systemui.util.time.FakeSystemClock;
@@ -100,7 +98,6 @@
@Mock private VisibilityLocationProvider mVisibilityLocationProvider;
@Mock private VisualStabilityProvider mVisualStabilityProvider;
@Mock private VisualStabilityCoordinatorLogger mLogger;
- @Mock private KeyguardStateController mKeyguardStateController;
@Captor private ArgumentCaptor<WakefulnessLifecycle.Observer> mWakefulnessObserverCaptor;
@Captor private ArgumentCaptor<StatusBarStateController.StateListener> mSBStateListenerCaptor;
@@ -141,7 +138,6 @@
mKosmos.getCommunalSceneInteractor(),
mKosmos.getShadeInteractor(),
mKosmos.getKeyguardTransitionInteractor(),
- mKeyguardStateController,
mLogger);
mCoordinator.attach(mNotifPipeline);
mTestScope.getTestScheduler().runCurrent();
@@ -526,13 +522,23 @@
@EnableFlags(Flags.FLAG_CHECK_LOCKSCREEN_GONE_TRANSITION)
public void testNotLockscreenInGoneTransition_invalidationCalled() {
// GIVEN visual stability is being maintained b/c animation is playing
- doReturn(true).when(mKeyguardStateController).isKeyguardFadingAway();
- mCoordinator.mKeyguardFadeAwayAnimationCallback.onKeyguardFadingAwayChanged();
+ mKosmos.getKeyguardTransitionRepository().sendTransitionStepJava(
+ mTestScope, new TransitionStep(
+ KeyguardState.LOCKSCREEN,
+ KeyguardState.GONE,
+ 1f,
+ TransitionState.RUNNING), /* validateStep = */ false);
+ mTestScope.getTestScheduler().runCurrent();
assertFalse(mNotifStabilityManager.isPipelineRunAllowed());
// WHEN the animation has stopped playing
- doReturn(false).when(mKeyguardStateController).isKeyguardFadingAway();
- mCoordinator.mKeyguardFadeAwayAnimationCallback.onKeyguardFadingAwayChanged();
+ mKosmos.getKeyguardTransitionRepository().sendTransitionStepJava(
+ mTestScope, new TransitionStep(
+ KeyguardState.LOCKSCREEN,
+ KeyguardState.GONE,
+ 1f,
+ TransitionState.FINISHED), /* validateStep = */ false);
+ mTestScope.getTestScheduler().runCurrent();
// invalidate is called, b/c we were previously suppressing the pipeline from running
verifyStabilityManagerWasInvalidated(times(1));
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekbarHapticPlugin.kt b/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekbarHapticPlugin.kt
index 932e5af..cc77f68a 100644
--- a/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekbarHapticPlugin.kt
+++ b/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekbarHapticPlugin.kt
@@ -22,6 +22,7 @@
import androidx.annotation.VisibleForTesting
import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.util.time.SystemClock
+import com.google.android.msdl.domain.MSDLPlayer
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
@@ -39,6 +40,7 @@
@JvmOverloads
constructor(
vibratorHelper: VibratorHelper,
+ msdlPlayer: MSDLPlayer,
systemClock: SystemClock,
sliderHapticFeedbackConfig: SliderHapticFeedbackConfig = SliderHapticFeedbackConfig(),
private val sliderTrackerConfig: SeekableSliderTrackerConfig = SeekableSliderTrackerConfig(),
@@ -63,6 +65,7 @@
private val sliderHapticFeedbackProvider =
SliderHapticFeedbackProvider(
vibratorHelper,
+ msdlPlayer,
dragVelocityProvider,
sliderHapticFeedbackConfig,
systemClock,
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProvider.kt b/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProvider.kt
index 06428b7..bc4f531 100644
--- a/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProvider.kt
@@ -22,7 +22,11 @@
import android.view.animation.AccelerateInterpolator
import androidx.annotation.FloatRange
import androidx.annotation.VisibleForTesting
+import com.android.systemui.Flags
import com.android.systemui.statusbar.VibratorHelper
+import com.google.android.msdl.data.model.MSDLToken
+import com.google.android.msdl.domain.InteractionProperties
+import com.google.android.msdl.domain.MSDLPlayer
import kotlin.math.abs
import kotlin.math.min
import kotlin.math.pow
@@ -38,6 +42,7 @@
*/
class SliderHapticFeedbackProvider(
private val vibratorHelper: VibratorHelper,
+ private val msdlPlayer: MSDLPlayer,
private val velocityProvider: SliderDragVelocityProvider,
private val config: SliderHapticFeedbackConfig = SliderHapticFeedbackConfig(),
private val clock: com.android.systemui.util.time.SystemClock,
@@ -67,11 +72,20 @@
*/
private fun vibrateOnEdgeCollision(absoluteVelocity: Float) {
val powerScale = scaleOnEdgeCollision(absoluteVelocity)
- val vibration =
- VibrationEffect.startComposition()
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, powerScale)
- .compose()
- vibratorHelper.vibrate(vibration, VIBRATION_ATTRIBUTES_PIPELINING)
+ if (Flags.msdlFeedback()) {
+ val properties =
+ InteractionProperties.DynamicVibrationScale(
+ powerScale,
+ VIBRATION_ATTRIBUTES_PIPELINING,
+ )
+ msdlPlayer.playToken(MSDLToken.DRAG_THRESHOLD_INDICATOR_LIMIT, properties)
+ } else {
+ val vibration =
+ VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, powerScale)
+ .compose()
+ vibratorHelper.vibrate(vibration, VIBRATION_ATTRIBUTES_PIPELINING)
+ }
}
/**
@@ -112,16 +126,26 @@
val powerScale = scaleOnDragTexture(absoluteVelocity, normalizedSliderProgress)
- // Trigger the vibration composition
- val composition = VibrationEffect.startComposition()
- repeat(config.numberOfLowTicks) {
- composition.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, powerScale)
- }
- vibratorHelper.vibrate(composition.compose(), VIBRATION_ATTRIBUTES_PIPELINING)
+ // Deliver haptic feedback
+ performContinuousSliderDragVibration(powerScale)
dragTextureLastTime = currentTime
dragTextureLastProgress = normalizedSliderProgress
}
+ private fun performContinuousSliderDragVibration(scale: Float) {
+ if (Flags.msdlFeedback()) {
+ val properties =
+ InteractionProperties.DynamicVibrationScale(scale, VIBRATION_ATTRIBUTES_PIPELINING)
+ msdlPlayer.playToken(MSDLToken.DRAG_INDICATOR_CONTINUOUS, properties)
+ } else {
+ val composition = VibrationEffect.startComposition()
+ repeat(config.numberOfLowTicks) {
+ composition.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, scale)
+ }
+ vibratorHelper.vibrate(composition.compose(), VIBRATION_ATTRIBUTES_PIPELINING)
+ }
+ }
+
/**
* Get the scale of the drag texture vibration.
*
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/slider/compose/ui/SliderHapticsViewModel.kt b/packages/SystemUI/src/com/android/systemui/haptics/slider/compose/ui/SliderHapticsViewModel.kt
index 1dbcb3df..de24259 100644
--- a/packages/SystemUI/src/com/android/systemui/haptics/slider/compose/ui/SliderHapticsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/haptics/slider/compose/ui/SliderHapticsViewModel.kt
@@ -33,6 +33,7 @@
import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.util.time.SystemClock
+import com.google.android.msdl.domain.MSDLPlayer
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
@@ -50,6 +51,7 @@
@Assisted private val sliderHapticFeedbackConfig: SliderHapticFeedbackConfig,
@Assisted private val sliderTrackerConfig: SeekableSliderTrackerConfig,
vibratorHelper: VibratorHelper,
+ msdlPlayer: MSDLPlayer,
systemClock: SystemClock,
) : ExclusiveActivatable() {
@@ -78,6 +80,7 @@
private val sliderHapticFeedbackProvider =
SliderHapticFeedbackProvider(
vibratorHelper,
+ msdlPlayer,
dragVelocityProvider,
sliderHapticFeedbackConfig,
systemClock,
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicy.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicy.kt
deleted file mode 100644
index f73d204..0000000
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicy.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2022 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 com.android.systemui.screenshot
-
-import android.annotation.UserIdInt
-import android.content.ComponentName
-import android.graphics.Rect
-import android.os.UserHandle
-import android.view.Display
-
-/**
- * Provides policy decision-making information to screenshot request handling.
- */
-interface ScreenshotPolicy {
-
- /** @return true if the user is a managed profile (a.k.a. work profile) */
- suspend fun isManagedProfile(@UserIdInt userId: Int): Boolean
-
- /**
- * Requests information about the owner of display content which occupies a majority of the
- * screenshot and/or has most recently been interacted with at the time the screenshot was
- * requested.
- *
- * @param displayId the id of the display to inspect
- * @return content info for the primary content on the display
- */
- suspend fun findPrimaryContent(displayId: Int): DisplayContentInfo
-
- data class DisplayContentInfo(
- val component: ComponentName,
- val bounds: Rect,
- val user: UserHandle,
- val taskId: Int,
- )
-
- fun getDefaultDisplayId(): Int = Display.DEFAULT_DISPLAY
-}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicyImpl.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicyImpl.kt
deleted file mode 100644
index 21a7310..0000000
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicyImpl.kt
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2022 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 com.android.systemui.screenshot
-
-import android.annotation.UserIdInt
-import android.app.ActivityTaskManager
-import android.app.ActivityTaskManager.RootTaskInfo
-import android.app.IActivityTaskManager
-import android.app.WindowConfiguration
-import android.app.WindowConfiguration.activityTypeToString
-import android.app.WindowConfiguration.windowingModeToString
-import android.content.ComponentName
-import android.content.Context
-import android.content.Intent
-import android.graphics.Rect
-import android.os.Process
-import android.os.RemoteException
-import android.os.UserHandle
-import android.os.UserManager
-import android.util.Log
-import com.android.internal.annotations.VisibleForTesting
-import com.android.internal.infra.ServiceConnector
-import com.android.systemui.SystemUIService
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.settings.DisplayTracker
-import com.android.systemui.screenshot.ScreenshotPolicy.DisplayContentInfo
-import java.util.Arrays
-import javax.inject.Inject
-import kotlin.coroutines.resume
-import kotlin.coroutines.suspendCoroutine
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.withContext
-
-@SysUISingleton
-internal open class ScreenshotPolicyImpl @Inject constructor(
- context: Context,
- private val userMgr: UserManager,
- private val atmService: IActivityTaskManager,
- @Background val bgDispatcher: CoroutineDispatcher,
- private val displayTracker: DisplayTracker
-) : ScreenshotPolicy {
-
- private val proxyConnector: ServiceConnector<IScreenshotProxy> =
- ServiceConnector.Impl(
- context,
- Intent(context, ScreenshotProxyService::class.java),
- Context.BIND_AUTO_CREATE or Context.BIND_WAIVE_PRIORITY or Context.BIND_NOT_VISIBLE,
- context.userId,
- IScreenshotProxy.Stub::asInterface
- )
-
- override fun getDefaultDisplayId(): Int {
- return displayTracker.defaultDisplayId
- }
-
- override suspend fun isManagedProfile(@UserIdInt userId: Int): Boolean {
- val managed = withContext(bgDispatcher) { userMgr.isManagedProfile(userId) }
- Log.d(TAG, "isManagedProfile: $managed")
- return managed
- }
-
- private fun nonPipVisibleTask(info: RootTaskInfo): Boolean {
- if (DEBUG) {
- debugLogRootTaskInfo(info)
- }
- return info.windowingMode != WindowConfiguration.WINDOWING_MODE_PINNED &&
- info.isVisible &&
- info.isRunning &&
- info.numActivities > 0 &&
- info.topActivity != null &&
- info.childTaskIds.isNotEmpty()
- }
-
- /**
- * Uses RootTaskInfo from ActivityTaskManager to guess at the primary focused task within a
- * display. If no task is visible or the top task is covered by a system window, the info
- * reported will reference a SystemUI component instead.
- */
- override suspend fun findPrimaryContent(displayId: Int): DisplayContentInfo {
- // Determine if the notification shade is expanded. If so, task windows are not
- // visible behind it, so the screenshot should instead be associated with SystemUI.
- if (isNotificationShadeExpanded()) {
- return systemUiContent
- }
-
- val taskInfoList = getAllRootTaskInfosOnDisplay(displayId)
-
- // If no visible task is located, then report SystemUI as the foreground content
- val target = taskInfoList.firstOrNull(::nonPipVisibleTask) ?: return systemUiContent
- return target.toDisplayContentInfo()
- }
-
- private fun debugLogRootTaskInfo(info: RootTaskInfo) {
- Log.d(TAG, "RootTaskInfo={" +
- "taskId=${info.taskId} " +
- "parentTaskId=${info.parentTaskId} " +
- "position=${info.position} " +
- "positionInParent=${info.positionInParent} " +
- "isVisible=${info.isVisible()} " +
- "visible=${info.visible} " +
- "isFocused=${info.isFocused} " +
- "isSleeping=${info.isSleeping} " +
- "isRunning=${info.isRunning} " +
- "windowMode=${windowingModeToString(info.windowingMode)} " +
- "activityType=${activityTypeToString(info.activityType)} " +
- "topActivity=${info.topActivity} " +
- "topActivityInfo=${info.topActivityInfo} " +
- "numActivities=${info.numActivities} " +
- "childTaskIds=${Arrays.toString(info.childTaskIds)} " +
- "childUserIds=${Arrays.toString(info.childTaskUserIds)} " +
- "childTaskBounds=${Arrays.toString(info.childTaskBounds)} " +
- "childTaskNames=${Arrays.toString(info.childTaskNames)}" +
- "}"
- )
-
- for (j in 0 until info.childTaskIds.size) {
- Log.d(TAG, " *** [$j] ******")
- Log.d(TAG, " *** childTaskIds[$j]: ${info.childTaskIds[j]}")
- Log.d(TAG, " *** childTaskUserIds[$j]: ${info.childTaskUserIds[j]}")
- Log.d(TAG, " *** childTaskBounds[$j]: ${info.childTaskBounds[j]}")
- Log.d(TAG, " *** childTaskNames[$j]: ${info.childTaskNames[j]}")
- }
- }
-
- @VisibleForTesting
- open suspend fun getAllRootTaskInfosOnDisplay(displayId: Int): List<RootTaskInfo> =
- withContext(bgDispatcher) {
- try {
- atmService.getAllRootTaskInfosOnDisplay(displayId)
- } catch (e: RemoteException) {
- Log.e(TAG, "getAllRootTaskInfosOnDisplay", e)
- listOf()
- }
- }
-
- @VisibleForTesting
- open suspend fun isNotificationShadeExpanded(): Boolean = suspendCoroutine { k ->
- proxyConnector
- .postForResult { it.isNotificationShadeExpanded }
- .whenComplete { expanded, error ->
- if (error != null) {
- Log.e(TAG, "isNotificationShadeExpanded", error)
- }
- k.resume(expanded ?: false)
- }
- }
-
- @VisibleForTesting
- internal val systemUiContent =
- DisplayContentInfo(
- ComponentName(context, SystemUIService::class.java),
- Rect(),
- Process.myUserHandle(),
- ActivityTaskManager.INVALID_TASK_ID
- )
-}
-
-private const val TAG: String = "ScreenshotPolicyImpl"
-private const val DEBUG: Boolean = false
-
-@VisibleForTesting
-internal fun RootTaskInfo.toDisplayContentInfo(): DisplayContentInfo {
- val topActivity: ComponentName = topActivity ?: error("should not be null")
- val topChildTask = childTaskIds.size - 1
- val childTaskId = childTaskIds[topChildTask]
- val childTaskUserId = childTaskUserIds[topChildTask]
- val childTaskBounds = childTaskBounds[topChildTask]
-
- return DisplayContentInfo(
- topActivity,
- childTaskBounds,
- UserHandle.of(childTaskUserId),
- childTaskId)
-}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java b/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
index 254dde4..90695fa 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
@@ -27,8 +27,6 @@
import com.android.systemui.screenshot.InteractiveScreenshotHandler;
import com.android.systemui.screenshot.LegacyScreenshotController;
import com.android.systemui.screenshot.ScreenshotController;
-import com.android.systemui.screenshot.ScreenshotPolicy;
-import com.android.systemui.screenshot.ScreenshotPolicyImpl;
import com.android.systemui.screenshot.ScreenshotSoundController;
import com.android.systemui.screenshot.ScreenshotSoundControllerImpl;
import com.android.systemui.screenshot.ScreenshotSoundProvider;
@@ -66,9 +64,6 @@
TakeScreenshotExecutorImpl impl);
@Binds
- abstract ScreenshotPolicy bindScreenshotPolicyImpl(ScreenshotPolicyImpl impl);
-
- @Binds
abstract ImageCapture bindImageCaptureImpl(ImageCaptureImpl capture);
@Binds
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
index 75165cb..8703f68 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
@@ -40,6 +40,8 @@
import com.android.systemui.util.ViewController;
import com.android.systemui.util.time.SystemClock;
+import com.google.android.msdl.domain.MSDLPlayer;
+
import javax.inject.Inject;
/**
@@ -283,12 +285,14 @@
private final VibratorHelper mVibratorHelper;
private final SystemClock mSystemClock;
private final ActivityStarter mActivityStarter;
+ private final MSDLPlayer mMSDLPlayer;
@Inject
public Factory(
FalsingManager falsingManager,
UiEventLogger uiEventLogger,
VibratorHelper vibratorHelper,
+ MSDLPlayer msdlPlayer,
SystemClock clock,
ActivityStarter activityStarter
) {
@@ -297,6 +301,7 @@
mVibratorHelper = vibratorHelper;
mSystemClock = clock;
mActivityStarter = activityStarter;
+ mMSDLPlayer = msdlPlayer;
}
/**
@@ -314,6 +319,7 @@
.inflate(layout, viewRoot, false);
SeekbarHapticPlugin plugin = new SeekbarHapticPlugin(
mVibratorHelper,
+ mMSDLPlayer,
mSystemClock);
HapticSliderViewBinder.bind(viewRoot, plugin);
return new BrightnessSliderController(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
index 6edffc0..8660cd1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
@@ -29,9 +29,11 @@
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
+import com.android.systemui.keyguard.shared.model.Edge;
import com.android.systemui.keyguard.shared.model.KeyguardState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.scene.shared.flag.SceneContainerFlag;
+import com.android.systemui.scene.shared.model.Scenes;
import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractor;
import com.android.systemui.shade.domain.interactor.ShadeInteractor;
import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
@@ -44,7 +46,6 @@
import com.android.systemui.statusbar.notification.domain.interactor.SeenNotificationsInteractor;
import com.android.systemui.statusbar.notification.shared.NotificationMinimalism;
import com.android.systemui.statusbar.policy.HeadsUpManager;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.kotlin.BooleanFlowOperators;
import com.android.systemui.util.kotlin.JavaAdapter;
@@ -77,7 +78,6 @@
private final CommunalSceneInteractor mCommunalSceneInteractor;
private final ShadeInteractor mShadeInteractor;
private final KeyguardTransitionInteractor mKeyguardTransitionInteractor;
- private final KeyguardStateController mKeyguardStateController;
private final VisualStabilityCoordinatorLogger mLogger;
private boolean mSleepy = true;
@@ -120,7 +120,6 @@
CommunalSceneInteractor communalSceneInteractor,
ShadeInteractor shadeInteractor,
KeyguardTransitionInteractor keyguardTransitionInteractor,
- KeyguardStateController keyguardStateController,
VisualStabilityCoordinatorLogger logger) {
mHeadsUpManager = headsUpManager;
mShadeAnimationInteractor = shadeAnimationInteractor;
@@ -134,7 +133,6 @@
mCommunalSceneInteractor = communalSceneInteractor;
mShadeInteractor = shadeInteractor;
mKeyguardTransitionInteractor = keyguardTransitionInteractor;
- mKeyguardStateController = keyguardStateController;
mLogger = logger;
dumpManager.registerDumpable(this);
@@ -164,23 +162,17 @@
KeyguardState.LOCKSCREEN),
this::onLockscreenKeyguardStateTransitionValueChanged);
}
-
if (Flags.checkLockscreenGoneTransition()) {
- mKeyguardStateController.addCallback(mKeyguardFadeAwayAnimationCallback);
+ mJavaAdapter.alwaysCollectFlow(mKeyguardTransitionInteractor.isInTransition(
+ Edge.create(KeyguardState.LOCKSCREEN, Scenes.Gone),
+ Edge.create(KeyguardState.LOCKSCREEN, KeyguardState.GONE)),
+ this::onLockscreenInGoneTransitionChanged);
}
+
pipeline.setVisualStabilityManager(mNotifStabilityManager);
}
- final KeyguardStateController.Callback mKeyguardFadeAwayAnimationCallback =
- new KeyguardStateController.Callback() {
- @Override
- public void onKeyguardFadingAwayChanged() {
- onLockscreenInGoneTransitionChanged(
- mKeyguardStateController.isKeyguardFadingAway());
- }
- };
-
// TODO(b/203826051): Ensure stability manager can allow reordering off-screen
// HUNs to the top of the shade
private final NotifStabilityManager mNotifStabilityManager =
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 7c5116d..3d2ebf2 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -140,6 +140,7 @@
import com.android.systemui.volume.panel.shared.flag.VolumePanelFlag;
import com.android.systemui.volume.ui.navigation.VolumeNavigator;
+import com.google.android.msdl.domain.MSDLPlayer;
import com.google.common.collect.ImmutableList;
import dagger.Lazy;
@@ -315,6 +316,7 @@
private final Lazy<SecureSettings> mSecureSettings;
private int mDialogTimeoutMillis;
private final VibratorHelper mVibratorHelper;
+ private final MSDLPlayer mMSDLPlayer;
private final com.android.systemui.util.time.SystemClock mSystemClock;
private final VolumePanelFlag mVolumePanelFlag;
private final VolumeDialogInteractor mInteractor;
@@ -340,12 +342,14 @@
DumpManager dumpManager,
Lazy<SecureSettings> secureSettings,
VibratorHelper vibratorHelper,
+ MSDLPlayer msdlPlayer,
com.android.systemui.util.time.SystemClock systemClock,
VolumeDialogInteractor interactor) {
mContext =
new ContextThemeWrapper(context, R.style.volume_dialog_theme);
mHandler = new H(looper);
mVibratorHelper = vibratorHelper;
+ mMSDLPlayer = msdlPlayer;
mSystemClock = systemClock;
mShouldListenForJank = shouldListenForJank;
mController = volumeDialogController;
@@ -927,7 +931,7 @@
}
private void addSliderHapticsToRow(VolumeRow row) {
- row.createPlugin(mVibratorHelper, mSystemClock);
+ row.createPlugin(mVibratorHelper, mMSDLPlayer, mSystemClock);
HapticSliderViewBinder.bind(row.slider, row.mHapticPlugin);
}
@@ -2707,11 +2711,13 @@
void createPlugin(
VibratorHelper vibratorHelper,
+ MSDLPlayer msdlPlayer,
com.android.systemui.util.time.SystemClock systemClock) {
if (mHapticPlugin != null) return;
mHapticPlugin = new SeekbarHapticPlugin(
vibratorHelper,
+ msdlPlayer,
systemClock,
sSliderHapticFeedbackConfig,
sSliderTrackerConfig);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java b/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java
index ed8de69..2009143 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java
@@ -50,6 +50,8 @@
import com.android.systemui.volume.panel.shared.flag.VolumePanelFlag;
import com.android.systemui.volume.ui.navigation.VolumeNavigator;
+import com.google.android.msdl.domain.MSDLPlayer;
+
import dagger.Binds;
import dagger.Lazy;
import dagger.Module;
@@ -121,6 +123,7 @@
DumpManager dumpManager,
Lazy<SecureSettings> secureSettings,
VibratorHelper vibratorHelper,
+ MSDLPlayer msdlPlayer,
SystemClock systemClock,
VolumeDialogInteractor interactor) {
if (Flags.volumeRedesign()) {
@@ -144,6 +147,7 @@
dumpManager,
secureSettings,
vibratorHelper,
+ msdlPlayer,
systemClock,
interactor);
impl.setStreamImportant(AudioManager.STREAM_SYSTEM, false);
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index 02d0b57..8039e00 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -281,13 +281,13 @@
void initSplitScreen(SplitScreen splitScreen) {
mWakefulnessLifecycle.addObserver(new WakefulnessLifecycle.Observer() {
@Override
- public void onFinishedWakingUp() {
- splitScreen.onFinishedWakingUp();
+ public void onStartedGoingToSleep() {
+ splitScreen.onStartedGoingToSleep();
}
@Override
- public void onStartedGoingToSleep() {
- splitScreen.onStartedGoingToSleep();
+ public void onStartedWakingUp() {
+ splitScreen.onStartedWakingUp();
}
});
mCommandQueue.addCallback(new CommandQueue.Callbacks() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java
index e981d62..cad22d3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java
@@ -16,11 +16,11 @@
package com.android.systemui.keyguard;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.argThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt
index dcf32a5..51c8525 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt
@@ -38,11 +38,11 @@
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyString
import org.mockito.Captor
import org.mockito.Mock
-import org.mockito.Mockito
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
@@ -61,7 +61,7 @@
private const val SMARTSPACE_KEY = "SMARTSPACE_KEY"
private fun <T> anyObject(): T {
- return Mockito.anyObject<T>()
+ return ArgumentMatchers.any<T>()
}
@SmallTest
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
index bdd8dc8..2aa300d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
@@ -21,7 +21,7 @@
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.mock;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
index 2f41ac17..338ed75 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
@@ -19,9 +19,8 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.anyObject;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -194,7 +193,7 @@
TestableLooper.get(this).processAllMessages();
verify(mThermalServiceMock, times(1))
- .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_SKIN));
+ .registerThermalEventListenerWithType(any(), eq(Temperature.TYPE_SKIN));
}
@Test
@@ -207,7 +206,7 @@
TestableLooper.get(this).processAllMessages();
verify(mThermalServiceMock, times(1))
- .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_USB_PORT));
+ .registerThermalEventListenerWithType(any(), eq(Temperature.TYPE_USB_PORT));
}
@Test
@@ -220,7 +219,7 @@
TestableLooper.get(this).processAllMessages();
verify(mThermalServiceMock, times(0))
- .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_SKIN));
+ .registerThermalEventListenerWithType(any(), eq(Temperature.TYPE_SKIN));
}
@Test
@@ -233,7 +232,7 @@
TestableLooper.get(this).processAllMessages();
verify(mThermalServiceMock, times(0))
- .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_USB_PORT));
+ .registerThermalEventListenerWithType(any(), eq(Temperature.TYPE_USB_PORT));
}
@Test
@@ -243,14 +242,14 @@
// success registering skin thermal event listener
when(mThermalServiceMock.registerThermalEventListenerWithType(
- anyObject(), eq(Temperature.TYPE_SKIN))).thenReturn(true);
+ any(), eq(Temperature.TYPE_SKIN))).thenReturn(true);
mPowerUI.doSkinThermalEventListenerRegistration();
// verify registering skin thermal event listener, return true (success)
TestableLooper.get(this).processAllMessages();
verify(mThermalServiceMock, times(1))
- .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_SKIN));
+ .registerThermalEventListenerWithType(any(), eq(Temperature.TYPE_SKIN));
// Settings SHOW_TEMPERATURE_WARNING is set to 0
Settings.Global.putInt(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, 0);
@@ -259,7 +258,7 @@
// verify unregistering skin thermal event listener
TestableLooper.get(this).processAllMessages();
- verify(mThermalServiceMock, times(1)).unregisterThermalEventListener(anyObject());
+ verify(mThermalServiceMock, times(1)).unregisterThermalEventListener(any());
}
@Test
@@ -269,14 +268,14 @@
// fail registering skin thermal event listener
when(mThermalServiceMock.registerThermalEventListenerWithType(
- anyObject(), eq(Temperature.TYPE_SKIN))).thenReturn(false);
+ any(), eq(Temperature.TYPE_SKIN))).thenReturn(false);
mPowerUI.doSkinThermalEventListenerRegistration();
// verify registering skin thermal event listener, return false (fail)
TestableLooper.get(this).processAllMessages();
verify(mThermalServiceMock, times(1))
- .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_SKIN));
+ .registerThermalEventListenerWithType(any(), eq(Temperature.TYPE_SKIN));
// Settings SHOW_TEMPERATURE_WARNING is set to 0
Settings.Global.putInt(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, 0);
@@ -285,7 +284,7 @@
// verify that cannot unregister listener (current state is unregistered)
TestableLooper.get(this).processAllMessages();
- verify(mThermalServiceMock, times(0)).unregisterThermalEventListener(anyObject());
+ verify(mThermalServiceMock, times(0)).unregisterThermalEventListener(any());
// Settings SHOW_TEMPERATURE_WARNING is set to 1
Settings.Global.putInt(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, 1);
@@ -295,7 +294,7 @@
// verify that can register listener (current state is unregistered)
TestableLooper.get(this).processAllMessages();
verify(mThermalServiceMock, times(2))
- .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_SKIN));
+ .registerThermalEventListenerWithType(any(), eq(Temperature.TYPE_SKIN));
}
@Test
@@ -305,14 +304,14 @@
// success registering usb thermal event listener
when(mThermalServiceMock.registerThermalEventListenerWithType(
- anyObject(), eq(Temperature.TYPE_USB_PORT))).thenReturn(true);
+ any(), eq(Temperature.TYPE_USB_PORT))).thenReturn(true);
mPowerUI.doUsbThermalEventListenerRegistration();
// verify registering usb thermal event listener, return true (success)
TestableLooper.get(this).processAllMessages();
verify(mThermalServiceMock, times(1))
- .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_USB_PORT));
+ .registerThermalEventListenerWithType(any(), eq(Temperature.TYPE_USB_PORT));
// Settings SHOW_USB_TEMPERATURE_ALARM is set to 0
Settings.Global.putInt(mContext.getContentResolver(), SHOW_USB_TEMPERATURE_ALARM, 0);
@@ -320,7 +319,7 @@
// verify unregistering usb thermal event listener
mPowerUI.doUsbThermalEventListenerRegistration();
TestableLooper.get(this).processAllMessages();
- verify(mThermalServiceMock, times(1)).unregisterThermalEventListener(anyObject());
+ verify(mThermalServiceMock, times(1)).unregisterThermalEventListener(any());
}
@Test
@@ -330,14 +329,14 @@
// fail registering usb thermal event listener
when(mThermalServiceMock.registerThermalEventListenerWithType(
- anyObject(), eq(Temperature.TYPE_USB_PORT))).thenReturn(false);
+ any(), eq(Temperature.TYPE_USB_PORT))).thenReturn(false);
mPowerUI.doUsbThermalEventListenerRegistration();
// verify registering usb thermal event listener, return false (fail)
TestableLooper.get(this).processAllMessages();
verify(mThermalServiceMock, times(1))
- .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_USB_PORT));
+ .registerThermalEventListenerWithType(any(), eq(Temperature.TYPE_USB_PORT));
// Settings SHOW_USB_TEMPERATURE_ALARM is set to 0
Settings.Global.putInt(mContext.getContentResolver(), SHOW_USB_TEMPERATURE_ALARM, 0);
@@ -346,7 +345,7 @@
// verify that cannot unregister listener (current state is unregistered)
TestableLooper.get(this).processAllMessages();
- verify(mThermalServiceMock, times(0)).unregisterThermalEventListener(anyObject());
+ verify(mThermalServiceMock, times(0)).unregisterThermalEventListener(any());
// Settings SHOW_USB_TEMPERATURE_ALARM is set to 1
Settings.Global.putInt(mContext.getContentResolver(), SHOW_USB_TEMPERATURE_ALARM, 1);
@@ -356,7 +355,7 @@
// verify that can register listener (current state is unregistered)
TestableLooper.get(this).processAllMessages();
verify(mThermalServiceMock, times(2)).registerThermalEventListenerWithType(
- anyObject(), eq(Temperature.TYPE_USB_PORT));
+ any(), eq(Temperature.TYPE_USB_PORT));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
index dad65f5..f6d5732 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
@@ -25,7 +25,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
index 748c7d9..296478b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
@@ -36,7 +36,7 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Matchers.argThat;
+import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
deleted file mode 100644
index 3756ec1..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2022 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 com.android.systemui.screenshot
-
-import android.app.ActivityTaskManager.RootTaskInfo
-import android.app.IActivityTaskManager
-import android.content.ComponentName
-import android.content.Context
-import android.graphics.Rect
-import android.os.UserHandle
-import android.os.UserManager
-import android.testing.AndroidTestingRunner
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.screenshot.ScreenshotPolicy.DisplayContentInfo
-import com.android.systemui.screenshot.policy.ActivityType.Home
-import com.android.systemui.screenshot.policy.ActivityType.Undefined
-import com.android.systemui.screenshot.policy.WindowingMode.FullScreen
-import com.android.systemui.screenshot.policy.WindowingMode.PictureInPicture
-import com.android.systemui.screenshot.policy.newChildTask
-import com.android.systemui.screenshot.policy.newRootTaskInfo
-import com.android.systemui.settings.FakeDisplayTracker
-import com.android.systemui.util.mockito.mock
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.runBlocking
-import org.junit.Test
-import org.junit.runner.RunWith
-
-// The following values are chosen to be distinct from commonly seen real values
-private const val DISPLAY_ID = 100
-private const val PRIMARY_USER = 2000
-private const val MANAGED_PROFILE_USER = 3000
-
-@RunWith(AndroidTestingRunner::class)
-class ScreenshotPolicyImplTest : SysuiTestCase() {
-
- @Test
- fun testToDisplayContentInfo() {
- assertThat(fullScreenWorkProfileTask.toDisplayContentInfo())
- .isEqualTo(
- DisplayContentInfo(
- ComponentName(
- "com.google.android.apps.nbu.files",
- "com.google.android.apps.nbu.files.home.HomeActivity"
- ),
- Rect(0, 0, 1080, 2400),
- UserHandle.of(MANAGED_PROFILE_USER),
- 65
- )
- )
- }
-
- @Test
- fun findPrimaryContent_ignoresPipTask() = runBlocking {
- val policy =
- fakeTasksPolicyImpl(
- mContext,
- shadeExpanded = false,
- tasks = listOf(pipTask, fullScreenWorkProfileTask, launcherTask, emptyTask)
- )
-
- val info = policy.findPrimaryContent(DISPLAY_ID)
- assertThat(info).isEqualTo(fullScreenWorkProfileTask.toDisplayContentInfo())
- }
-
- @Test
- fun findPrimaryContent_shadeExpanded_ignoresTopTask() = runBlocking {
- val policy =
- fakeTasksPolicyImpl(
- mContext,
- shadeExpanded = true,
- tasks = listOf(fullScreenWorkProfileTask, launcherTask, emptyTask)
- )
-
- val info = policy.findPrimaryContent(DISPLAY_ID)
- assertThat(info).isEqualTo(policy.systemUiContent)
- }
-
- @Test
- fun findPrimaryContent_emptyTaskList() = runBlocking {
- val policy = fakeTasksPolicyImpl(mContext, shadeExpanded = false, tasks = listOf())
-
- val info = policy.findPrimaryContent(DISPLAY_ID)
- assertThat(info).isEqualTo(policy.systemUiContent)
- }
-
- @Test
- fun findPrimaryContent_workProfileNotOnTop() = runBlocking {
- val policy =
- fakeTasksPolicyImpl(
- mContext,
- shadeExpanded = false,
- tasks = listOf(launcherTask, fullScreenWorkProfileTask, emptyTask)
- )
-
- val info = policy.findPrimaryContent(DISPLAY_ID)
- assertThat(info).isEqualTo(launcherTask.toDisplayContentInfo())
- }
-
- private fun fakeTasksPolicyImpl(
- context: Context,
- shadeExpanded: Boolean,
- tasks: List<RootTaskInfo>
- ): ScreenshotPolicyImpl {
- val userManager = mock<UserManager>()
- val atmService = mock<IActivityTaskManager>()
- val dispatcher = Dispatchers.Unconfined
- val displayTracker = FakeDisplayTracker(context)
-
- return object :
- ScreenshotPolicyImpl(context, userManager, atmService, dispatcher, displayTracker) {
- override suspend fun isManagedProfile(userId: Int) = (userId == MANAGED_PROFILE_USER)
- override suspend fun getAllRootTaskInfosOnDisplay(displayId: Int) = tasks
- override suspend fun isNotificationShadeExpanded() = shadeExpanded
- }
- }
-
- private val pipTask =
- newRootTaskInfo(
- taskId = 66,
- userId = PRIMARY_USER,
- displayId = DISPLAY_ID,
- bounds = Rect(628, 1885, 1038, 2295),
- windowingMode = PictureInPicture,
- topActivity = ComponentName.unflattenFromString(YOUTUBE_PIP_ACTIVITY),
- ) {
- listOf(newChildTask(taskId = 66, userId = 0, name = YOUTUBE_HOME_ACTIVITY))
- }
-
- private val fullScreenWorkProfileTask =
- newRootTaskInfo(
- taskId = 65,
- userId = MANAGED_PROFILE_USER,
- displayId = DISPLAY_ID,
- bounds = Rect(0, 0, 1080, 2400),
- windowingMode = FullScreen,
- topActivity = ComponentName.unflattenFromString(FILES_HOME_ACTIVITY),
- ) {
- listOf(
- newChildTask(taskId = 65, userId = MANAGED_PROFILE_USER, name = FILES_HOME_ACTIVITY)
- )
- }
- private val launcherTask =
- newRootTaskInfo(
- taskId = 1,
- userId = PRIMARY_USER,
- displayId = DISPLAY_ID,
- activityType = Home,
- windowingMode = FullScreen,
- bounds = Rect(0, 0, 1080, 2400),
- topActivity = ComponentName.unflattenFromString(LAUNCHER_ACTIVITY),
- ) {
- listOf(newChildTask(taskId = 1, userId = 0, name = LAUNCHER_ACTIVITY))
- }
-
- private val emptyTask =
- newRootTaskInfo(
- taskId = 2,
- userId = PRIMARY_USER,
- displayId = DISPLAY_ID,
- visible = false,
- running = false,
- numActivities = 0,
- activityType = Undefined,
- bounds = Rect(0, 0, 1080, 2400),
- ) {
- listOf(
- newChildTask(taskId = 3, name = ""),
- newChildTask(taskId = 4, name = ""),
- )
- }
-}
-
-private const val YOUTUBE_HOME_ACTIVITY =
- "com.google.android.youtube/" + "com.google.android.youtube.app.honeycomb.Shell\$HomeActivity"
-
-private const val FILES_HOME_ACTIVITY =
- "com.google.android.apps.nbu.files/" + "com.google.android.apps.nbu.files.home.HomeActivity"
-
-private const val YOUTUBE_PIP_ACTIVITY =
- "com.google.android.youtube/" +
- "com.google.android.apps.youtube.app.watchwhile.WatchWhileActivity"
-
-private const val LAUNCHER_ACTIVITY =
- "com.google.android.apps.nexuslauncher/" +
- "com.google.android.apps.nexuslauncher.NexusLauncherActivity"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextViewTest.kt
index 040a9e9..8bd8b72 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextViewTest.kt
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package systemui.shared.clocks.view
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginActionManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginActionManagerTest.java
index e9222c3e..3ad0605 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginActionManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginActionManagerTest.java
@@ -19,8 +19,8 @@
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
index 2b5e014..b730b37 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
@@ -21,8 +21,8 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowInsetsController.BEHAVIOR_DEFAULT;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandRegistryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandRegistryTest.kt
index b18b7f8..72ffa0e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandRegistryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandRegistryTest.kt
@@ -16,41 +16,39 @@
package com.android.systemui.statusbar.commandline
-import androidx.test.filters.SmallTest
-import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
-
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-
-import org.mockito.ArgumentMatchers.anyList
-import org.mockito.ArgumentMatchers.eq
-import org.mockito.Mockito
-import org.mockito.Mockito.mock
-import org.mockito.Mockito.verify
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-
import java.io.PrintWriter
import java.io.StringWriter
import java.util.concurrent.Executor
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyList
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.verify
private fun <T> anyObject(): T {
- return Mockito.anyObject<T>()
+ return any<T>()
}
private fun <T : Any> safeEq(value: T): T = eq(value) ?: value
-@RunWith(AndroidTestingRunner::class)
+@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
@SmallTest
class CommandRegistryTest : SysuiTestCase() {
lateinit var registry: CommandRegistry
- val inLineExecutor = object : Executor {
- override fun execute(command: Runnable) {
- command.run()
+ val inLineExecutor =
+ object : Executor {
+ override fun execute(command: Runnable) {
+ command.run()
+ }
}
- }
val writer: PrintWriter = PrintWriter(StringWriter())
@@ -83,11 +81,9 @@
}
class FakeCommand() : Command {
- override fun execute(pw: PrintWriter, args: List<String>) {
- }
+ override fun execute(pw: PrintWriter, args: List<String>) {}
- override fun help(pw: PrintWriter) {
- }
+ override fun help(pw: PrintWriter) {}
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/CallbackHandlerTest.java
index 7bd77a6..5fce08b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/CallbackHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/CallbackHandlerTest.java
@@ -18,7 +18,7 @@
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.eq;
import android.os.HandlerThread;
import android.telephony.SubscriptionInfo;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
index 83dbfa0..b00f9e9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
@@ -25,10 +25,10 @@
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.isA;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.isA;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
@@ -297,7 +297,8 @@
assertNotNull(mDefaultCallbackInWifiTracker);
assertNotNull(mDefaultCallbackInNetworkController);
verify(mMockCm, atLeastOnce()).registerNetworkCallback(
- isA(NetworkRequest.class), callbackArg.capture(), isA(Handler.class));
+ isA(NetworkRequest.class), callbackArg.capture(),
+ isA(Handler.class));
mNetworkCallback = callbackArg.getValue();
assertNotNull(mNetworkCallback);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt
index dcd57f1..c2460f9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt
@@ -17,30 +17,27 @@
package com.android.systemui.statusbar.policy
import android.app.NotificationManager
-import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
-
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-
import com.android.systemui.SysuiTestCase
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.time.FakeSystemClock
-
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
-import org.mockito.Mockito
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
private fun <T> anyObject(): T {
- return Mockito.anyObject<T>()
+ return any<T>()
}
-@RunWith(AndroidTestingRunner::class)
+@RunWith(AndroidJUnit4::class)
@RunWithLooper()
@SmallTest
class BatteryStateNotifierTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
index 9bb7607..f91f373 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
@@ -22,10 +22,9 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyObject;
-import static org.mockito.Matchers.argThat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -120,9 +119,9 @@
verify(mBroadcastDispatcher).registerReceiverWithHandler(
brCaptor.capture(),
- anyObject(),
- anyObject(),
- anyObject());
+ any(),
+ any(),
+ any());
mBroadcastReceiver = brCaptor.getValue();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
index ecc7909..3007eab 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
@@ -92,6 +92,7 @@
import com.android.systemui.volume.panel.shared.flag.VolumePanelFlag;
import com.android.systemui.volume.ui.navigation.VolumeNavigator;
+import com.google.android.msdl.domain.MSDLPlayer;
import com.google.common.collect.ImmutableList;
import dagger.Lazy;
@@ -169,6 +170,9 @@
@Mock
private VibratorHelper mVibratorHelper;
+ @Mock
+ private MSDLPlayer mMSDLPlayer;
+
private int mLongestHideShowAnimationDuration = 250;
private FakeSettings mSecureSettings;
@@ -222,6 +226,7 @@
mDumpManager,
mLazySecureSettings,
mVibratorHelper,
+ mMSDLPlayer,
new FakeSystemClock(),
mVolumeDialogInteractor);
mDialog.init(0, null);
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/FakeMSDLPlayer.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/FakeMSDLPlayer.kt
index 2b81da3..fe82ab9 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/FakeMSDLPlayer.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/FakeMSDLPlayer.kt
@@ -23,19 +23,24 @@
import com.google.android.msdl.logging.MSDLEvent
class FakeMSDLPlayer : MSDLPlayer {
+ val tokensPlayed = mutableListOf<MSDLToken>()
+ val propertiesPlayed = mutableListOf<InteractionProperties?>()
private val history = arrayListOf<MSDLEvent>()
+
var currentFeedbackLevel = FeedbackLevel.DEFAULT
var latestTokenPlayed: MSDLToken? = null
+ get() = tokensPlayed.lastOrNull()
private set
var latestPropertiesPlayed: InteractionProperties? = null
+ get() = propertiesPlayed.lastOrNull()
private set
override fun getSystemFeedbackLevel(): FeedbackLevel = currentFeedbackLevel
override fun playToken(token: MSDLToken, properties: InteractionProperties?) {
- latestTokenPlayed = token
- latestPropertiesPlayed = properties
+ tokensPlayed.add(token)
+ propertiesPlayed.add(properties)
history.add(MSDLEvent(token, properties))
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/slider/SliderHapticsViewModelFactoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/slider/SliderHapticsViewModelFactoryKosmos.kt
index 257d758..3fbcf77 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/slider/SliderHapticsViewModelFactoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/slider/SliderHapticsViewModelFactoryKosmos.kt
@@ -18,6 +18,7 @@
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.interaction.InteractionSource
+import com.android.systemui.haptics.msdl.msdlPlayer
import com.android.systemui.haptics.slider.compose.ui.SliderHapticsViewModel
import com.android.systemui.haptics.vibratorHelper
import com.android.systemui.kosmos.Kosmos
@@ -40,6 +41,7 @@
sliderHapticFeedbackConfig,
sliderTrackerConfig,
vibratorHelper,
+ msdlPlayer,
fakeSystemClock,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/BrightnessSliderControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/BrightnessSliderControllerKosmos.kt
index 8b7e5d8..88063c9 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/BrightnessSliderControllerKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/BrightnessSliderControllerKosmos.kt
@@ -18,6 +18,7 @@
import com.android.internal.logging.uiEventLogger
import com.android.systemui.classifier.falsingManager
+import com.android.systemui.haptics.msdl.msdlPlayer
import com.android.systemui.haptics.vibratorHelper
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.plugins.activityStarter
@@ -31,6 +32,7 @@
falsingManager,
uiEventLogger,
vibratorHelper,
+ msdlPlayer,
systemClock,
activityStarter,
)
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
index a77ba62..ce1a292 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
@@ -64,6 +64,7 @@
import com.android.server.accessibility.AccessibilityManagerService;
import com.android.server.accessibility.AccessibilityTraceManager;
import com.android.server.accessibility.Flags;
+import com.android.server.input.InputManagerInternal;
import com.android.server.wm.WindowManagerInternal;
import java.util.ArrayList;
@@ -396,7 +397,7 @@
mCurrentMagnificationSpec.offsetX, mCurrentMagnificationSpec.offsetY)) {
sendSpecToAnimation(mCurrentMagnificationSpec, null);
}
- onMagnificationChangedLocked();
+ onMagnificationChangedLocked(/* isScaleTransient= */ false);
}
magnified.recycle();
}
@@ -474,8 +475,16 @@
return mIdOfLastServiceToMagnify;
}
+ /**
+ * This is invoked whenever magnification change happens.
+ *
+ * @param isScaleTransient represents that if the scale is being changed and the changed
+ * value may be short lived and be updated again soon.
+ * Calling the method usually notifies input manager to update the
+ * cursor scale, but setting this value {@code true} prevents it.
+ */
@GuardedBy("mLock")
- void onMagnificationChangedLocked() {
+ void onMagnificationChangedLocked(boolean isScaleTransient) {
final float scale = getScale();
final float centerX = getCenterX();
final float centerY = getCenterY();
@@ -498,6 +507,10 @@
} else {
hideThumbnail();
}
+
+ if (!isScaleTransient) {
+ notifyScaleForInput(mDisplayId, scale);
+ }
}
@GuardedBy("mLock")
@@ -611,8 +624,9 @@
* Directly Zooms out the scale to 1f with animating the transition. This method is
* triggered only by service automatically, such as when user context changed.
*/
+ @GuardedBy("mLock")
void zoomOutFromService() {
- setScaleAndCenter(1.0f, Float.NaN, Float.NaN,
+ setScaleAndCenter(1.0f, Float.NaN, Float.NaN, /* isScaleTransient= */ false,
transformToStubCallback(true),
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
mZoomedOutFromService = true;
@@ -640,7 +654,7 @@
setActivated(false);
if (changed) {
spec.clear();
- onMagnificationChangedLocked();
+ onMagnificationChangedLocked(/* isScaleTransient= */ false);
}
mIdOfLastServiceToMagnify = INVALID_SERVICE_ID;
sendSpecToAnimation(spec, animationCallback);
@@ -651,7 +665,7 @@
}
@GuardedBy("mLock")
- boolean setScale(float scale, float pivotX, float pivotY,
+ boolean setScale(float scale, float pivotX, float pivotY, boolean isScaleTransient,
boolean animate, int id) {
if (!mRegistered) {
return false;
@@ -674,12 +688,14 @@
final float centerX = normPivotX + offsetX;
final float centerY = normPivotY + offsetY;
mIdOfLastServiceToMagnify = id;
- return setScaleAndCenter(scale, centerX, centerY, transformToStubCallback(animate), id);
+ return setScaleAndCenter(scale, centerX, centerY, isScaleTransient,
+ transformToStubCallback(animate), id);
}
@GuardedBy("mLock")
boolean setScaleAndCenter(float scale, float centerX, float centerY,
- MagnificationAnimationCallback animationCallback, int id) {
+ boolean isScaleTransient, MagnificationAnimationCallback animationCallback,
+ int id) {
if (!mRegistered) {
return false;
}
@@ -696,7 +712,7 @@
+ animationCallback + ", id = " + id + ")");
}
boolean changed = setActivated(true);
- changed |= updateMagnificationSpecLocked(scale, centerX, centerY);
+ changed |= updateMagnificationSpecLocked(scale, centerX, centerY, isScaleTransient);
sendSpecToAnimation(mCurrentMagnificationSpec, animationCallback);
if (isActivated() && (id != INVALID_SERVICE_ID)) {
mIdOfLastServiceToMagnify = id;
@@ -773,7 +789,9 @@
* @return {@code true} if the magnification spec changed or {@code false}
* otherwise
*/
- boolean updateMagnificationSpecLocked(float scale, float centerX, float centerY) {
+ @GuardedBy("mLock")
+ boolean updateMagnificationSpecLocked(float scale, float centerX, float centerY,
+ boolean isScaleTransient) {
// Handle defaults.
if (Float.isNaN(centerX)) {
centerX = getCenterX();
@@ -801,7 +819,7 @@
changed |= updateCurrentSpecWithOffsetsLocked(nonNormOffsetX, nonNormOffsetY);
if (changed) {
- onMagnificationChangedLocked();
+ onMagnificationChangedLocked(isScaleTransient);
}
return changed;
@@ -816,7 +834,7 @@
final float nonNormOffsetX = mCurrentMagnificationSpec.offsetX - offsetX;
final float nonNormOffsetY = mCurrentMagnificationSpec.offsetY - offsetY;
if (updateCurrentSpecWithOffsetsLocked(nonNormOffsetX, nonNormOffsetY)) {
- onMagnificationChangedLocked();
+ onMagnificationChangedLocked(/* isScaleTransient= */ false);
}
if (id != INVALID_SERVICE_ID) {
mIdOfLastServiceToMagnify = id;
@@ -861,7 +879,7 @@
}
synchronized (mLock) {
mCurrentMagnificationSpec.setTo(lastSpecSent);
- onMagnificationChangedLocked();
+ onMagnificationChangedLocked(/* isScaleTransient= */ false);
}
}
});
@@ -955,6 +973,7 @@
context,
traceManager,
LocalServices.getService(WindowManagerInternal.class),
+ LocalServices.getService(InputManagerInternal.class),
new Handler(context.getMainLooper()),
context.getResources().getInteger(R.integer.config_longAnimTime)),
lock,
@@ -1464,20 +1483,24 @@
* @param scale the target scale, must be >= 1
* @param pivotX the screen-relative X coordinate around which to scale
* @param pivotY the screen-relative Y coordinate around which to scale
+ * @param isScaleTransient {@code true} if the scale is for a short time and potentially changed
+ * soon. {@code false} otherwise.
* @param animate {@code true} to animate the transition, {@code false}
* to transition immediately
* @param id the ID of the service requesting the change
* @return {@code true} if the magnification spec changed, {@code false} if
* the spec did not change
*/
+ @SuppressWarnings("GuardedBy")
+ // errorprone cannot recognize an inner class guarded by an outer class member.
public boolean setScale(int displayId, float scale, float pivotX, float pivotY,
- boolean animate, int id) {
+ boolean isScaleTransient, boolean animate, int id) {
synchronized (mLock) {
final DisplayMagnification display = mDisplays.get(displayId);
if (display == null) {
return false;
}
- return display.setScale(scale, pivotX, pivotY, animate, id);
+ return display.setScale(scale, pivotX, pivotY, isScaleTransient, animate, id);
}
}
@@ -1496,6 +1519,8 @@
* @return {@code true} if the magnification spec changed, {@code false} if
* the spec did not change
*/
+ @SuppressWarnings("GuardedBy")
+ // errorprone cannot recognize an inner class guarded by an outer class member.
public boolean setCenter(int displayId, float centerX, float centerY, boolean animate, int id) {
synchronized (mLock) {
final DisplayMagnification display = mDisplays.get(displayId);
@@ -1503,7 +1528,7 @@
return false;
}
return display.setScaleAndCenter(Float.NaN, centerX, centerY,
- animate ? STUB_ANIMATION_CALLBACK : null, id);
+ /* isScaleTransient= */ false, animate ? STUB_ANIMATION_CALLBACK : null, id);
}
}
@@ -1526,7 +1551,32 @@
*/
public boolean setScaleAndCenter(int displayId, float scale, float centerX, float centerY,
boolean animate, int id) {
- return setScaleAndCenter(displayId, scale, centerX, centerY,
+ return setScaleAndCenter(displayId, scale, centerX, centerY, /* isScaleTransient= */ false,
+ transformToStubCallback(animate), id);
+ }
+
+ /**
+ * Sets the scale and center of the magnified region, optionally
+ * animating the transition. If animation is disabled, the transition
+ * is immediate.
+ *
+ * @param displayId The logical display id.
+ * @param scale the target scale, or {@link Float#NaN} to leave unchanged
+ * @param centerX the screen-relative X coordinate around which to
+ * center and scale, or {@link Float#NaN} to leave unchanged
+ * @param centerY the screen-relative Y coordinate around which to
+ * center and scale, or {@link Float#NaN} to leave unchanged
+ * @param isScaleTransient {@code true} if the scale is for a short time and potentially changed
+ * soon. {@code false} otherwise.
+ * @param animate {@code true} to animate the transition, {@code false}
+ * to transition immediately
+ * @param id the ID of the service requesting the change
+ * @return {@code true} if the magnification spec changed, {@code false} if
+ * the spec did not change
+ */
+ public boolean setScaleAndCenter(int displayId, float scale, float centerX, float centerY,
+ boolean isScaleTransient, boolean animate, int id) {
+ return setScaleAndCenter(displayId, scale, centerX, centerY, isScaleTransient,
transformToStubCallback(animate), id);
}
@@ -1541,20 +1591,25 @@
* center and scale, or {@link Float#NaN} to leave unchanged
* @param centerY the screen-relative Y coordinate around which to
* center and scale, or {@link Float#NaN} to leave unchanged
+ * @param isScaleTransient {@code true} if the scale is for a short time and potentially changed
+ * soon. {@code false} otherwise.
* @param animationCallback Called when the animation result is valid.
* {@code null} to transition immediately
* @param id the ID of the service requesting the change
* @return {@code true} if the magnification spec changed, {@code false} if
* the spec did not change
*/
+ @SuppressWarnings("GuardedBy")
+ // errorprone cannot recognize an inner class guarded by an outer class member.
public boolean setScaleAndCenter(int displayId, float scale, float centerX, float centerY,
- MagnificationAnimationCallback animationCallback, int id) {
+ boolean isScaleTransient, MagnificationAnimationCallback animationCallback, int id) {
synchronized (mLock) {
final DisplayMagnification display = mDisplays.get(displayId);
if (display == null) {
return false;
}
- return display.setScaleAndCenter(scale, centerX, centerY, animationCallback, id);
+ return display.setScaleAndCenter(scale, centerX, centerY, isScaleTransient,
+ animationCallback, id);
}
}
@@ -1569,6 +1624,8 @@
* screen pixels.
* @param id the ID of the service requesting the change
*/
+ @SuppressWarnings("GuardedBy")
+ // errorprone cannot recognize an inner class guarded by an outer class member.
public void offsetMagnifiedRegion(int displayId, float offsetX, float offsetY, int id) {
synchronized (mLock) {
final DisplayMagnification display = mDisplays.get(displayId);
@@ -1640,6 +1697,8 @@
*/
public void persistScale(int displayId) {
final float scale = getScale(displayId);
+ notifyScaleForInput(displayId, scale);
+
if (scale < MagnificationConstants.PERSISTED_SCALE_MIN_VALUE) {
return;
}
@@ -1665,6 +1724,8 @@
*
* @param displayId The logical display id.
*/
+ @SuppressWarnings("GuardedBy")
+ // errorprone cannot recognize an inner class guarded by an outer class member.
private void zoomOutFromService(int displayId) {
synchronized (mLock) {
final DisplayMagnification display = mDisplays.get(displayId);
@@ -1691,6 +1752,20 @@
}
/**
+ * Notifies input manager that magnification scale changed non-transiently
+ * so that pointer cursor is scaled as well.
+ *
+ * @param displayId The logical display id.
+ * @param scale The new scale factor.
+ */
+ public void notifyScaleForInput(int displayId, float scale) {
+ if (Flags.magnificationEnlargePointer()) {
+ mControllerCtx.getInputManager()
+ .setAccessibilityPointerIconScaleFactor(displayId, scale);
+ }
+ }
+
+ /**
* Resets all displays' magnification if last magnifying service is disabled.
*
* @param connectionId
@@ -2166,6 +2241,7 @@
private final Context mContext;
private final AccessibilityTraceManager mTrace;
private final WindowManagerInternal mWindowManager;
+ private final InputManagerInternal mInputManager;
private final Handler mHandler;
private final Long mAnimationDuration;
@@ -2175,11 +2251,13 @@
public ControllerContext(@NonNull Context context,
@NonNull AccessibilityTraceManager traceManager,
@NonNull WindowManagerInternal windowManager,
+ @NonNull InputManagerInternal inputManager,
@NonNull Handler handler,
long animationDuration) {
mContext = context;
mTrace = traceManager;
mWindowManager = windowManager;
+ mInputManager = inputManager;
mHandler = handler;
mAnimationDuration = animationDuration;
}
@@ -2209,6 +2287,14 @@
}
/**
+ * @return InputManagerInternal
+ */
+ @NonNull
+ public InputManagerInternal getInputManager() {
+ return mInputManager;
+ }
+
+ /**
* @return Handler for main looper
*/
@NonNull
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
index 963334b..c6a966f 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
@@ -617,7 +617,8 @@
}
if (DEBUG_PANNING_SCALING) Slog.i(mLogTag, "Scaled content to: " + scale + "x");
- mFullScreenMagnificationController.setScale(mDisplayId, scale, pivotX, pivotY, false,
+ mFullScreenMagnificationController.setScale(mDisplayId, scale, pivotX, pivotY,
+ /* isScaleTransient= */ true, /* animate= */ false,
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
checkShouldDetectPassPersistedScale();
@@ -1974,6 +1975,7 @@
/* scale= */ scale,
/* centerX= */ mPivotEdge.x,
/* centerY= */ mPivotEdge.y,
+ /* isScaleTransient= */ true,
/* animate= */ true,
/* id= */ AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
if (scale == 1.0f) {
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
index 1489d16..d40e747 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
@@ -176,7 +176,8 @@
public void onPerformScaleAction(int displayId, float scale, boolean updatePersistence) {
if (getFullScreenMagnificationController().isActivated(displayId)) {
getFullScreenMagnificationController().setScaleAndCenter(displayId, scale,
- Float.NaN, Float.NaN, false, MAGNIFICATION_GESTURE_HANDLER_ID);
+ Float.NaN, Float.NaN, /* isScaleTransient= */ !updatePersistence, false,
+ MAGNIFICATION_GESTURE_HANDLER_ID);
if (updatePersistence) {
getFullScreenMagnificationController().persistScale(displayId);
}
@@ -371,7 +372,7 @@
}
screenMagnificationController.setScaleAndCenter(displayId, targetScale,
magnificationCenter.x, magnificationCenter.y,
- magnificationAnimationCallback, id);
+ /* isScaleTransient= */ false, magnificationAnimationCallback, id);
} else {
if (screenMagnificationController.isRegistered(displayId)) {
screenMagnificationController.reset(displayId, false);
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index c47cad9..28b606c 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -3178,12 +3178,15 @@
mStats.collectPowerStatsSamples();
}
- BatteryUsageStats batteryUsageStats =
- mBatteryUsageStatsProvider.getBatteryUsageStats(mStats, query);
- if (proto) {
- batteryUsageStats.dumpToProto(fd);
- } else {
- batteryUsageStats.dump(pw, " ");
+ try (BatteryUsageStats batteryUsageStats =
+ mBatteryUsageStatsProvider.getBatteryUsageStats(mStats, query)) {
+ if (proto) {
+ batteryUsageStats.dumpToProto(fd);
+ } else {
+ batteryUsageStats.dump(pw, " ");
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "Cannot close BatteryUsageStats", e);
}
}
diff --git a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
index ba4b71c..17fcbf4 100644
--- a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
@@ -22,7 +22,7 @@
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
import static com.android.server.am.ActivityManagerService.MY_PID;
import static com.android.server.am.ProcessRecord.TAG;
-import static com.android.server.stats.pull.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;
+import static com.android.internal.os.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -58,7 +58,7 @@
import com.android.modules.expresslog.Counter;
import com.android.server.ResourcePressureUtil;
import com.android.server.criticalevents.CriticalEventLog;
-import com.android.server.stats.pull.ProcfsMemoryUtil.MemorySnapshot;
+import com.android.internal.os.ProcfsMemoryUtil.MemorySnapshot;
import com.android.server.wm.WindowProcessController;
import java.io.File;
diff --git a/services/core/java/com/android/server/input/InputManagerInternal.java b/services/core/java/com/android/server/input/InputManagerInternal.java
index 99f7f12..c888eef 100644
--- a/services/core/java/com/android/server/input/InputManagerInternal.java
+++ b/services/core/java/com/android/server/input/InputManagerInternal.java
@@ -262,4 +262,12 @@
*/
public abstract void handleKeyGestureInKeyGestureController(int deviceId, int[] keycodes,
int modifierState, @KeyGestureEvent.KeyGestureType int event);
+
+ /**
+ * Sets the magnification scale factor for pointer icons.
+ *
+ * @param displayId the ID of the display where the new scale factor is applied.
+ * @param scaleFactor the new scale factor to be applied for pointer icons.
+ */
+ public abstract void setAccessibilityPointerIconScaleFactor(int displayId, float scaleFactor);
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 8acf583..98e5319 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -3506,6 +3506,11 @@
int modifierState, @KeyGestureEvent.KeyGestureType int gestureType) {
mKeyGestureController.handleKeyGesture(deviceId, keycodes, modifierState, gestureType);
}
+
+ @Override
+ public void setAccessibilityPointerIconScaleFactor(int displayId, float scaleFactor) {
+ InputManagerService.this.setAccessibilityPointerIconScaleFactor(displayId, scaleFactor);
+ }
}
@Override
@@ -3688,6 +3693,10 @@
mPointerIconCache.setPointerScale(scale);
}
+ void setAccessibilityPointerIconScaleFactor(int displayId, float scaleFactor) {
+ mPointerIconCache.setAccessibilityScaleFactor(displayId, scaleFactor);
+ }
+
interface KeyboardBacklightControllerInterface {
default void incrementKeyboardBacklight(int deviceId) {}
default void decrementKeyboardBacklight(int deviceId) {}
diff --git a/services/core/java/com/android/server/input/PointerIconCache.java b/services/core/java/com/android/server/input/PointerIconCache.java
index 297cd68..e16031c 100644
--- a/services/core/java/com/android/server/input/PointerIconCache.java
+++ b/services/core/java/com/android/server/input/PointerIconCache.java
@@ -27,6 +27,7 @@
import android.os.Handler;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseDoubleArray;
import android.util.SparseIntArray;
import android.view.ContextThemeWrapper;
import android.view.Display;
@@ -34,6 +35,7 @@
import android.view.PointerIcon;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.UiThread;
import java.util.Objects;
@@ -51,7 +53,7 @@
private final NativeInputManagerService mNative;
// We use the UI thread for loading pointer icons.
- private final Handler mUiThreadHandler = UiThread.getHandler();
+ private final Handler mUiThreadHandler;
@GuardedBy("mLoadedPointerIconsByDisplayAndType")
private final SparseArray<SparseArray<PointerIcon>> mLoadedPointerIconsByDisplayAndType =
@@ -70,6 +72,9 @@
POINTER_ICON_VECTOR_STYLE_STROKE_WHITE;
@GuardedBy("mLoadedPointerIconsByDisplayAndType")
private float mPointerIconScale = DEFAULT_POINTER_SCALE;
+ // Note that android doesn't have SparseFloatArray, so this falls back to use double instead.
+ @GuardedBy("mLoadedPointerIconsByDisplayAndType")
+ private final SparseDoubleArray mAccessibilityScaleFactorPerDisplay = new SparseDoubleArray();
private final DisplayManager.DisplayListener mDisplayListener =
new DisplayManager.DisplayListener() {
@@ -86,6 +91,7 @@
mLoadedPointerIconsByDisplayAndType.remove(displayId);
mDisplayContexts.remove(displayId);
mDisplayDensities.delete(displayId);
+ mAccessibilityScaleFactorPerDisplay.delete(displayId);
}
}
@@ -96,8 +102,15 @@
};
/* package */ PointerIconCache(Context context, NativeInputManagerService nativeService) {
+ this(context, nativeService, UiThread.getHandler());
+ }
+
+ @VisibleForTesting
+ /* package */ PointerIconCache(Context context, NativeInputManagerService nativeService,
+ Handler handler) {
mContext = context;
mNative = nativeService;
+ mUiThreadHandler = handler;
}
public void systemRunning() {
@@ -134,6 +147,11 @@
mUiThreadHandler.post(() -> handleSetPointerScale(scale));
}
+ /** Set the scale for accessibility (magnification) for vector pointer icons. */
+ public void setAccessibilityScaleFactor(int displayId, float scaleFactor) {
+ mUiThreadHandler.post(() -> handleAccessibilityScaleFactor(displayId, scaleFactor));
+ }
+
/**
* Get a loaded system pointer icon. This will fetch the icon from the cache, or load it if
* it isn't already cached.
@@ -155,8 +173,10 @@
/* force= */ true);
theme.applyStyle(PointerIcon.vectorStrokeStyleToResource(mPointerIconStrokeStyle),
/* force= */ true);
+ final float scale = mPointerIconScale
+ * (float) mAccessibilityScaleFactorPerDisplay.get(displayId, 1f);
icon = PointerIcon.getLoadedSystemIcon(new ContextThemeWrapper(context, theme),
- type, mUseLargePointerIcons, mPointerIconScale);
+ type, mUseLargePointerIcons, scale);
iconsByType.put(type, icon);
}
return Objects.requireNonNull(icon);
@@ -261,6 +281,19 @@
mNative.reloadPointerIcons();
}
+ @android.annotation.UiThread
+ private void handleAccessibilityScaleFactor(int displayId, float scale) {
+ synchronized (mLoadedPointerIconsByDisplayAndType) {
+ if (mAccessibilityScaleFactorPerDisplay.get(displayId, 1f) == scale) {
+ return;
+ }
+ mAccessibilityScaleFactorPerDisplay.put(displayId, scale);
+ // Clear cached icons on the display.
+ mLoadedPointerIconsByDisplayAndType.remove(displayId);
+ }
+ mNative.reloadPointerIcons();
+ }
+
// Updates the cached display density for the given displayId, and returns true if
// the cached density changed.
@GuardedBy("mLoadedPointerIconsByDisplayAndType")
diff --git a/services/core/java/com/android/server/power/stats/AccumulatedBatteryUsageStatsSection.java b/services/core/java/com/android/server/power/stats/AccumulatedBatteryUsageStatsSection.java
index dd6d5db..c0a06fc 100644
--- a/services/core/java/com/android/server/power/stats/AccumulatedBatteryUsageStatsSection.java
+++ b/services/core/java/com/android/server/power/stats/AccumulatedBatteryUsageStatsSection.java
@@ -51,6 +51,11 @@
mBatteryUsageStats.build().dump(ipw, "");
}
+ @Override
+ public void close() {
+ mBatteryUsageStats.discard();
+ }
+
static class Reader implements PowerStatsSpan.SectionReader {
@Override
public String getType() {
diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
index c04158f..48174a6 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -11509,9 +11509,6 @@
mOnBatteryTimeBase);
}
- mPerDisplayBatteryStats = new DisplayBatteryStats[1];
- mPerDisplayBatteryStats[0] = new DisplayBatteryStats(mClock, mOnBatteryTimeBase);
-
mInteractiveTimer = new StopwatchTimer(mClock, null, -10, null, mOnBatteryTimeBase);
mPowerSaveModeEnabledTimer = new StopwatchTimer(mClock, null, -2, null,
mOnBatteryTimeBase);
diff --git a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
index 265f1dfc..b996c43 100644
--- a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
+++ b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
@@ -295,7 +295,8 @@
stats.builder = ((AccumulatedBatteryUsageStatsSection) section)
.getBatteryUsageStatsBuilder();
stats.startWallClockTime = powerStatsSpan.getMetadata().getStartTime();
- stats.startMonotonicTime = powerStatsSpan.getMetadata().getStartMonotonicTime();
+ stats.startMonotonicTime =
+ powerStatsSpan.getMetadata().getStartMonotonicTime();
stats.endMonotonicTime = powerStatsSpan.getMetadata().getEndMonotonicTime();
break;
}
@@ -484,29 +485,30 @@
continue;
}
- PowerStatsSpan powerStatsSpan = mPowerStatsStore.loadPowerStatsSpan(
- spanMetadata.getId(), BatteryUsageStatsSection.TYPE);
- if (powerStatsSpan == null) {
- continue;
- }
-
- for (PowerStatsSpan.Section section : powerStatsSpan.getSections()) {
- BatteryUsageStats snapshot =
- ((BatteryUsageStatsSection) section).getBatteryUsageStats();
- if (!Arrays.equals(snapshot.getCustomPowerComponentNames(),
- customEnergyConsumerNames)) {
- Log.w(TAG, "Ignoring older BatteryUsageStats snapshot, which has different "
- + "custom power components: "
- + Arrays.toString(snapshot.getCustomPowerComponentNames()));
+ try (PowerStatsSpan powerStatsSpan = mPowerStatsStore.loadPowerStatsSpan(
+ spanMetadata.getId(), BatteryUsageStatsSection.TYPE)) {
+ if (powerStatsSpan == null) {
continue;
}
- if (includeProcessStateData && !snapshot.isProcessStateDataIncluded()) {
- Log.w(TAG, "Ignoring older BatteryUsageStats snapshot, which "
- + " does not include process state data");
- continue;
+ for (PowerStatsSpan.Section section : powerStatsSpan.getSections()) {
+ BatteryUsageStats snapshot =
+ ((BatteryUsageStatsSection) section).getBatteryUsageStats();
+ if (!Arrays.equals(snapshot.getCustomPowerComponentNames(),
+ customEnergyConsumerNames)) {
+ Log.w(TAG, "Ignoring older BatteryUsageStats snapshot, which has different "
+ + "custom power components: "
+ + Arrays.toString(snapshot.getCustomPowerComponentNames()));
+ continue;
+ }
+
+ if (includeProcessStateData && !snapshot.isProcessStateDataIncluded()) {
+ Log.w(TAG, "Ignoring older BatteryUsageStats snapshot, which "
+ + " does not include process state data");
+ continue;
+ }
+ builder.add(snapshot);
}
- builder.add(snapshot);
}
}
return builder.build();
diff --git a/services/core/java/com/android/server/power/stats/BatteryUsageStatsSection.java b/services/core/java/com/android/server/power/stats/BatteryUsageStatsSection.java
index af36524..eb896e9 100644
--- a/services/core/java/com/android/server/power/stats/BatteryUsageStatsSection.java
+++ b/services/core/java/com/android/server/power/stats/BatteryUsageStatsSection.java
@@ -18,6 +18,7 @@
import android.os.BatteryUsageStats;
import android.util.IndentingPrintWriter;
+import android.util.Slog;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
@@ -28,6 +29,7 @@
class BatteryUsageStatsSection extends PowerStatsSpan.Section {
public static final String TYPE = "battery-usage-stats";
+ private static final String TAG = "BatteryUsageStatsSection";
private final BatteryUsageStats mBatteryUsageStats;
@@ -50,6 +52,15 @@
mBatteryUsageStats.dump(ipw, "");
}
+ @Override
+ public void close() {
+ try {
+ mBatteryUsageStats.close();
+ } catch (IOException e) {
+ Slog.e(TAG, "Closing BatteryUsageStats", e);
+ }
+ }
+
static class Reader implements PowerStatsSpan.SectionReader {
@Override
public String getType() {
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsSpan.java b/services/core/java/com/android/server/power/stats/PowerStatsSpan.java
index 5105272..4f560cf 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsSpan.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsSpan.java
@@ -51,7 +51,7 @@
/**
* Contains power stats of various kinds, aggregated over a time span.
*/
-public class PowerStatsSpan {
+public class PowerStatsSpan implements AutoCloseable {
private static final String TAG = "PowerStatsStore";
/**
@@ -321,6 +321,13 @@
public void dump(IndentingPrintWriter ipw) {
ipw.println(mType);
}
+
+ /**
+ * Closes the section, releasing any resources it held. Once closed, the Section
+ * should not be used.
+ */
+ public void close() {
+ }
}
/**
@@ -484,4 +491,10 @@
ipw.decreaseIndent();
}
}
+ @Override
+ public void close() {
+ for (int i = 0; i < mSections.size(); i++) {
+ mSections.get(i).close();
+ }
+ }
}
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsStore.java b/services/core/java/com/android/server/power/stats/PowerStatsStore.java
index 3673617..d83d355 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsStore.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsStore.java
@@ -331,9 +331,10 @@
ipw.increaseIndent();
List<PowerStatsSpan.Metadata> contents = getTableOfContents();
for (PowerStatsSpan.Metadata metadata : contents) {
- PowerStatsSpan span = loadPowerStatsSpan(metadata.getId());
- if (span != null) {
- span.dump(ipw);
+ try (PowerStatsSpan span = loadPowerStatsSpan(metadata.getId())) {
+ if (span != null) {
+ span.dump(ipw);
+ }
}
}
ipw.decreaseIndent();
diff --git a/services/core/java/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessor.java
index 32dfdf9..5f93bdf 100644
--- a/services/core/java/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessor.java
@@ -50,12 +50,14 @@
return;
}
- if (mScreenPowerStatsDescriptor == null) {
- mScreenPowerStatsDescriptor = screenStats.getPowerStatsDescriptor();
- if (mScreenPowerStatsDescriptor == null) {
- return;
- }
+ PowerStats.Descriptor screenDescriptor = screenStats.getPowerStatsDescriptor();
+ if (screenDescriptor == null) {
+ return;
+ }
+ if (mScreenPowerStatsDescriptor == null
+ || !mScreenPowerStatsDescriptor.equals(screenDescriptor)) {
+ mScreenPowerStatsDescriptor = screenDescriptor;
mScreenPowerStatsLayout = new ScreenPowerStatsLayout(mScreenPowerStatsDescriptor);
mTmpScreenStats = new long[mScreenPowerStatsDescriptor.statsArrayLength];
}
diff --git a/services/core/java/com/android/server/power/stats/processor/PowerStatsExporter.java b/services/core/java/com/android/server/power/stats/processor/PowerStatsExporter.java
index c8170a1..b2442c8 100644
--- a/services/core/java/com/android/server/power/stats/processor/PowerStatsExporter.java
+++ b/services/core/java/com/android/server/power/stats/processor/PowerStatsExporter.java
@@ -105,19 +105,19 @@
maxEndTime = spanMaxTime;
}
- PowerStatsSpan span = mPowerStatsStore.loadPowerStatsSpan(metadata.getId(),
- AggregatedPowerStatsSection.TYPE);
- if (span == null) {
- Slog.e(TAG, "Could not read PowerStatsStore section " + metadata);
- continue;
- }
- List<PowerStatsSpan.Section> sections = span.getSections();
- for (int k = 0; k < sections.size(); k++) {
- hasStoredSpans = true;
- PowerStatsSpan.Section section = sections.get(k);
- populateBatteryUsageStatsBuilder(batteryUsageStatsBuilder,
- ((AggregatedPowerStatsSection) section).getAggregatedPowerStats());
- // TODO(b/371614748): close the builder
+ try (PowerStatsSpan span = mPowerStatsStore.loadPowerStatsSpan(metadata.getId(),
+ AggregatedPowerStatsSection.TYPE)) {
+ if (span == null) {
+ Slog.e(TAG, "Could not read PowerStatsStore section " + metadata);
+ continue;
+ }
+ List<PowerStatsSpan.Section> sections = span.getSections();
+ for (int k = 0; k < sections.size(); k++) {
+ hasStoredSpans = true;
+ PowerStatsSpan.Section section = sections.get(k);
+ populateBatteryUsageStatsBuilder(batteryUsageStatsBuilder,
+ ((AggregatedPowerStatsSection) section).getAggregatedPowerStats());
+ }
}
}
diff --git a/services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java
index b295e30..8e7498f 100644
--- a/services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java
@@ -89,14 +89,15 @@
return true;
}
- mLastUsedDescriptor = descriptor;
- mStatsLayout = new ScreenPowerStatsLayout(descriptor);
- if (mStatsLayout.getDisplayCount() != mDisplayCount) {
- Slog.e(TAG, "Incompatible number of displays: " + mStatsLayout.getDisplayCount()
+ ScreenPowerStatsLayout statsLayout = new ScreenPowerStatsLayout(descriptor);
+ if (statsLayout.getDisplayCount() != mDisplayCount) {
+ Slog.e(TAG, "Incompatible number of displays: " + statsLayout.getDisplayCount()
+ ", expected: " + mDisplayCount);
return false;
}
+ mLastUsedDescriptor = descriptor;
+ mStatsLayout = statsLayout;
mTmpDeviceStatsArray = new long[descriptor.statsArrayLength];
mTmpUidStatsArray = new long[descriptor.uidStatsArrayLength];
return true;
diff --git a/services/core/java/com/android/server/security/forensic/BackupTransportConnection.java b/services/core/java/com/android/server/security/forensic/BackupTransportConnection.java
new file mode 100644
index 0000000..caca011
--- /dev/null
+++ b/services/core/java/com/android/server/security/forensic/BackupTransportConnection.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2024 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 com.android.server.security.forensic;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.security.forensic.ForensicEvent;
+import android.security.forensic.IBackupTransport;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import com.android.internal.infra.AndroidFuture;
+
+import java.util.List;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public class BackupTransportConnection implements ServiceConnection {
+ private static final String TAG = "BackupTransportConnection";
+ private static final long FUTURE_TIMEOUT_MILLIS = 60 * 1000; // 1 mins
+ private final Context mContext;
+ private String mForensicBackupTransportConfig;
+ volatile IBackupTransport mService;
+
+ public BackupTransportConnection(Context context) {
+ mContext = context;
+ mService = null;
+ }
+
+ /**
+ * Initialize the BackupTransport binder service.
+ * @return Whether the initialization succeed.
+ */
+ public boolean initialize() {
+ if (!bindService()) {
+ return false;
+ }
+ AndroidFuture<Integer> resultFuture = new AndroidFuture<>();
+ try {
+ mService.initialize(resultFuture);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote Exception", e);
+ unbindService();
+ return false;
+ }
+ Integer result = getFutureResult(resultFuture);
+ if (result != null && result == 0) {
+ return true;
+ } else {
+ unbindService();
+ return false;
+ }
+ }
+
+ /**
+ * Add data to the BackupTransport binder service.
+ * @param data List of ForensicEvent.
+ * @return Whether the data is added to the binder service.
+ */
+ public boolean addData(List<ForensicEvent> data) {
+ AndroidFuture<Integer> resultFuture = new AndroidFuture<>();
+ try {
+ mService.addData(data, resultFuture);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote Exception", e);
+ return false;
+ }
+ Integer result = getFutureResult(resultFuture);
+ return result != null && result == 0;
+ }
+
+ /**
+ * Release the BackupTransport binder service.
+ */
+ public void release() {
+ AndroidFuture<Integer> resultFuture = new AndroidFuture<>();
+ try {
+ mService.release(resultFuture);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote Exception", e);
+ } finally {
+ unbindService();
+ }
+ }
+
+ private <T> T getFutureResult(AndroidFuture<T> future) {
+ try {
+ return future.get(FUTURE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException | ExecutionException | TimeoutException
+ | CancellationException e) {
+ Slog.w(TAG, "Failed to get result from transport:", e);
+ return null;
+ }
+ }
+
+ private boolean bindService() {
+ mForensicBackupTransportConfig = mContext.getString(
+ com.android.internal.R.string.config_forensicBackupTransport);
+ if (TextUtils.isEmpty(mForensicBackupTransportConfig)) {
+ return false;
+ }
+
+ ComponentName serviceComponent =
+ ComponentName.unflattenFromString(mForensicBackupTransportConfig);
+ if (serviceComponent == null) {
+ return false;
+ }
+
+ Intent intent = new Intent().setComponent(serviceComponent);
+ boolean result = mContext.bindServiceAsUser(
+ intent, this, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM);
+ if (!result) {
+ unbindService();
+ }
+ return result;
+ }
+
+ private void unbindService() {
+ mContext.unbindService(this);
+ mService = null;
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ mService = IBackupTransport.Stub.asInterface(service);
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ mService = null;
+ }
+}
diff --git a/services/core/java/com/android/server/security/forensic/ForensicService.java b/services/core/java/com/android/server/security/forensic/ForensicService.java
index 07639d1..20c648e 100644
--- a/services/core/java/com/android/server/security/forensic/ForensicService.java
+++ b/services/core/java/com/android/server/security/forensic/ForensicService.java
@@ -63,6 +63,7 @@
private final Context mContext;
private final Handler mHandler;
+ private final BackupTransportConnection mBackupTransportConnection;
private final BinderService mBinderService;
private final ArrayList<IForensicServiceStateCallback> mStateMonitors = new ArrayList<>();
@@ -77,6 +78,7 @@
super(injector.getContext());
mContext = injector.getContext();
mHandler = new EventHandler(injector.getLooper(), this);
+ mBackupTransportConnection = injector.getBackupTransportConnection();
mBinderService = new BinderService(this);
}
@@ -221,6 +223,10 @@
private void enable(IForensicServiceCommandCallback callback) throws RemoteException {
switch (mState) {
case STATE_VISIBLE:
+ if (!mBackupTransportConnection.initialize()) {
+ callback.onFailure(ERROR_BACKUP_TRANSPORT_UNAVAILABLE);
+ break;
+ }
mState = STATE_ENABLED;
notifyStateMonitors();
callback.onSuccess();
@@ -236,6 +242,7 @@
private void disable(IForensicServiceCommandCallback callback) throws RemoteException {
switch (mState) {
case STATE_ENABLED:
+ mBackupTransportConnection.release();
mState = STATE_VISIBLE;
notifyStateMonitors();
callback.onSuccess();
@@ -266,6 +273,8 @@
Context getContext();
Looper getLooper();
+
+ BackupTransportConnection getBackupTransportConnection();
}
private static final class InjectorImpl implements Injector {
@@ -289,6 +298,11 @@
serviceThread.start();
return serviceThread.getLooper();
}
+
+ @Override
+ public BackupTransportConnection getBackupTransportConnection() {
+ return new BackupTransportConnection(mContext);
+ }
}
}
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index e7735d8..54e4f8e 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -48,6 +48,9 @@
import static android.util.MathUtils.constrain;
import static android.view.Display.HdrCapabilities.HDR_TYPE_INVALID;
+import static com.android.internal.os.ProcfsMemoryUtil.getProcessCmdlines;
+import static com.android.internal.os.ProcfsMemoryUtil.readCmdlineFromProcfs;
+import static com.android.internal.os.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;
import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_STATS__GESTURE_SHORTCUT_TYPE__TRIPLE_TAP;
import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_STATS__HARDWARE_SHORTCUT_TYPE__VOLUME_KEY;
@@ -68,9 +71,6 @@
import static com.android.server.stats.Flags.applyNetworkStatsPollRateLimit;
import static com.android.server.stats.pull.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs;
import static com.android.server.stats.pull.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs;
-import static com.android.server.stats.pull.ProcfsMemoryUtil.getProcessCmdlines;
-import static com.android.server.stats.pull.ProcfsMemoryUtil.readCmdlineFromProcfs;
-import static com.android.server.stats.pull.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;
import static com.android.server.stats.pull.netstats.NetworkStatsUtils.fromPublicNetworkStats;
import static com.android.server.stats.pull.netstats.NetworkStatsUtils.isAddEntriesSupported;
@@ -209,6 +209,8 @@
import com.android.internal.os.LooperStats;
import com.android.internal.os.PowerProfile;
import com.android.internal.os.ProcessCpuTracker;
+import com.android.internal.os.ProcfsMemoryUtil;
+import com.android.internal.os.ProcfsMemoryUtil.MemorySnapshot;
import com.android.internal.os.SelectedProcessCpuThreadReader;
import com.android.internal.os.StoragedUidIoStatsReader;
import com.android.internal.util.CollectionUtils;
@@ -229,7 +231,6 @@
import com.android.server.power.stats.KernelWakelockStats;
import com.android.server.power.stats.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
import com.android.server.stats.pull.IonMemoryUtil.IonAllocations;
-import com.android.server.stats.pull.ProcfsMemoryUtil.MemorySnapshot;
import com.android.server.stats.pull.netstats.NetworkStatsAccumulator;
import com.android.server.stats.pull.netstats.NetworkStatsExt;
import com.android.server.stats.pull.netstats.SubInfo;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 4f71719..567eca2 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -2572,14 +2572,21 @@
wpc.computeProcessActivityState();
}
- void computeProcessActivityStateBatch() {
+ boolean computeProcessActivityStateBatch() {
if (mActivityStateChangedProcs.isEmpty()) {
- return;
+ return false;
}
+ boolean changed = false;
for (int i = mActivityStateChangedProcs.size() - 1; i >= 0; i--) {
- mActivityStateChangedProcs.get(i).computeProcessActivityState();
+ final WindowProcessController wpc = mActivityStateChangedProcs.get(i);
+ final int prevState = wpc.getActivityStateFlags();
+ wpc.computeProcessActivityState();
+ if (!changed && prevState != wpc.getActivityStateFlags()) {
+ changed = true;
+ }
}
mActivityStateChangedProcs.clear();
+ return changed;
}
/**
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index ccd5996..6cc4b1e 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -994,7 +994,9 @@
// Ensure the final animation targets which hidden by transition could be visible.
for (int i = 0; i < targets.size(); i++) {
final WindowContainer wc = targets.get(i).mContainer;
- wc.prepareSurfaces();
+ if (wc.mSurfaceControl != null) {
+ wc.prepareSurfaces();
+ }
}
// The pending builder could be cleared due to prepareSurfaces
@@ -1328,16 +1330,13 @@
if (!allWindowDrawn) {
return;
}
- final SurfaceControl startingSurface = mOpenAnimAdaptor.mStartingSurface;
- if (startingSurface != null && startingSurface.isValid()) {
- startTransaction.addTransactionCommittedListener(Runnable::run, () -> {
- synchronized (mWindowManagerService.mGlobalLock) {
- if (mOpenAnimAdaptor != null) {
- mOpenAnimAdaptor.cleanUpWindowlessSurface(true);
- }
+ startTransaction.addTransactionCommittedListener(Runnable::run, () -> {
+ synchronized (mWindowManagerService.mGlobalLock) {
+ if (mOpenAnimAdaptor != null) {
+ mOpenAnimAdaptor.cleanUpWindowlessSurface(true);
}
- });
- }
+ }
+ });
}
void clearBackAnimateTarget(boolean cancel) {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 41a5804..6707a27 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -105,6 +105,7 @@
import android.content.pm.UserProperties;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.graphics.Region;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.power.Mode;
@@ -153,6 +154,7 @@
import com.android.server.policy.PermissionPolicyInternal;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.utils.Slogf;
+import com.android.server.wm.utils.RegionUtils;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -270,6 +272,8 @@
private boolean mTaskLayersChanged = true;
private int mTmpTaskLayerRank;
private final RankTaskLayersRunnable mRankTaskLayersRunnable = new RankTaskLayersRunnable();
+ private Region mTmpOccludingRegion;
+ private Region mTmpTaskRegion;
private String mDestroyAllActivitiesReason;
private final Runnable mDestroyAllActivitiesRunnable = new Runnable() {
@@ -2921,6 +2925,11 @@
});
}
+ void invalidateTaskLayersAndUpdateOomAdjIfNeeded() {
+ mRankTaskLayersRunnable.mCheckUpdateOomAdj = true;
+ invalidateTaskLayers();
+ }
+
void invalidateTaskLayers() {
if (!mTaskLayersChanged) {
mTaskLayersChanged = true;
@@ -2938,13 +2947,18 @@
// Only rank for leaf tasks because the score of activity is based on immediate parent.
forAllLeafTasks(task -> {
final int oldRank = task.mLayerRank;
- final ActivityRecord r = task.topRunningActivityLocked();
- if (r != null && r.isVisibleRequested()) {
+ final int oldRatio = task.mNonOccludedFreeformAreaRatio;
+ task.mNonOccludedFreeformAreaRatio = 0;
+ if (task.isVisibleRequested()) {
task.mLayerRank = ++mTmpTaskLayerRank;
+ if (task.inFreeformWindowingMode()) {
+ computeNonOccludedFreeformAreaRatio(task);
+ }
} else {
task.mLayerRank = Task.LAYER_RANK_INVISIBLE;
}
- if (task.mLayerRank != oldRank) {
+ if (task.mLayerRank != oldRank
+ || task.mNonOccludedFreeformAreaRatio != oldRatio) {
task.forAllActivities(activity -> {
if (activity.hasProcess()) {
mTaskSupervisor.onProcessActivityStateChanged(activity.app,
@@ -2953,10 +2967,40 @@
});
}
}, true /* traverseTopToBottom */);
-
- if (!mTaskSupervisor.inActivityVisibilityUpdate()) {
- mTaskSupervisor.computeProcessActivityStateBatch();
+ if (mTmpOccludingRegion != null) {
+ mTmpOccludingRegion.setEmpty();
}
+ boolean changed = false;
+ if (!mTaskSupervisor.inActivityVisibilityUpdate()) {
+ changed = mTaskSupervisor.computeProcessActivityStateBatch();
+ }
+ if (mRankTaskLayersRunnable.mCheckUpdateOomAdj) {
+ mRankTaskLayersRunnable.mCheckUpdateOomAdj = false;
+ if (changed) {
+ mService.updateOomAdj();
+ }
+ }
+ }
+
+ /** This method is called for visible freeform task from top to bottom. */
+ private void computeNonOccludedFreeformAreaRatio(@NonNull Task task) {
+ if (!com.android.window.flags.Flags.processPriorityPolicyForMultiWindowMode()) {
+ return;
+ }
+ if (mTmpOccludingRegion == null) {
+ mTmpOccludingRegion = new Region();
+ mTmpTaskRegion = new Region();
+ }
+ final Rect taskBounds = task.getBounds();
+ mTmpTaskRegion.set(taskBounds);
+ // Exclude the area outside the display.
+ mTmpTaskRegion.op(task.mDisplayContent.getBounds(), Region.Op.INTERSECT);
+ // Exclude the area covered by the above tasks.
+ mTmpTaskRegion.op(mTmpOccludingRegion, Region.Op.DIFFERENCE);
+ task.mNonOccludedFreeformAreaRatio = 100 * RegionUtils.getAreaSize(mTmpTaskRegion)
+ / (taskBounds.width() * taskBounds.height());
+ // Accumulate the occluding region for other visible tasks behind.
+ mTmpOccludingRegion.op(taskBounds, Region.Op.UNION);
}
void clearOtherAppTimeTrackers(AppTimeTracker except) {
@@ -3862,6 +3906,8 @@
}
private class RankTaskLayersRunnable implements Runnable {
+ boolean mCheckUpdateOomAdj;
+
@Override
public void run() {
synchronized (mService.mGlobalLock) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 4861341..8a624b3 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -432,6 +432,9 @@
// This number will be assigned when we evaluate OOM scores for all visible tasks.
int mLayerRank = LAYER_RANK_INVISIBLE;
+ /** A 0~100 ratio to indicate the percentage of visible area on screen of a freeform task. */
+ int mNonOccludedFreeformAreaRatio;
+
/* Unique identifier for this task. */
final int mTaskId;
/* User for which this task was created. */
@@ -1207,6 +1210,28 @@
}
@Override
+ void onResize() {
+ super.onResize();
+ updateTaskLayerForFreeform();
+ }
+
+ @Override
+ void onMovedByResize() {
+ super.onMovedByResize();
+ updateTaskLayerForFreeform();
+ }
+
+ private void updateTaskLayerForFreeform() {
+ if (!com.android.window.flags.Flags.processPriorityPolicyForMultiWindowMode()) {
+ return;
+ }
+ if (!isVisibleRequested() || !inFreeformWindowingMode()) {
+ return;
+ }
+ mRootWindowContainer.invalidateTaskLayersAndUpdateOomAdjIfNeeded();
+ }
+
+ @Override
@Nullable
ActivityRecord getTopResumedActivity() {
if (!isLeafTask()) {
@@ -3410,6 +3435,36 @@
info.requestedVisibleTypes = (windowState != null && Flags.enableFullyImmersiveInDesktop())
? windowState.getRequestedVisibleTypes() : WindowInsets.Type.defaultVisible();
AppCompatUtils.fillAppCompatTaskInfo(this, info, top);
+ info.topActivityMainWindowFrame = calculateTopActivityMainWindowFrameForTaskInfo(top);
+ }
+
+ /**
+ * Returns the top activity's main window frame if it doesn't match
+ * {@link ActivityRecord#getBounds() the top activity bounds}, or {@code null}, otherwise.
+ *
+ * @param top The top running activity of the task
+ */
+ @Nullable
+ private static Rect calculateTopActivityMainWindowFrameForTaskInfo(
+ @Nullable ActivityRecord top) {
+ if (!Flags.betterSupportNonMatchParentActivity()) {
+ return null;
+ }
+ if (top == null) {
+ return null;
+ }
+ final WindowState mainWindow = top.findMainWindow();
+ if (mainWindow == null) {
+ return null;
+ }
+ if (!mainWindow.mHaveFrame) {
+ return null;
+ }
+ final Rect windowFrame = mainWindow.getFrame();
+ if (top.getBounds().equals(windowFrame)) {
+ return null;
+ }
+ return windowFrame;
}
/**
@@ -5919,6 +5974,10 @@
pw.print(prefix); pw.print(" mLastNonFullscreenBounds=");
pw.println(mLastNonFullscreenBounds);
}
+ if (mNonOccludedFreeformAreaRatio != 0) {
+ pw.print(prefix); pw.print(" mNonOccludedFreeformAreaRatio=");
+ pw.println(mNonOccludedFreeformAreaRatio);
+ }
if (isLeafTask()) {
pw.println(prefix + " isSleeping=" + shouldSleepActivities());
printThisActivity(pw, getTopPausingActivity(), dumpPackage, false,
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 3ffeacf..d6ba312 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -3027,7 +3027,11 @@
// The task order may be changed by finishIfPossible() for adjusting focus if there are
// nested tasks, so add all activities into a list to avoid missed removals.
final ArrayList<ActivityRecord> removingActivities = new ArrayList<>();
- forAllActivities((Consumer<ActivityRecord>) removingActivities::add);
+ forAllActivities((r) -> {
+ if (!r.finishing) {
+ removingActivities.add(r);
+ }
+ });
for (int i = removingActivities.size() - 1; i >= 0; --i) {
final ActivityRecord r = removingActivities.get(i);
if (withTransition && r.isVisible()) {
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 1a107c2..7f0c336 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -121,6 +121,11 @@
*/
private static final int MAX_NUM_PERCEPTIBLE_FREEFORM =
SystemProperties.getInt("persist.wm.max_num_perceptible_freeform", 1);
+ /**
+ * If the visible area percentage of a resumed freeform task is greater than or equal to this
+ * ratio, its process will have a higher priority.
+ */
+ private static final int PERCEPTIBLE_FREEFORM_VISIBLE_RATIO = 90;
private static final int MAX_RAPID_ACTIVITY_LAUNCH_COUNT = 200;
private static final long RAPID_ACTIVITY_LAUNCH_MS = 500;
@@ -1234,6 +1239,7 @@
boolean hasResumedFreeform = false;
int minTaskLayer = Integer.MAX_VALUE;
int stateFlags = 0;
+ int nonOccludedRatio = 0;
final boolean wasResumed = hasResumedActivity();
final boolean wasAnyVisible = (mActivityStateFlags
& (ACTIVITY_STATE_FLAG_IS_VISIBLE | ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE)) != 0;
@@ -1261,6 +1267,8 @@
stateFlags |= ACTIVITY_STATE_FLAG_RESUMED_SPLIT_SCREEN;
} else if (windowingMode == WINDOWING_MODE_FREEFORM) {
hasResumedFreeform = true;
+ nonOccludedRatio =
+ Math.max(task.mNonOccludedFreeformAreaRatio, nonOccludedRatio);
}
}
if (minTaskLayer > 0) {
@@ -1298,7 +1306,8 @@
&& com.android.window.flags.Flags.processPriorityPolicyForMultiWindowMode()
// Exclude task layer 1 because it is already the top most.
&& minTaskLayer > 1) {
- if (minTaskLayer <= 1 + MAX_NUM_PERCEPTIBLE_FREEFORM) {
+ if (minTaskLayer <= 1 + MAX_NUM_PERCEPTIBLE_FREEFORM
+ || nonOccludedRatio >= PERCEPTIBLE_FREEFORM_VISIBLE_RATIO) {
stateFlags |= ACTIVITY_STATE_FLAG_PERCEPTIBLE_FREEFORM;
} else {
stateFlags |= ACTIVITY_STATE_FLAG_VISIBLE_MULTI_WINDOW_MODE;
diff --git a/services/core/java/com/android/server/wm/utils/RegionUtils.java b/services/core/java/com/android/server/wm/utils/RegionUtils.java
index ce7776f..ff23145 100644
--- a/services/core/java/com/android/server/wm/utils/RegionUtils.java
+++ b/services/core/java/com/android/server/wm/utils/RegionUtils.java
@@ -81,4 +81,15 @@
Collections.reverse(rects);
rects.forEach(rectConsumer);
}
+
+ /** Returns the area size of the region. */
+ public static int getAreaSize(Region region) {
+ final RegionIterator regionIterator = new RegionIterator(region);
+ int area = 0;
+ final Rect rect = new Rect();
+ while (regionIterator.next(rect)) {
+ area += rect.width() * rect.height();
+ }
+ return area;
+ }
}
diff --git a/services/tests/PackageManagerServiceTests/appenumeration/Android.bp b/services/tests/PackageManagerServiceTests/appenumeration/Android.bp
index f15e533..2f00a1b 100644
--- a/services/tests/PackageManagerServiceTests/appenumeration/Android.bp
+++ b/services/tests/PackageManagerServiceTests/appenumeration/Android.bp
@@ -32,6 +32,7 @@
"androidx.test.runner",
"truth",
"Harrier",
+ "bedstead-multiuser",
],
platform_apis: true,
certificate: "platform",
diff --git a/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java b/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java
index 70a2d48..48cebd7 100644
--- a/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java
+++ b/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java
@@ -22,6 +22,7 @@
import static android.Manifest.permission.MOVE_PACKAGE;
import static android.content.pm.PackageManager.MOVE_FAILED_DOESNT_EXIST;
+import static com.android.bedstead.multiuser.MultiUserDeviceStateExtensionsKt.secondaryUser;
import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
import static com.google.common.truth.Truth.assertThat;
@@ -112,9 +113,9 @@
final UserReference primaryUser = sDeviceState.primaryUser();
if (primaryUser.id() == UserHandle.myUserId()) {
mCurrentUser = primaryUser;
- mOtherUser = sDeviceState.secondaryUser();
+ mOtherUser = secondaryUser(sDeviceState);
} else {
- mCurrentUser = sDeviceState.secondaryUser();
+ mCurrentUser = secondaryUser(sDeviceState);
mOtherUser = primaryUser;
}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java
index 177f30a..0a1fc31 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java
@@ -987,5 +987,7 @@
BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE)
.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT))
.isEqualTo(60000);
+
+ span.close();
}
}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsManagerTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsManagerTest.java
index 9a64ce1..94997b2 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsManagerTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsManagerTest.java
@@ -41,7 +41,7 @@
public final RavenwoodRule mRavenwood = new RavenwoodRule();
@Test
- public void testBatteryUsageStatsDataConsistency() {
+ public void testBatteryUsageStatsDataConsistency() throws Exception {
BatteryStatsManager bsm = getContext().getSystemService(BatteryStatsManager.class);
BatteryUsageStats stats = bsm.getBatteryUsageStats(
new BatteryUsageStatsQuery.Builder().setMaxStatsAgeMs(
@@ -70,5 +70,7 @@
}
}
}
+
+ stats.close();
}
}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsAtomTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsAtomTest.java
index 7d2bc17..813dd84 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsAtomTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsAtomTest.java
@@ -64,7 +64,7 @@
private static final int UID_3 = 4000;
@Test
- public void testAtom_BatteryUsageStatsPerUid() {
+ public void testAtom_BatteryUsageStatsPerUid() throws Exception {
final BatteryUsageStats bus = buildBatteryUsageStats();
BatteryStatsService.FrameworkStatsLogger statsLogger =
mock(BatteryStatsService.FrameworkStatsLogger.class);
@@ -72,6 +72,8 @@
List<StatsEvent> actual = new ArrayList<>();
new BatteryStatsService.StatsPerUidLogger(statsLogger).logStats(bus, actual);
+ bus.close();
+
if (DEBUG) {
System.out.println(mockingDetails(statsLogger).printInvocations());
}
@@ -284,7 +286,7 @@
}
@Test
- public void testAtom_BatteryUsageStatsAtomsProto() {
+ public void testAtom_BatteryUsageStatsAtomsProto() throws Exception {
final BatteryUsageStats bus = buildBatteryUsageStats();
final byte[] bytes = bus.getStatsProto();
BatteryUsageStatsAtomsProto proto;
@@ -347,6 +349,7 @@
// UID_3 - Should be none, since no interesting data (done last for debugging convenience).
assertEquals(3, proto.uidBatteryConsumers.length);
+ bus.close();
}
private void assertSameBatteryConsumer(String message, BatteryConsumer consumer,
@@ -582,7 +585,7 @@
}
@Test
- public void testLargeAtomTruncated() {
+ public void testLargeAtomTruncated() throws Exception {
final BatteryUsageStats.Builder builder =
new BatteryUsageStats.Builder(new String[0], true, false, false, false, 0);
// If not truncated, this BatteryUsageStats object would generate a proto buffer
@@ -618,6 +621,8 @@
assertThat(bytes.length).isGreaterThan(20000);
assertThat(bytes.length).isLessThan(50000);
+ batteryUsageStats.close();
+
BatteryUsageStatsAtomsProto proto;
try {
proto = BatteryUsageStatsAtomsProto.parseFrom(bytes);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java
index e9d95fc..87a26d0 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java
@@ -94,7 +94,7 @@
}
@Test
- public void test_getBatteryUsageStats() {
+ public void test_getBatteryUsageStats() throws IOException {
final BatteryUsageStats batteryUsageStats = prepareBatteryUsageStats(false);
final List<UidBatteryConsumer> uidBatteryConsumers =
@@ -121,24 +121,27 @@
assertThat(batteryUsageStats.getStatsStartTimestamp()).isEqualTo(12345);
assertThat(batteryUsageStats.getStatsEndTimestamp()).isEqualTo(180 * MINUTE_IN_MS);
+ batteryUsageStats.close();
}
@Test
- public void batteryLevelInfo_charging() {
+ public void batteryLevelInfo_charging() throws IOException {
final BatteryUsageStats batteryUsageStats = prepareBatteryUsageStats(true);
assertThat(batteryUsageStats.getBatteryCapacity()).isEqualTo(4000.0);
assertThat(batteryUsageStats.getChargeTimeRemainingMs()).isEqualTo(1_200_000);
+ batteryUsageStats.close();
}
@Test
- public void batteryLevelInfo_onBattery() {
+ public void batteryLevelInfo_onBattery() throws IOException {
final BatteryUsageStats batteryUsageStats = prepareBatteryUsageStats(false);
assertThat(batteryUsageStats.getBatteryCapacity()).isEqualTo(4000.0);
assertThat(batteryUsageStats.getBatteryTimeRemainingMs()).isEqualTo(600_000);
+ batteryUsageStats.close();
}
@Test
- public void test_selectPowerComponents() {
+ public void test_selectPowerComponents() throws IOException {
BatteryStatsImpl batteryStats = prepareBatteryStats(false);
BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext,
@@ -163,6 +166,8 @@
assertThat(
uidBatteryConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT))
.isEqualTo(0);
+
+ batteryUsageStats.close();
}
private BatteryStatsImpl prepareBatteryStats(boolean plugInAtTheEnd) {
@@ -274,7 +279,7 @@
}
@Test
- public void testWriteAndReadHistory() {
+ public void testWriteAndReadHistory() throws IOException {
MockBatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
synchronized (batteryStats) {
batteryStats.setRecordAllHistoryLocked(true);
@@ -306,6 +311,8 @@
Parcel in = Parcel.obtain();
batteryUsageStats.writeToParcel(in, 0);
+ batteryUsageStats.close();
+
final byte[] bytes = in.marshall();
Parcel out = Parcel.obtain();
@@ -349,10 +356,12 @@
assertThat(iterator.hasNext()).isFalse();
assertThat(iterator.next()).isNull();
+
+ unparceled.close();
}
@Test
- public void testWriteAndReadHistoryTags() {
+ public void testWriteAndReadHistoryTags() throws IOException {
MockBatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
synchronized (batteryStats) {
batteryStats.setRecordAllHistoryLocked(true);
@@ -400,6 +409,8 @@
assertThat(parcel.dataSize()).isAtMost(128_000);
}
+ batteryUsageStats.close();
+
parcel.setDataPosition(0);
BatteryUsageStats unparceled = parcel.readParcelable(getClass().getClassLoader(),
@@ -461,7 +472,7 @@
}
@Test
- public void testAggregateBatteryStats() {
+ public void testAggregateBatteryStats() throws IOException {
BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
setTime(5 * MINUTE_IN_MS);
@@ -563,6 +574,8 @@
.getConsumedPower(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT))
.isWithin(0.1)
.of(180.0);
+
+ stats.close();
}
@Test
@@ -689,6 +702,8 @@
.isEqualTo(60 * MINUTE_IN_MS);
assertThat(count[0]).isEqualTo(expectedNumberOfUpdates);
+
+ stats.close();
}
private void setTime(long timeMs) {
@@ -733,6 +748,7 @@
.isWithin(PRECISION).of(8.33333);
assertThat(uid.getConsumedPower(componentId1))
.isWithin(PRECISION).of(8.33333);
+ stats.close();
return null;
}).when(powerStatsStore).storeBatteryUsageStatsAsync(anyLong(), any());
@@ -750,7 +766,7 @@
}
@Test
- public void testAggregateBatteryStats_incompatibleSnapshot() {
+ public void testAggregateBatteryStats_incompatibleSnapshot() throws IOException {
MockBatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
batteryStats.initMeasuredEnergyStats(new String[]{"FOO", "BAR"});
@@ -776,6 +792,8 @@
when(powerStatsStore.loadPowerStatsSpan(1, BatteryUsageStatsSection.TYPE))
.thenReturn(span1);
+ span1.close();
+
BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext,
mock(PowerAttributor.class), mStatsRule.getPowerProfile(),
mStatsRule.getCpuScalingPolicies(), powerStatsStore, 0, mMockClock);
@@ -787,5 +805,7 @@
assertThat(stats.getCustomPowerComponentNames())
.isEqualTo(batteryStats.getCustomEnergyConsumerNames());
assertThat(stats.getStatsDuration()).isEqualTo(1234);
+
+ stats.close();
}
}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java
index 52675f6..383616e 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java
@@ -323,6 +323,7 @@
}
private void before() {
+ BatteryUsageStats.DEBUG_INSTANCE_COUNT = true;
HandlerThread bgThread = new HandlerThread("bg thread");
bgThread.setUncaughtExceptionHandler((thread, throwable)-> {
mThrowable = throwable;
@@ -338,6 +339,10 @@
private void after() throws Throwable {
waitForBackgroundThread();
+ if (mBatteryUsageStats != null) {
+ mBatteryUsageStats.close();
+ }
+ BatteryUsageStats.assertAllInstancesClosed();
}
public void waitForBackgroundThread() throws Throwable {
@@ -409,6 +414,14 @@
}
BatteryUsageStats apply(BatteryUsageStatsQuery query, PowerCalculator... calculators) {
+ if (mBatteryUsageStats != null) {
+ try {
+ mBatteryUsageStats.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ mBatteryUsageStats = null;
+ }
final String[] customPowerComponentNames = mBatteryStats.getCustomEnergyConsumerNames();
final boolean includePowerModels = (query.getFlags()
& BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_POWER_MODELS) != 0;
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsTest.java
index 88624f2..1b6b8c4 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsTest.java
@@ -76,22 +76,25 @@
private static final int APP_UID2 = 314;
@Test
- public void testBuilder() {
+ public void testBuilder() throws Exception {
BatteryUsageStats batteryUsageStats = buildBatteryUsageStats1(true).build();
assertBatteryUsageStats1(batteryUsageStats, true);
+ batteryUsageStats.close();
}
@Test
- public void testBuilder_noProcessStateData() {
+ public void testBuilder_noProcessStateData() throws Exception {
BatteryUsageStats batteryUsageStats = buildBatteryUsageStats1(false).build();
assertBatteryUsageStats1(batteryUsageStats, false);
+ batteryUsageStats.close();
}
@Test
- public void testParcelability_smallNumberOfUids() {
+ public void testParcelability_smallNumberOfUids() throws Exception {
final BatteryUsageStats outBatteryUsageStats = buildBatteryUsageStats1(true).build();
final Parcel parcel = Parcel.obtain();
parcel.writeParcelable(outBatteryUsageStats, 0);
+ outBatteryUsageStats.close();
assertThat(parcel.dataSize()).isLessThan(100000);
@@ -101,10 +104,11 @@
parcel.readParcelable(getClass().getClassLoader());
assertThat(inBatteryUsageStats).isNotNull();
assertBatteryUsageStats1(inBatteryUsageStats, true);
+ inBatteryUsageStats.close();
}
@Test
- public void testParcelability_largeNumberOfUids() {
+ public void testParcelability_largeNumberOfUids() throws Exception {
final BatteryUsageStats.Builder builder =
new BatteryUsageStats.Builder(new String[0]);
@@ -141,22 +145,27 @@
assertThat(uidBatteryConsumer).isNotNull();
assertThat(uidBatteryConsumer.getConsumedPower()).isEqualTo(i * 100);
}
+ inBatteryUsageStats.close();
+ outBatteryUsageStats.close();
}
@Test
- public void testDefaultSessionDuration() {
+ public void testDefaultSessionDuration() throws Exception {
final BatteryUsageStats stats =
buildBatteryUsageStats1(true).setStatsDuration(10000).build();
assertThat(stats.getStatsDuration()).isEqualTo(10000);
+ stats.close();
}
@Test
- public void testDump() {
+ public void testDump() throws Exception {
final BatteryUsageStats stats = buildBatteryUsageStats1(true).build();
final StringWriter out = new StringWriter();
try (PrintWriter pw = new PrintWriter(out)) {
stats.dump(pw, " ");
}
+ stats.close();
+
final String dump = out.toString();
assertThat(dump).contains("Capacity: 4000");
@@ -187,12 +196,14 @@
}
@Test
- public void testDumpNoScreenOrPowerState() {
+ public void testDumpNoScreenOrPowerState() throws Exception {
final BatteryUsageStats stats = buildBatteryUsageStats1(true, false, false).build();
final StringWriter out = new StringWriter();
try (PrintWriter pw = new PrintWriter(out)) {
stats.dump(pw, " ");
}
+ stats.close();
+
final String dump = out.toString();
assertThat(dump).contains("Capacity: 4000");
@@ -222,7 +233,7 @@
}
@Test
- public void testAdd() {
+ public void testAdd() throws Exception {
final BatteryUsageStats stats1 = buildBatteryUsageStats1(false).build();
final BatteryUsageStats stats2 = buildBatteryUsageStats2(new String[]{"FOO"}, true).build();
final BatteryUsageStats sum =
@@ -261,24 +272,31 @@
assertAggregateBatteryConsumer(sum,
BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE,
40211, 40422, 40633, 40844);
+ stats1.close();
+ stats2.close();
+ sum.close();
}
@Test
- public void testAdd_customComponentMismatch() {
+ public void testAdd_customComponentMismatch() throws Exception {
final BatteryUsageStats.Builder builder =
new BatteryUsageStats.Builder(new String[]{"FOO"}, true, true, true, true, 0);
final BatteryUsageStats stats = buildBatteryUsageStats2(new String[]{"BAR"}, false).build();
assertThrows(IllegalArgumentException.class, () -> builder.add(stats));
+ stats.close();
+ builder.discard();
}
@Test
- public void testAdd_processStateDataMismatch() {
+ public void testAdd_processStateDataMismatch() throws Exception {
final BatteryUsageStats.Builder builder =
new BatteryUsageStats.Builder(new String[]{"FOO"}, true, true, true, true, 0);
final BatteryUsageStats stats = buildBatteryUsageStats2(new String[]{"FOO"}, false).build();
assertThrows(IllegalArgumentException.class, () -> builder.add(stats));
+ stats.close();
+ builder.discard();
}
@Test
@@ -290,12 +308,14 @@
final BatteryUsageStats stats = buildBatteryUsageStats1(true).build();
stats.writeXml(serializer);
serializer.endDocument();
+ stats.close();
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
TypedXmlPullParser parser = Xml.newBinaryPullParser();
parser.setInput(in, StandardCharsets.UTF_8.name());
final BatteryUsageStats fromXml = BatteryUsageStats.createFromXml(parser);
assertBatteryUsageStats1(fromXml, true);
+ fromXml.close();
}
private BatteryUsageStats.Builder buildBatteryUsageStats1(boolean includeUserBatteryConsumer) {
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/MockBatteryStatsImpl.java b/services/tests/powerstatstests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
index 1e4454c..b374a32 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
@@ -17,6 +17,7 @@
package com.android.server.power.stats;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.app.usage.NetworkStatsManager;
@@ -80,7 +81,7 @@
Handler handler, PowerStatsUidResolver powerStatsUidResolver) {
super(config, clock, new MonotonicClock(0, clock), historyDirectory, handler,
mock(PlatformIdleStateCallback.class), mock(EnergyStatsRetriever.class),
- mock(UserInfoProvider.class), mock(PowerProfile.class),
+ mock(UserInfoProvider.class), mockPowerProfile(),
new CpuScalingPolicies(new SparseArray<>(), new SparseArray<>()),
powerStatsUidResolver, mock(FrameworkStatsLogger.class),
mock(BatteryStatsHistory.TraceDelegate.class),
@@ -96,6 +97,12 @@
mKernelWakelockReader = null;
}
+ private static PowerProfile mockPowerProfile() {
+ PowerProfile powerProfile = mock(PowerProfile.class);
+ when(powerProfile.getNumDisplays()).thenReturn(1);
+ return powerProfile;
+ }
+
public void initMeasuredEnergyStats(String[] customBucketNames) {
final boolean[] supportedStandardBuckets =
new boolean[EnergyConsumerStats.NUMBER_STANDARD_POWER_BUCKETS];
diff --git a/services/tests/security/forensic/src/com/android/server/security/forensic/ForensicServiceTest.java b/services/tests/security/forensic/src/com/android/server/security/forensic/ForensicServiceTest.java
index 7aa2e0f..2b55303 100644
--- a/services/tests/security/forensic/src/com/android/server/security/forensic/ForensicServiceTest.java
+++ b/services/tests/security/forensic/src/com/android/server/security/forensic/ForensicServiceTest.java
@@ -19,6 +19,9 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
import android.annotation.SuppressLint;
import android.content.Context;
@@ -50,7 +53,8 @@
IForensicServiceCommandCallback.ErrorCode.DATA_SOURCE_UNAVAILABLE;
@Mock
- private Context mContextSpy;
+ private Context mContext;
+ private BackupTransportConnection mBackupTransportConnection;
private ForensicService mForensicService;
private TestLooper mTestLooper;
@@ -63,7 +67,7 @@
mTestLooper = new TestLooper();
mLooper = mTestLooper.getLooper();
- mForensicService = new ForensicService(new MockInjector(mContextSpy));
+ mForensicService = new ForensicService(new MockInjector(mContext));
mForensicService.onStart();
}
@@ -253,6 +257,8 @@
assertEquals(STATE_VISIBLE, scb1.mState);
assertEquals(STATE_VISIBLE, scb2.mState);
+ doReturn(true).when(mBackupTransportConnection).initialize();
+
CommandCallback ccb = new CommandCallback();
mForensicService.getBinderService().enable(ccb);
mTestLooper.dispatchAll();
@@ -262,6 +268,29 @@
}
@Test
+ public void testEnable_FromVisible_TwoMonitors_BackupTransportUnavailable()
+ throws RemoteException {
+ mForensicService.setState(STATE_VISIBLE);
+ StateCallback scb1 = new StateCallback();
+ StateCallback scb2 = new StateCallback();
+ mForensicService.getBinderService().monitorState(scb1);
+ mForensicService.getBinderService().monitorState(scb2);
+ mTestLooper.dispatchAll();
+ assertEquals(STATE_VISIBLE, scb1.mState);
+ assertEquals(STATE_VISIBLE, scb2.mState);
+
+ doReturn(false).when(mBackupTransportConnection).initialize();
+
+ CommandCallback ccb = new CommandCallback();
+ mForensicService.getBinderService().enable(ccb);
+ mTestLooper.dispatchAll();
+ assertEquals(STATE_VISIBLE, scb1.mState);
+ assertEquals(STATE_VISIBLE, scb2.mState);
+ assertNotNull(ccb.mErrorCode);
+ assertEquals(ERROR_BACKUP_TRANSPORT_UNAVAILABLE, ccb.mErrorCode.intValue());
+ }
+
+ @Test
public void testEnable_FromEnabled_TwoMonitors() throws RemoteException {
mForensicService.setState(STATE_ENABLED);
StateCallback scb1 = new StateCallback();
@@ -330,6 +359,8 @@
assertEquals(STATE_ENABLED, scb1.mState);
assertEquals(STATE_ENABLED, scb2.mState);
+ doNothing().when(mBackupTransportConnection).release();
+
CommandCallback ccb = new CommandCallback();
mForensicService.getBinderService().disable(ccb);
mTestLooper.dispatchAll();
@@ -356,6 +387,12 @@
return mLooper;
}
+ @Override
+ public BackupTransportConnection getBackupTransportConnection() {
+ mBackupTransportConnection = spy(new BackupTransportConnection(mContext));
+ return mBackupTransportConnection;
+ }
+
}
private static class StateCallback extends IForensicServiceStateCallback.Stub {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java
index 7829fcc..8df18a8 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java
@@ -480,7 +480,7 @@
if (config.getMode() == MAGNIFICATION_MODE_FULLSCREEN) {
mFullScreenMagnificationControllerStub.resetAndStubMethods();
mMockFullScreenMagnificationController.setScaleAndCenter(displayId, config.getScale(),
- config.getCenterX(), config.getCenterY(), false, SERVICE_ID);
+ config.getCenterX(), config.getCenterY(), true, false, SERVICE_ID);
mMagnificationManagerStub.deactivateIfNeed();
} else if (config.getMode() == MAGNIFICATION_MODE_WINDOW) {
mMagnificationManagerStub.resetAndStubMethods();
@@ -531,6 +531,9 @@
};
doAnswer(enableMagnificationStubAnswer).when(
mScreenMagnificationController).setScaleAndCenter(eq(TEST_DISPLAY), anyFloat(),
+ anyFloat(), anyFloat(), anyBoolean(), anyBoolean(), eq(SERVICE_ID));
+ doAnswer(enableMagnificationStubAnswer).when(
+ mScreenMagnificationController).setScaleAndCenter(eq(TEST_DISPLAY), anyFloat(),
anyFloat(), anyFloat(), anyBoolean(), eq(SERVICE_ID));
Answer disableMagnificationStubAnswer = invocation -> {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
index c4b4afd..5985abc 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
@@ -18,6 +18,7 @@
import static android.accessibilityservice.MagnificationConfig.MAGNIFICATION_MODE_FULLSCREEN;
+import static com.android.server.accessibility.Flags.FLAG_MAGNIFICATION_ENLARGE_POINTER;
import static com.android.server.accessibility.magnification.FullScreenMagnificationController.MagnificationInfoChangedCallback;
import static com.android.server.accessibility.magnification.MockMagnificationConnection.TEST_DISPLAY;
import static com.android.window.flags.Flags.FLAG_ALWAYS_DRAW_MAGNIFICATION_FULLSCREEN_BORDER;
@@ -76,6 +77,7 @@
import com.android.server.accessibility.AccessibilityTraceManager;
import com.android.server.accessibility.Flags;
import com.android.server.accessibility.test.MessageCapturingHandler;
+import com.android.server.input.InputManagerInternal;
import com.android.server.wm.WindowManagerInternal;
import com.android.server.wm.WindowManagerInternal.MagnificationCallbacks;
@@ -126,6 +128,7 @@
final Resources mMockResources = mock(Resources.class);
final AccessibilityTraceManager mMockTraceManager = mock(AccessibilityTraceManager.class);
final WindowManagerInternal mMockWindowManager = mock(WindowManagerInternal.class);
+ final InputManagerInternal mMockInputManager = mock(InputManagerInternal.class);
private final MagnificationAnimationCallback mAnimationCallback = mock(
MagnificationAnimationCallback.class);
private final MagnificationInfoChangedCallback mRequestObserver = mock(
@@ -163,6 +166,7 @@
when(mMockControllerCtx.getContext()).thenReturn(mMockContext);
when(mMockControllerCtx.getTraceManager()).thenReturn(mMockTraceManager);
when(mMockControllerCtx.getWindowManager()).thenReturn(mMockWindowManager);
+ when(mMockControllerCtx.getInputManager()).thenReturn(mMockInputManager);
when(mMockControllerCtx.getHandler()).thenReturn(mMessageCapturingHandler);
when(mMockControllerCtx.getAnimationDuration()).thenReturn(1000L);
mResolver = new MockContentResolver();
@@ -285,10 +289,11 @@
mFullScreenMagnificationController.magnificationRegionContains(displayId, 100,
100));
assertFalse(mFullScreenMagnificationController.reset(displayId, true));
- assertFalse(mFullScreenMagnificationController.setScale(displayId, 2, 100, 100, true, 0));
+ assertFalse(
+ mFullScreenMagnificationController.setScale(displayId, 2, 100, 100, true, true, 0));
assertFalse(mFullScreenMagnificationController.setCenter(displayId, 100, 100, false, 1));
assertFalse(mFullScreenMagnificationController.setScaleAndCenter(displayId,
- 1.5f, 100, 100, false, 2));
+ 1.5f, 100, 100, true, false, 2));
assertTrue(mFullScreenMagnificationController.getIdOfLastServiceToMagnify(displayId) < 0);
mFullScreenMagnificationController.getMagnificationRegion(displayId, new Region());
@@ -313,7 +318,7 @@
final float scale = 2.0f;
final PointF center = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
assertFalse(mFullScreenMagnificationController
- .setScale(TEST_DISPLAY, scale, center.x, center.y, false, SERVICE_ID_1));
+ .setScale(TEST_DISPLAY, scale, center.x, center.y, true, false, SERVICE_ID_1));
assertFalse(mFullScreenMagnificationController.isActivated(TEST_DISPLAY));
}
@@ -331,7 +336,7 @@
final PointF center = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
final PointF offsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, center, scale);
assertTrue(mFullScreenMagnificationController
- .setScale(displayId, scale, center.x, center.y, false, SERVICE_ID_1));
+ .setScale(displayId, scale, center.x, center.y, true, false, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
final MagnificationSpec expectedSpec = getMagnificationSpec(scale, offsets);
@@ -357,7 +362,7 @@
float scale = 2.0f;
PointF pivotPoint = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
assertTrue(mFullScreenMagnificationController
- .setScale(displayId, scale, pivotPoint.x, pivotPoint.y, true, SERVICE_ID_1));
+ .setScale(displayId, scale, pivotPoint.x, pivotPoint.y, true, true, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
// New center should be halfway between original center and pivot
@@ -405,7 +410,7 @@
float scale = 2.0f;
assertTrue(mFullScreenMagnificationController.setScale(displayId, scale,
INITIAL_MAGNIFICATION_BOUNDS.centerX(), INITIAL_MAGNIFICATION_BOUNDS.centerY(),
- false, SERVICE_ID_1));
+ true, false, SERVICE_ID_1));
Mockito.reset(mMockWindowManager);
PointF newCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
@@ -440,7 +445,7 @@
MagnificationSpec endSpec = getMagnificationSpec(scale, offsets);
assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId, scale,
- newCenter.x, newCenter.y, mAnimationCallback, SERVICE_ID_1));
+ newCenter.x, newCenter.y, true, mAnimationCallback, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
assertEquals(newCenter.x, mFullScreenMagnificationController.getCenterX(displayId), 0.5);
@@ -486,11 +491,11 @@
final PointF center = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
final float targetScale = 2.0f;
assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId,
- targetScale, center.x, center.y, false, SERVICE_ID_1));
+ targetScale, center.x, center.y, true, false, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
assertFalse(mFullScreenMagnificationController.setScaleAndCenter(displayId,
- targetScale, center.x, center.y, mAnimationCallback, SERVICE_ID_1));
+ targetScale, center.x, center.y, true, mAnimationCallback, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
verify(mMockValueAnimator, never()).start();
@@ -516,7 +521,7 @@
assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId,
MagnificationScaleProvider.MAX_SCALE + 1.0f,
- newCenter.x, newCenter.y, false, SERVICE_ID_1));
+ newCenter.x, newCenter.y, true, false, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
assertEquals(newCenter.x, mFullScreenMagnificationController.getCenterX(displayId), 0.5);
@@ -527,7 +532,7 @@
// Verify that we can't zoom below 1x
assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId, 0.5f,
INITIAL_MAGNIFICATION_BOUNDS_CENTER.x, INITIAL_MAGNIFICATION_BOUNDS_CENTER.y,
- false, SERVICE_ID_1));
+ true, false, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
assertEquals(INITIAL_MAGNIFICATION_BOUNDS_CENTER.x,
@@ -551,7 +556,7 @@
// Off the edge to the top and left
assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId,
- scale, -100f, -200f, false, SERVICE_ID_1));
+ scale, -100f, -200f, true, false, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
PointF newCenter = INITIAL_BOUNDS_UPPER_LEFT_2X_CENTER;
@@ -565,7 +570,7 @@
// Off the edge to the bottom and right
assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId, scale,
INITIAL_MAGNIFICATION_BOUNDS.right + 1, INITIAL_MAGNIFICATION_BOUNDS.bottom + 1,
- false, SERVICE_ID_1));
+ true, false, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
newCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
newOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter, scale);
@@ -619,7 +624,7 @@
PointF startOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, startCenter, scale);
// First zoom in
assertTrue(mFullScreenMagnificationController
- .setScaleAndCenter(displayId, scale, startCenter.x, startCenter.y, false,
+ .setScaleAndCenter(displayId, scale, startCenter.x, startCenter.y, true, false,
SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
Mockito.reset(mMockWindowManager);
@@ -673,7 +678,7 @@
// Upper left edges
PointF ulCenter = INITIAL_BOUNDS_UPPER_LEFT_2X_CENTER;
assertTrue(mFullScreenMagnificationController
- .setScaleAndCenter(displayId, scale, ulCenter.x, ulCenter.y, false,
+ .setScaleAndCenter(displayId, scale, ulCenter.x, ulCenter.y, true, false,
SERVICE_ID_1));
Mockito.reset(mMockWindowManager);
MagnificationSpec ulSpec = getCurrentMagnificationSpec(displayId);
@@ -685,7 +690,7 @@
// Lower right edges
PointF lrCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
assertTrue(mFullScreenMagnificationController
- .setScaleAndCenter(displayId, scale, lrCenter.x, lrCenter.y, false,
+ .setScaleAndCenter(displayId, scale, lrCenter.x, lrCenter.y, true, false,
SERVICE_ID_1));
Mockito.reset(mMockWindowManager);
MagnificationSpec lrSpec = getCurrentMagnificationSpec(displayId);
@@ -710,7 +715,7 @@
float scale = 2.0f;
// First zoom in
assertTrue(mFullScreenMagnificationController
- .setScaleAndCenter(displayId, scale, startCenter.x, startCenter.y, false,
+ .setScaleAndCenter(displayId, scale, startCenter.x, startCenter.y, true, false,
SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
@@ -753,7 +758,7 @@
PointF startOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, startCenter, scale);
// First zoom in
assertTrue(mFullScreenMagnificationController
- .setScaleAndCenter(displayId, scale, startCenter.x, startCenter.y, false,
+ .setScaleAndCenter(displayId, scale, startCenter.x, startCenter.y, true, false,
SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
@@ -786,12 +791,12 @@
register(displayId);
PointF startCenter = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
assertTrue(mFullScreenMagnificationController
- .setScale(displayId, 2.0f, startCenter.x, startCenter.y, false,
+ .setScale(displayId, 2.0f, startCenter.x, startCenter.y, true, false,
SERVICE_ID_1));
assertEquals(SERVICE_ID_1,
mFullScreenMagnificationController.getIdOfLastServiceToMagnify(displayId));
assertTrue(mFullScreenMagnificationController
- .setScale(displayId, 1.5f, startCenter.x, startCenter.y, false,
+ .setScale(displayId, 1.5f, startCenter.x, startCenter.y, true, false,
SERVICE_ID_2));
assertEquals(SERVICE_ID_2,
mFullScreenMagnificationController.getIdOfLastServiceToMagnify(displayId));
@@ -809,10 +814,10 @@
register(displayId);
PointF startCenter = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
mFullScreenMagnificationController
- .setScale(displayId, 2.0f, startCenter.x, startCenter.y, false,
+ .setScale(displayId, 2.0f, startCenter.x, startCenter.y, true, false,
SERVICE_ID_1);
mFullScreenMagnificationController
- .setScale(displayId, 1.5f, startCenter.x, startCenter.y, false,
+ .setScale(displayId, 1.5f, startCenter.x, startCenter.y, true, false,
SERVICE_ID_2);
assertFalse(mFullScreenMagnificationController.resetIfNeeded(displayId, SERVICE_ID_1));
checkActivatedAndMagnifying(/* activated= */ true, /* magnifying= */ true, displayId);
@@ -873,7 +878,7 @@
float scale = 2.5f;
PointF firstCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId,
- scale, firstCenter.x, firstCenter.y, mAnimationCallback, SERVICE_ID_1));
+ scale, firstCenter.x, firstCenter.y, true, mAnimationCallback, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
Mockito.reset(mMockValueAnimator);
// Stubs the logic after the animation is started.
@@ -1076,7 +1081,7 @@
float scale = 2.0f;
// setting animate parameter to true is differ from zoomIn2xToMiddle()
mFullScreenMagnificationController.setScale(displayId, scale, startCenter.x, startCenter.y,
- true, SERVICE_ID_1);
+ true, true, SERVICE_ID_1);
MagnificationSpec startSpec = getCurrentMagnificationSpec(displayId);
MagnificationCallbacks callbacks = getMagnificationCallbacks(displayId);
Mockito.reset(mMockWindowManager);
@@ -1107,7 +1112,7 @@
PointF startCenter = OTHER_BOUNDS_LOWER_RIGHT_2X_CENTER;
float scale = 2.0f;
mFullScreenMagnificationController.setScale(displayId, scale, startCenter.x, startCenter.y,
- false, SERVICE_ID_1);
+ true, false, SERVICE_ID_1);
mMessageCapturingHandler.sendAllMessages();
MagnificationSpec startSpec = getCurrentMagnificationSpec(displayId);
verify(mMockWindowManager).setMagnificationSpec(eq(displayId), argThat(closeTo(startSpec)));
@@ -1148,7 +1153,7 @@
PointF startCenter = OTHER_BOUNDS_LOWER_RIGHT_2X_CENTER;
float scale = 2.0f;
mFullScreenMagnificationController.setScale(displayId, scale, startCenter.x, startCenter.y,
- true, SERVICE_ID_1);
+ true, true, SERVICE_ID_1);
mMessageCapturingHandler.sendAllMessages();
MagnificationSpec startSpec = getCurrentMagnificationSpec(displayId);
when(mMockValueAnimator.isRunning()).thenReturn(true);
@@ -1335,7 +1340,7 @@
scale, computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, firstCenter, scale));
assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId,
- scale, firstCenter.x, firstCenter.y, true, SERVICE_ID_1));
+ scale, firstCenter.x, firstCenter.y, true, true, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
assertEquals(firstCenter.x, mFullScreenMagnificationController.getCenterX(displayId), 0.5);
@@ -1404,7 +1409,7 @@
register(DISPLAY_0);
final float scale = 1.0f;
mFullScreenMagnificationController.setScaleAndCenter(
- DISPLAY_0, scale, Float.NaN, Float.NaN, true, SERVICE_ID_1);
+ DISPLAY_0, scale, Float.NaN, Float.NaN, true, true, SERVICE_ID_1);
checkActivatedAndMagnifying(/* activated= */ true, /* magnifying= */ false, DISPLAY_0);
verify(mMockWindowManager).setFullscreenMagnificationActivated(DISPLAY_0, true);
@@ -1449,7 +1454,7 @@
PointF pivotPoint = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
mFullScreenMagnificationController.setScale(TEST_DISPLAY, 1.0f, pivotPoint.x, pivotPoint.y,
- false, SERVICE_ID_1);
+ true, false, SERVICE_ID_1);
mFullScreenMagnificationController.persistScale(TEST_DISPLAY);
// persistScale may post a task to a background thread. Let's wait for it completes.
@@ -1464,10 +1469,10 @@
register(DISPLAY_1);
final PointF pivotPoint = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
mFullScreenMagnificationController.setScale(DISPLAY_0, 3.0f, pivotPoint.x, pivotPoint.y,
- false, SERVICE_ID_1);
+ true, false, SERVICE_ID_1);
mFullScreenMagnificationController.persistScale(DISPLAY_0);
mFullScreenMagnificationController.setScale(DISPLAY_1, 4.0f, pivotPoint.x, pivotPoint.y,
- false, SERVICE_ID_1);
+ true, false, SERVICE_ID_1);
mFullScreenMagnificationController.persistScale(DISPLAY_1);
// persistScale may post a task to a background thread. Let's wait for it completes.
@@ -1479,6 +1484,101 @@
}
@Test
+ @RequiresFlagsEnabled(FLAG_MAGNIFICATION_ENLARGE_POINTER)
+ public void persistScale_setValue_notifyInput() {
+ register(TEST_DISPLAY);
+
+ PointF pivotPoint = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
+ mFullScreenMagnificationController.setScale(TEST_DISPLAY, 4.0f, pivotPoint.x, pivotPoint.y,
+ /* isScaleTransient= */ true, /* animate= */ false, SERVICE_ID_1);
+ verify(mMockInputManager, never()).setAccessibilityPointerIconScaleFactor(anyInt(),
+ anyFloat());
+
+ mFullScreenMagnificationController.persistScale(TEST_DISPLAY);
+
+ // persistScale may post a task to a background thread. Let's wait for it completes.
+ waitForBackgroundThread();
+ Assert.assertEquals(mFullScreenMagnificationController.getPersistedScale(TEST_DISPLAY),
+ 4.0f);
+ verify(mMockInputManager).setAccessibilityPointerIconScaleFactor(TEST_DISPLAY, 4.0f);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(FLAG_MAGNIFICATION_ENLARGE_POINTER)
+ public void setScale_setNonTransientScale_notifyInput() {
+ register(TEST_DISPLAY);
+
+ PointF pivotPoint = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
+ mFullScreenMagnificationController.setScale(TEST_DISPLAY, 4.0f, pivotPoint.x, pivotPoint.y,
+ /* isScaleTransient= */ false, /* animate= */ false, SERVICE_ID_1);
+
+ verify(mMockInputManager).setAccessibilityPointerIconScaleFactor(TEST_DISPLAY, 4.0f);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(FLAG_MAGNIFICATION_ENLARGE_POINTER)
+ public void setScaleAndCenter_setTransientScale_notNotifyInput() {
+ register(TEST_DISPLAY);
+
+ PointF point = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
+ mFullScreenMagnificationController.setScaleAndCenter(TEST_DISPLAY, 3.0f, point.x,
+ point.y, /* isScaleTransient= */ true, /* animate= */ false, SERVICE_ID_1);
+
+ verify(mRequestObserver).onFullScreenMagnificationChanged(anyInt(), any(Region.class),
+ any(MagnificationConfig.class));
+ verify(mMockInputManager, never()).setAccessibilityPointerIconScaleFactor(anyInt(),
+ anyFloat());
+ }
+
+ @Test
+ @RequiresFlagsEnabled(FLAG_MAGNIFICATION_ENLARGE_POINTER)
+ public void setScaleAndCenter_setNonTransientScale_notifyInput() {
+ register(TEST_DISPLAY);
+
+ PointF point = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
+ mFullScreenMagnificationController.setScaleAndCenter(TEST_DISPLAY, 3.0f, point.x,
+ point.y, /* isScaleTransient= */ false, /* animate= */ false, SERVICE_ID_1);
+
+ verify(mMockInputManager).setAccessibilityPointerIconScaleFactor(TEST_DISPLAY, 3.0f);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(FLAG_MAGNIFICATION_ENLARGE_POINTER)
+ public void setCenter_notNotifyInput() {
+ register(TEST_DISPLAY);
+
+ PointF point = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
+ mFullScreenMagnificationController.setScale(TEST_DISPLAY, 2.0f, point.x, point.y,
+ /* isScaleTransient= */ true, /* animate= */ false, SERVICE_ID_1);
+ mFullScreenMagnificationController.setCenter(TEST_DISPLAY, point.x, point.y, false,
+ SERVICE_ID_1);
+
+ // Note that setCenter doesn't change scale, so it's not necessary to notify the input
+ // manager, but we currently do. The input manager skips redundant computation if the
+ // notified scale is the same as the previous call.
+ verify(mMockInputManager).setAccessibilityPointerIconScaleFactor(TEST_DISPLAY,
+ 2.0f);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(FLAG_MAGNIFICATION_ENLARGE_POINTER)
+ public void offsetMagnifiedRegion_notNotifyInput() {
+ register(TEST_DISPLAY);
+
+ PointF point = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
+ mFullScreenMagnificationController.setScale(TEST_DISPLAY, 2.0f, point.x, point.y,
+ /* isScaleTransient= */ true, /* animate= */ false, SERVICE_ID_1);
+ mFullScreenMagnificationController.offsetMagnifiedRegion(TEST_DISPLAY, 100, 50,
+ SERVICE_ID_1);
+
+ // Note that setCenter doesn't change scale, so it's not necessary to notify the input
+ // manager, but we currently do. The input manager skips redundant computation if the
+ // notified scale is the same as the previous call.
+ verify(mMockInputManager).setAccessibilityPointerIconScaleFactor(TEST_DISPLAY,
+ 2.0f);
+ }
+
+ @Test
public void testOnContextChanged_alwaysOnFeatureDisabled_resetMagnification() {
setScaleToMagnifying();
@@ -1535,7 +1635,7 @@
PointF pivotPoint = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
mFullScreenMagnificationController.setScale(DISPLAY_0, scale, pivotPoint.x, pivotPoint.y,
- false, SERVICE_ID_1);
+ true, false, SERVICE_ID_1);
}
private void initMockWindowManager() {
@@ -1578,7 +1678,7 @@
PointF startCenter = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
float scale = 2.0f;
mFullScreenMagnificationController.setScale(displayId, scale, startCenter.x, startCenter.y,
- false, SERVICE_ID_1);
+ true, false, SERVICE_ID_1);
checkActivatedAndMagnifying(/* activated= */ true, /* magnifying= */ true, displayId);
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
index e5831b3..9f5dd93 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
@@ -90,6 +90,7 @@
import com.android.server.accessibility.EventStreamTransformation;
import com.android.server.accessibility.Flags;
import com.android.server.accessibility.magnification.FullScreenMagnificationController.MagnificationInfoChangedCallback;
+import com.android.server.input.InputManagerInternal;
import com.android.server.testutils.OffsettableClock;
import com.android.server.testutils.TestHandler;
import com.android.server.wm.WindowManagerInternal;
@@ -227,9 +228,11 @@
final FullScreenMagnificationController.ControllerContext mockController =
mock(FullScreenMagnificationController.ControllerContext.class);
final WindowManagerInternal mockWindowManager = mock(WindowManagerInternal.class);
+ final InputManagerInternal mockInputManager = mock(InputManagerInternal.class);
when(mockController.getContext()).thenReturn(mContext);
when(mockController.getTraceManager()).thenReturn(mMockTraceManager);
when(mockController.getWindowManager()).thenReturn(mockWindowManager);
+ when(mockController.getInputManager()).thenReturn(mockInputManager);
when(mockController.getHandler()).thenReturn(new Handler(mContext.getMainLooper()));
when(mockController.newValueAnimator()).thenReturn(new ValueAnimator());
when(mockController.getAnimationDuration()).thenReturn(1000L);
@@ -1343,7 +1346,7 @@
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, persistedScale,
UserHandle.USER_SYSTEM);
mFullScreenMagnificationController.setScale(DISPLAY_0, scale, DEFAULT_X,
- DEFAULT_Y, /* animate= */ false,
+ DEFAULT_Y, true, /* animate= */ false,
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
mMgh.transitionTo(mMgh.mPanningScalingState);
@@ -1364,7 +1367,7 @@
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, persistedScale,
UserHandle.USER_SYSTEM);
mFullScreenMagnificationController.setScale(DISPLAY_0, scale, DEFAULT_X,
- DEFAULT_Y, /* animate= */ false,
+ DEFAULT_Y, true, /* animate= */ false,
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
mMgh.transitionTo(mMgh.mPanningScalingState);
@@ -1401,7 +1404,7 @@
mFullScreenMagnificationController.getPersistedScale(DISPLAY_0);
mFullScreenMagnificationController.setScale(DISPLAY_0, persistedScale, DEFAULT_X,
- DEFAULT_Y, /* animate= */ false,
+ DEFAULT_Y, true, /* animate= */ false,
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
mMgh.transitionTo(mMgh.mPanningScalingState);
@@ -1438,7 +1441,7 @@
(INITIAL_MAGNIFICATION_BOUNDS.top + INITIAL_MAGNIFICATION_BOUNDS.height()) / 2.0f;
float scale = 5.6f; // value is unimportant but unique among tests to increase coverage.
mFullScreenMagnificationController.setScaleAndCenter(
- DISPLAY_0, centerX, centerY, scale, /* animate= */ false, 1);
+ DISPLAY_0, centerX, centerY, scale, true, /* animate= */ false, 1);
centerX = mFullScreenMagnificationController.getCenterX(DISPLAY_0);
centerY = mFullScreenMagnificationController.getCenterY(DISPLAY_0);
@@ -1530,7 +1533,7 @@
(INITIAL_MAGNIFICATION_BOUNDS.top + INITIAL_MAGNIFICATION_BOUNDS.height()) / 2.0f;
float scale = 6.2f; // value is unimportant but unique among tests to increase coverage.
mFullScreenMagnificationController.setScaleAndCenter(
- DISPLAY_0, centerX, centerY, scale, /* animate= */ false, 1);
+ DISPLAY_0, centerX, centerY, scale, true, /* animate= */ false, 1);
MotionEvent event = mouseEvent(centerX, centerY, ACTION_HOVER_MOVE);
send(event, InputDevice.SOURCE_MOUSE);
fastForward(20);
@@ -1571,7 +1574,7 @@
(INITIAL_MAGNIFICATION_BOUNDS.top + INITIAL_MAGNIFICATION_BOUNDS.height()) / 2.0f;
float scale = 4.0f; // value is unimportant but unique among tests to increase coverage.
mFullScreenMagnificationController.setScaleAndCenter(
- DISPLAY_0, centerX, centerY, scale, /* animate= */ false, 1);
+ DISPLAY_0, centerX, centerY, scale, true, /* animate= */ false, 1);
// HOVER_MOVE should change magnifier viewport.
MotionEvent event = motionEvent(centerX + 20, centerY, ACTION_HOVER_MOVE);
@@ -1615,7 +1618,7 @@
(INITIAL_MAGNIFICATION_BOUNDS.top + INITIAL_MAGNIFICATION_BOUNDS.height()) / 2.0f;
float scale = 5.3f; // value is unimportant but unique among tests to increase coverage.
mFullScreenMagnificationController.setScaleAndCenter(
- DISPLAY_0, centerX, centerY, scale, /* animate= */ false, 1);
+ DISPLAY_0, centerX, centerY, scale, true, /* animate= */ false, 1);
MotionEvent event = motionEvent(centerX, centerY, ACTION_HOVER_MOVE);
send(event, source);
fastForward(20);
@@ -1649,7 +1652,7 @@
(INITIAL_MAGNIFICATION_BOUNDS.top + INITIAL_MAGNIFICATION_BOUNDS.height()) / 2.0f;
float scale = 2.7f; // value is unimportant but unique among tests to increase coverage.
mFullScreenMagnificationController.setScaleAndCenter(
- DISPLAY_0, centerX, centerY, scale, /* animate= */ false, 1);
+ DISPLAY_0, centerX, centerY, scale, true, /* animate= */ false, 1);
MotionEvent event = motionEvent(centerX, centerY, ACTION_HOVER_MOVE);
send(event, source);
fastForward(20);
@@ -1685,7 +1688,7 @@
(INITIAL_MAGNIFICATION_BOUNDS.top + INITIAL_MAGNIFICATION_BOUNDS.height()) / 2.0f;
float scale = 3.8f; // value is unimportant but unique among tests to increase coverage.
mFullScreenMagnificationController.setScaleAndCenter(
- DISPLAY_0, centerX, centerY, scale, /* animate= */ false, 1);
+ DISPLAY_0, centerX, centerY, scale, true, /* animate= */ false, 1);
centerX = mFullScreenMagnificationController.getCenterX(DISPLAY_0);
centerY = mFullScreenMagnificationController.getCenterY(DISPLAY_0);
@@ -1722,7 +1725,7 @@
(INITIAL_MAGNIFICATION_BOUNDS.top + INITIAL_MAGNIFICATION_BOUNDS.height()) / 2.0f;
float scale = 4.0f; // value is unimportant but unique among tests to increase coverage.
mFullScreenMagnificationController.setScaleAndCenter(
- DISPLAY_0, centerX, centerY, scale, /* animate= */ false, 1);
+ DISPLAY_0, centerX, centerY, scale, true, /* animate= */ false, 1);
centerX = mFullScreenMagnificationController.getCenterX(DISPLAY_0);
centerY = mFullScreenMagnificationController.getCenterY(DISPLAY_0);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
index 2528177..8164ef9 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
@@ -76,6 +76,7 @@
import com.android.server.accessibility.AccessibilityManagerService;
import com.android.server.accessibility.AccessibilityTraceManager;
import com.android.server.accessibility.test.MessageCapturingHandler;
+import com.android.server.input.InputManagerInternal;
import com.android.server.wm.WindowManagerInternal;
import com.android.window.flags.Flags;
@@ -154,6 +155,8 @@
private WindowManagerInternal mWindowManagerInternal;
@Mock
private WindowManagerInternal.AccessibilityControllerInternal mA11yController;
+ @Mock
+ private InputManagerInternal mInputManagerInternal;
@Mock
private DisplayManagerInternal mDisplayManagerInternal;
@@ -200,6 +203,7 @@
when(mControllerCtx.getContext()).thenReturn(mContext);
when(mControllerCtx.getTraceManager()).thenReturn(mTraceManager);
when(mControllerCtx.getWindowManager()).thenReturn(mWindowManagerInternal);
+ when(mControllerCtx.getInputManager()).thenReturn(mInputManagerInternal);
when(mControllerCtx.getHandler()).thenReturn(mMessageCapturingHandler);
when(mControllerCtx.getAnimationDuration()).thenReturn(1000L);
when(mControllerCtx.newValueAnimator()).thenReturn(mValueAnimator);
@@ -417,7 +421,7 @@
assertTrue(mMagnificationConnectionManager.isWindowMagnifierEnabled(TEST_DISPLAY));
verify(mScreenMagnificationController, never()).setScaleAndCenter(TEST_DISPLAY,
DEFAULT_SCALE, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y,
- true, MAGNIFICATION_GESTURE_HANDLER_ID);
+ true, true, MAGNIFICATION_GESTURE_HANDLER_ID);
verify(mTransitionCallBack).onResult(TEST_DISPLAY, false);
}
@@ -467,7 +471,7 @@
assertFalse(mMagnificationConnectionManager.isWindowMagnifierEnabled(TEST_DISPLAY));
verify(mScreenMagnificationController).setScaleAndCenter(eq(TEST_DISPLAY),
eq(DEFAULT_SCALE), eq(MAGNIFIED_CENTER_X), eq(MAGNIFIED_CENTER_Y),
- any(MagnificationAnimationCallback.class), eq(TEST_SERVICE_ID));
+ eq(false), any(MagnificationAnimationCallback.class), eq(TEST_SERVICE_ID));
}
@Test
@@ -484,7 +488,7 @@
verify(mScreenMagnificationController, never()).setScaleAndCenter(anyInt(),
anyFloat(), anyFloat(), anyFloat(),
- anyBoolean(), anyInt());
+ anyBoolean(), anyBoolean(), anyInt());
}
@Test
@@ -546,7 +550,7 @@
config, animate, TEST_SERVICE_ID);
verify(mScreenMagnificationController).setScaleAndCenter(eq(TEST_DISPLAY),
/* scale= */ anyFloat(), /* centerX= */ anyFloat(), /* centerY= */ anyFloat(),
- mCallbackArgumentCaptor.capture(), /* id= */ anyInt());
+ anyBoolean(), mCallbackArgumentCaptor.capture(), /* id= */ anyInt());
mCallbackArgumentCaptor.getValue().onResult(true);
mMockConnection.invokeCallbacks();
@@ -616,7 +620,7 @@
@Test
public void magnifyThroughExternalRequest_showMagnificationButton() {
mScreenMagnificationController.setScaleAndCenter(TEST_DISPLAY, DEFAULT_SCALE,
- MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y, false, TEST_SERVICE_ID);
+ MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y, true, false, TEST_SERVICE_ID);
// The first time is trigger when fullscreen mode is activated.
// The second time is triggered when magnification spec is changed.
@@ -638,7 +642,7 @@
mMagnificationController.onPerformScaleAction(TEST_DISPLAY, newScale, updatePersistence);
verify(mScreenMagnificationController).setScaleAndCenter(eq(TEST_DISPLAY), eq(newScale),
- anyFloat(), anyFloat(), anyBoolean(), anyInt());
+ anyFloat(), anyFloat(), anyBoolean(), anyBoolean(), anyInt());
verify(mScreenMagnificationController).persistScale(eq(TEST_DISPLAY));
}
@@ -681,7 +685,7 @@
final MagnificationConfig config = obtainMagnificationConfig(MODE_FULLSCREEN);
mScreenMagnificationController.setScaleAndCenter(TEST_DISPLAY,
config.getScale(), config.getCenterX(), config.getCenterY(),
- true, TEST_SERVICE_ID);
+ true, true, TEST_SERVICE_ID);
// The notify method is triggered when setting magnification enabled.
// The setScaleAndCenter call should not trigger notify method due to same scale and center.
@@ -930,7 +934,7 @@
public void onWindowModeActivated_fullScreenIsActivatedByExternal_fullScreenIsDisabled() {
mScreenMagnificationController.setScaleAndCenter(TEST_DISPLAY,
DEFAULT_SCALE, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y,
- true, TEST_SERVICE_ID);
+ true, true, TEST_SERVICE_ID);
mMagnificationController.onWindowMagnificationActivationState(TEST_DISPLAY, true);
@@ -1317,7 +1321,8 @@
}
if (mode == MODE_FULLSCREEN) {
mScreenMagnificationController.setScaleAndCenter(displayId, DEFAULT_SCALE, centerX,
- centerY, true, AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
+ centerY, true, true,
+ AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
} else {
mMagnificationConnectionManager.enableWindowMagnification(displayId, DEFAULT_SCALE,
centerX, centerY, null, TEST_SERVICE_ID);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index c30b4bb..c3466b9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -139,7 +139,6 @@
import android.os.Process;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
-import android.platform.test.annotations.RequiresFlagsEnabled;
import android.provider.DeviceConfig;
import android.util.MutableBoolean;
import android.view.DisplayInfo;
@@ -2662,8 +2661,11 @@
}
@Test
- @RequiresFlagsEnabled(Flags.FLAG_UNIVERSAL_RESIZABLE_BY_DEFAULT)
public void testSetOrientation_restrictedByTargetSdk() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_UNIVERSAL_RESIZABLE_BY_DEFAULT);
+ mDisplayContent.setIgnoreOrientationRequest(true);
+ makeDisplayLargeScreen(mDisplayContent);
+
assertSetOrientation(Build.VERSION_CODES.CUR_DEVELOPMENT, CATEGORY_SOCIAL, false);
assertSetOrientation(Build.VERSION_CODES.CUR_DEVELOPMENT, CATEGORY_GAME, true);
@@ -2673,12 +2675,13 @@
}
private void assertSetOrientation(int targetSdk, int category, boolean expectRotate) {
- final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
- activity.mTargetSdk = targetSdk;
+ final String packageName = targetSdk <= Build.VERSION_CODES.VANILLA_ICE_CREAM
+ ? mContext.getPackageName() // WmTests uses legacy sdk.
+ : null; // Simulate CUR_DEVELOPMENT by invalid package (see PlatformCompat).
+ final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true)
+ .setComponent(getUniqueComponentName(packageName)).build();
activity.info.applicationInfo.category = category;
- activity.setVisible(true);
-
// Assert orientation is unspecified to start.
assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, activity.getOrientation());
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java
index c8a3559..08963f1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java
@@ -307,6 +307,8 @@
void createNewTaskWithBaseActivity() {
final Task newTask = new WindowTestsBase.TaskBuilder(mSupervisor)
.setCreateActivity(true)
+ // Respect "@ChangeId" according to test package's target sdk.
+ .setPackage(mAtm.mContext.getPackageName())
.setDisplay(mDisplayContent).build();
mTaskStack.push(newTask);
pushActivity(newTask.getTopNonFinishingActivity());
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 5c0d424..2bebcc3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1081,7 +1081,8 @@
final DisplayRotation dr = dc.getDisplayRotation();
spyOn(dr);
doReturn(false).when(dr).useDefaultSettingsProvider();
- final ActivityRecord app = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ final ActivityRecord app = new ActivityBuilder(mAtm).setCreateTask(true)
+ .setComponent(getUniqueComponentName(mContext.getPackageName())).build();
app.setOrientation(SCREEN_ORIENTATION_LANDSCAPE, app);
assertFalse(dc.getRotationReversionController().isAnyOverrideActive());
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java
index 35c9e3f..f4fa12e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java
@@ -51,6 +51,7 @@
import android.app.servertransaction.RefreshCallbackItem;
import android.app.servertransaction.ResumeActivityItem;
import android.content.ComponentName;
+import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.ScreenOrientation;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -592,6 +593,11 @@
.setTask(mTask)
.build();
+ spyOn(mActivity.info.applicationInfo);
+ // Disable for camera compat.
+ doReturn(false).when(mActivity.info.applicationInfo).isChangeEnabled(
+ ActivityInfo.UNIVERSAL_RESIZABLE_BY_DEFAULT);
+
spyOn(mActivity.mAtmService.getLifecycleManager());
spyOn(mActivity.mAppCompatController.getAppCompatCameraOverrides());
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index cf1dcd0..7e8bd38 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -285,6 +285,52 @@
}
@Test
+ public void testTaskLayerRankFreeform() {
+ mSetFlagsRule.enableFlags(com.android.window.flags.Flags
+ .FLAG_PROCESS_PRIORITY_POLICY_FOR_MULTI_WINDOW_MODE);
+ final Task[] freeformTasks = new Task[3];
+ final WindowProcessController[] processes = new WindowProcessController[3];
+ for (int i = 0; i < freeformTasks.length; i++) {
+ freeformTasks[i] = new TaskBuilder(mSupervisor)
+ .setWindowingMode(WINDOWING_MODE_FREEFORM).setCreateActivity(true).build();
+ final ActivityRecord r = freeformTasks[i].getTopMostActivity();
+ r.setState(RESUMED, "test");
+ processes[i] = r.app;
+ }
+ resizeDisplay(mDisplayContent, 2400, 2000);
+ // ---------
+ // | 2 | 1 |
+ // ---------
+ // | 0 | |
+ // ---------
+ freeformTasks[2].setBounds(0, 0, 1000, 1000);
+ freeformTasks[1].setBounds(1000, 0, 2000, 1000);
+ freeformTasks[0].setBounds(0, 1000, 1000, 2000);
+ mRootWindowContainer.rankTaskLayers();
+ assertEquals(1, freeformTasks[2].mLayerRank);
+ assertEquals(2, freeformTasks[1].mLayerRank);
+ assertEquals(3, freeformTasks[0].mLayerRank);
+ assertFalse("Top doesn't need perceptible hint", (processes[2].getActivityStateFlags()
+ & WindowProcessController.ACTIVITY_STATE_FLAG_PERCEPTIBLE_FREEFORM) != 0);
+ assertTrue((processes[1].getActivityStateFlags()
+ & WindowProcessController.ACTIVITY_STATE_FLAG_PERCEPTIBLE_FREEFORM) != 0);
+ assertTrue((processes[0].getActivityStateFlags()
+ & WindowProcessController.ACTIVITY_STATE_FLAG_PERCEPTIBLE_FREEFORM) != 0);
+
+ // Make task2 occlude half of task0.
+ clearInvocations(mAtm);
+ freeformTasks[2].setBounds(0, 0, 1000, 1500);
+ waitHandlerIdle(mWm.mH);
+ // The process of task0 will demote from perceptible to visible.
+ final int stateFlags0 = processes[0].getActivityStateFlags();
+ assertTrue((stateFlags0
+ & WindowProcessController.ACTIVITY_STATE_FLAG_VISIBLE_MULTI_WINDOW_MODE) != 0);
+ assertFalse((stateFlags0
+ & WindowProcessController.ACTIVITY_STATE_FLAG_PERCEPTIBLE_FREEFORM) != 0);
+ verify(mAtm).updateOomAdj();
+ }
+
+ @Test
public void testForceStopPackage() {
final Task task = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
final ActivityRecord activity = task.getTopMostActivity();
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index e956e22..e66dfeb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -4824,12 +4824,7 @@
assertFalse(mActivity.isUniversalResizeable());
mDisplayContent.setIgnoreOrientationRequest(true);
- final int swDp = mDisplayContent.getConfiguration().smallestScreenWidthDp;
- if (swDp < WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP) {
- final int height = 100 + (int) (mDisplayContent.getDisplayMetrics().density
- * WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP);
- resizeDisplay(mDisplayContent, 100 + height, height);
- }
+ makeDisplayLargeScreen(mDisplayContent);
assertTrue(mActivity.isUniversalResizeable());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index a215c0a..757c358 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -1123,6 +1123,15 @@
displayContent.onRequestedOverrideConfigurationChanged(c);
}
+ static void makeDisplayLargeScreen(DisplayContent displayContent) {
+ final int swDp = displayContent.getConfiguration().smallestScreenWidthDp;
+ if (swDp < WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP) {
+ final int height = 100 + (int) (displayContent.getDisplayMetrics().density
+ * WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP);
+ resizeDisplay(displayContent, 100 + height, height);
+ }
+ }
+
/** Used for the tests that assume the display is portrait by default. */
static void makeDisplayPortrait(DisplayContent displayContent) {
if (displayContent.mBaseDisplayHeight <= displayContent.mBaseDisplayWidth) {
@@ -1223,7 +1232,14 @@
}
static ComponentName getUniqueComponentName() {
- return ComponentName.createRelative(DEFAULT_COMPONENT_PACKAGE_NAME,
+ return getUniqueComponentName(DEFAULT_COMPONENT_PACKAGE_NAME);
+ }
+
+ static ComponentName getUniqueComponentName(String packageName) {
+ if (packageName == null) {
+ packageName = DEFAULT_COMPONENT_PACKAGE_NAME;
+ }
+ return ComponentName.createRelative(packageName,
DEFAULT_COMPONENT_CLASS_NAME + sCurrentActivityId++);
}
@@ -1298,8 +1314,7 @@
ActivityBuilder setActivityTheme(int theme) {
mActivityTheme = theme;
// Use the real package of test so it can get a valid context for theme.
- mComponent = ComponentName.createRelative(mService.mContext.getPackageName(),
- DEFAULT_COMPONENT_CLASS_NAME + sCurrentActivityId++);
+ mComponent = getUniqueComponentName(mService.mContext.getPackageName());
return this;
}
@@ -1743,7 +1758,7 @@
if (mIntent == null) {
mIntent = new Intent();
if (mComponent == null) {
- mComponent = getUniqueComponentName();
+ mComponent = getUniqueComponentName(mPackage);
}
mIntent.setComponent(mComponent);
mIntent.setFlags(mFlags);
diff --git a/tests/Input/Android.bp b/tests/Input/Android.bp
index 6742cbe..168141b 100644
--- a/tests/Input/Android.bp
+++ b/tests/Input/Android.bp
@@ -41,6 +41,7 @@
"hamcrest-library",
"junit-params",
"kotlin-test",
+ "mockito-kotlin-nodeps",
"mockito-target-extended-minus-junit4",
"platform-test-annotations",
"platform-screenshot-diff-core",
diff --git a/tests/Input/src/com/android/server/input/PointerIconCacheTest.kt b/tests/Input/src/com/android/server/input/PointerIconCacheTest.kt
new file mode 100644
index 0000000..47e7ac7
--- /dev/null
+++ b/tests/Input/src/com/android/server/input/PointerIconCacheTest.kt
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2024 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 com.android.server.input
+
+import android.content.Context
+import android.content.ContextWrapper
+import android.os.Handler
+import android.os.test.TestLooper
+import android.platform.test.annotations.Presubmit
+import android.view.Display
+import android.view.PointerIcon
+import androidx.test.platform.app.InstrumentationRegistry
+import junit.framework.Assert.assertEquals
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.mockito.Mock
+import org.mockito.junit.MockitoJUnit
+import org.mockito.kotlin.times
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+
+/**
+ * Tests for {@link PointerIconCache}.
+ */
+@Presubmit
+class PointerIconCacheTest {
+
+ @get:Rule
+ val rule = MockitoJUnit.rule()!!
+
+ @Mock
+ private lateinit var native: NativeInputManagerService
+ @Mock
+ private lateinit var defaultDisplay: Display
+
+ private lateinit var context: Context
+ private lateinit var testLooper: TestLooper
+ private lateinit var cache: PointerIconCache
+
+ @Before
+ fun setup() {
+ whenever(defaultDisplay.displayId).thenReturn(Display.DEFAULT_DISPLAY)
+
+ context = object : ContextWrapper(InstrumentationRegistry.getInstrumentation().context) {
+ override fun getDisplay() = defaultDisplay
+ }
+
+ testLooper = TestLooper()
+ cache = PointerIconCache(context, native, Handler(testLooper.looper))
+ }
+
+ @Test
+ fun testSetPointerScale() {
+ val defaultBitmap = getDefaultIcon().bitmap
+ cache.setPointerScale(2f)
+
+ testLooper.dispatchAll()
+ verify(native).reloadPointerIcons()
+
+ val bitmap =
+ cache.getLoadedPointerIcon(Display.DEFAULT_DISPLAY, PointerIcon.TYPE_ARROW).bitmap
+
+ assertEquals(defaultBitmap.height * 2, bitmap.height)
+ assertEquals(defaultBitmap.width * 2, bitmap.width)
+ }
+
+ @Test
+ fun testSetAccessibilityScaleFactor() {
+ val defaultBitmap = getDefaultIcon().bitmap
+ cache.setAccessibilityScaleFactor(Display.DEFAULT_DISPLAY, 4f)
+
+ testLooper.dispatchAll()
+ verify(native).reloadPointerIcons()
+
+ val bitmap =
+ cache.getLoadedPointerIcon(Display.DEFAULT_DISPLAY, PointerIcon.TYPE_ARROW).bitmap
+
+ assertEquals(defaultBitmap.height * 4, bitmap.height)
+ assertEquals(defaultBitmap.width * 4, bitmap.width)
+ }
+
+ @Test
+ fun testSetAccessibilityScaleFactorOnSecondaryDisplay() {
+ val defaultBitmap = getDefaultIcon().bitmap
+ val secondaryDisplayId = Display.DEFAULT_DISPLAY + 1
+ cache.setAccessibilityScaleFactor(secondaryDisplayId, 4f)
+
+ testLooper.dispatchAll()
+ verify(native).reloadPointerIcons()
+
+ val bitmap =
+ cache.getLoadedPointerIcon(Display.DEFAULT_DISPLAY, PointerIcon.TYPE_ARROW).bitmap
+ assertEquals(defaultBitmap.height, bitmap.height)
+ assertEquals(defaultBitmap.width, bitmap.width)
+
+ val bitmapSecondary =
+ cache.getLoadedPointerIcon(secondaryDisplayId, PointerIcon.TYPE_ARROW).bitmap
+ assertEquals(defaultBitmap.height * 4, bitmapSecondary.height)
+ assertEquals(defaultBitmap.width * 4, bitmapSecondary.width)
+ }
+
+ @Test
+ fun testSetPointerScaleAndAccessibilityScaleFactor() {
+ val defaultBitmap = getDefaultIcon().bitmap
+ cache.setPointerScale(2f)
+ cache.setAccessibilityScaleFactor(Display.DEFAULT_DISPLAY, 3f)
+
+ testLooper.dispatchAll()
+ verify(native, times(2)).reloadPointerIcons()
+
+ val bitmap =
+ cache.getLoadedPointerIcon(Display.DEFAULT_DISPLAY, PointerIcon.TYPE_ARROW).bitmap
+
+ assertEquals(defaultBitmap.height * 6, bitmap.height)
+ assertEquals(defaultBitmap.width * 6, bitmap.width)
+ }
+
+ private fun getDefaultIcon() =
+ PointerIcon.getLoadedSystemIcon(context, PointerIcon.TYPE_ARROW, false, 1f)
+}