Merge "add shell user permissions for Asistant GTS tests"
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
index 736ee18..f2d10ac 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -2296,31 +2296,35 @@
@Override
public void onAppAdded(int uid) {
- final long nowElapsed = sElapsedRealtimeClock.millis();
- mTempAllowlistCache.put(uid, true);
- final ArraySet<String> packages = getPackagesForUid(uid);
- if (packages != null) {
- final int userId = UserHandle.getUserId(uid);
- for (int i = packages.size() - 1; i >= 0; --i) {
- Timer t = mEJPkgTimers.get(userId, packages.valueAt(i));
- if (t != null) {
- t.onStateChangedLocked(nowElapsed, true);
+ synchronized (mLock) {
+ final long nowElapsed = sElapsedRealtimeClock.millis();
+ mTempAllowlistCache.put(uid, true);
+ final ArraySet<String> packages = getPackagesForUidLocked(uid);
+ if (packages != null) {
+ final int userId = UserHandle.getUserId(uid);
+ for (int i = packages.size() - 1; i >= 0; --i) {
+ Timer t = mEJPkgTimers.get(userId, packages.valueAt(i));
+ if (t != null) {
+ t.onStateChangedLocked(nowElapsed, true);
+ }
}
- }
- if (maybeUpdateConstraintForUidLocked(uid)) {
- mStateChangedListener.onControllerStateChanged();
+ if (maybeUpdateConstraintForUidLocked(uid)) {
+ mStateChangedListener.onControllerStateChanged();
+ }
}
}
}
@Override
public void onAppRemoved(int uid) {
- final long nowElapsed = sElapsedRealtimeClock.millis();
- final long endElapsed = nowElapsed + mEJTempAllowlistGracePeriodMs;
- mTempAllowlistCache.delete(uid);
- mTempAllowlistGraceCache.put(uid, endElapsed);
- Message msg = mHandler.obtainMessage(MSG_END_GRACE_PERIOD, uid, 0);
- mHandler.sendMessageDelayed(msg, mEJTempAllowlistGracePeriodMs);
+ synchronized (mLock) {
+ final long nowElapsed = sElapsedRealtimeClock.millis();
+ final long endElapsed = nowElapsed + mEJTempAllowlistGracePeriodMs;
+ mTempAllowlistCache.delete(uid);
+ mTempAllowlistGraceCache.put(uid, endElapsed);
+ Message msg = mHandler.obtainMessage(MSG_END_GRACE_PERIOD, uid, 0);
+ mHandler.sendMessageDelayed(msg, mEJTempAllowlistGracePeriodMs);
+ }
}
}
@@ -2351,7 +2355,7 @@
}
@Nullable
- private ArraySet<String> getPackagesForUid(final int uid) {
+ private ArraySet<String> getPackagesForUidLocked(final int uid) {
ArraySet<String> packages = mUidToPackageCache.get(uid);
if (packages == null) {
try {
@@ -2475,7 +2479,7 @@
// Update Timers first.
if (mPkgTimers.indexOfKey(userId) >= 0
|| mEJPkgTimers.indexOfKey(userId) >= 0) {
- final ArraySet<String> packages = getPackagesForUid(uid);
+ final ArraySet<String> packages = getPackagesForUidLocked(uid);
if (packages != null) {
for (int i = packages.size() - 1; i >= 0; --i) {
Timer t = mEJPkgTimers.get(userId, packages.valueAt(i));
@@ -2544,7 +2548,7 @@
if (DEBUG) {
Slog.d(TAG, uid + " is now out of grace period");
}
- final ArraySet<String> packages = getPackagesForUid(uid);
+ final ArraySet<String> packages = getPackagesForUidLocked(uid);
if (packages != null) {
final int userId = UserHandle.getUserId(uid);
final long nowElapsed = sElapsedRealtimeClock.millis();
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 3495f95..faf784d 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -1927,6 +1927,7 @@
field public static final String CONTEXTHUB_SERVICE = "contexthub";
field public static final String ETHERNET_SERVICE = "ethernet";
field public static final String EUICC_CARD_SERVICE = "euicc_card";
+ field public static final String FONT_SERVICE = "font";
field public static final String HDMI_CONTROL_SERVICE = "hdmi_control";
field public static final String MEDIA_TRANSCODING_SERVICE = "media_transcoding";
field public static final String MUSIC_RECOGNITION_SERVICE = "music_recognition";
@@ -2588,6 +2589,14 @@
}
+package android.graphics.fonts {
+
+ public class FontManager {
+ method @Nullable public android.text.FontConfig getFontConfig();
+ }
+
+}
+
package android.hardware {
public final class Sensor {
@@ -11879,7 +11888,6 @@
public abstract class DataService.DataServiceProvider implements java.lang.AutoCloseable {
ctor public DataService.DataServiceProvider(int);
- method public void cancelHandover(int, @NonNull android.telephony.data.DataServiceCallback);
method public abstract void close();
method public void deactivateDataCall(int, int, @Nullable android.telephony.data.DataServiceCallback);
method public final int getSlotIndex();
@@ -11890,15 +11898,12 @@
method public void setInitialAttachApn(@NonNull android.telephony.data.DataProfile, boolean, @NonNull android.telephony.data.DataServiceCallback);
method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @NonNull android.telephony.data.DataServiceCallback);
method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @IntRange(from=0, to=15) int, @Nullable android.telephony.data.SliceInfo, @NonNull android.telephony.data.DataServiceCallback);
- method public void startHandover(int, @NonNull android.telephony.data.DataServiceCallback);
}
public class DataServiceCallback {
method public void onApnUnthrottled(@NonNull String);
method public void onDataCallListChanged(@NonNull java.util.List<android.telephony.data.DataCallResponse>);
method public void onDeactivateDataCallComplete(int);
- method public void onHandoverCancelled(int);
- method public void onHandoverStarted(int);
method public void onRequestDataCallListComplete(int, @NonNull java.util.List<android.telephony.data.DataCallResponse>);
method public void onSetDataProfileComplete(int);
method public void onSetInitialAttachApnComplete(int);
@@ -13451,6 +13456,51 @@
}
+package android.text {
+
+ public final class FontConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.util.List<android.text.FontConfig.Alias> getAliases();
+ method @NonNull public java.util.List<android.text.FontConfig.FontFamily> getFontFamilies();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.text.FontConfig> CREATOR;
+ }
+
+ public static final class FontConfig.Alias implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public String getName();
+ method @NonNull public String getOriginal();
+ method @IntRange(from=0, to=1000) public int getWeight();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.text.FontConfig.Alias> CREATOR;
+ }
+
+ public static final class FontConfig.Font implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.io.File getFile();
+ method @Nullable public String getFontFamilyName();
+ method @NonNull public String getFontVariationSettings();
+ method @NonNull public android.graphics.fonts.FontStyle getStyle();
+ method public int getTtcIndex();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.text.FontConfig.Font> CREATOR;
+ }
+
+ public static final class FontConfig.FontFamily implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.util.List<android.text.FontConfig.Font> getFontList();
+ method @NonNull public android.os.LocaleList getLocaleList();
+ method @Nullable public String getName();
+ method public int getVariant();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.text.FontConfig.FontFamily> CREATOR;
+ field public static final int VARIANT_COMPACT = 1; // 0x1
+ field public static final int VARIANT_DEFAULT = 0; // 0x0
+ field public static final int VARIANT_ELEGANT = 2; // 0x2
+ }
+
+}
+
package android.util {
public class EventLog {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 5957292..c237d7d 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -627,6 +627,7 @@
field public static final String CONTENT_CAPTURE_MANAGER_SERVICE = "content_capture";
field public static final String DEVICE_IDLE_CONTROLLER = "deviceidle";
field public static final String DREAM_SERVICE = "dream";
+ field public static final String FONT_SERVICE = "font";
field public static final String POWER_WHITELIST_MANAGER = "power_whitelist";
field public static final String TEST_NETWORK_SERVICE = "test_network";
}
@@ -819,6 +820,14 @@
}
+package android.graphics.fonts {
+
+ public class FontManager {
+ method @Nullable public android.text.FontConfig getFontConfig();
+ }
+
+}
+
package android.hardware {
public final class SensorPrivacyManager {
@@ -2019,6 +2028,47 @@
package android.text {
+ public final class FontConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.util.List<android.text.FontConfig.Alias> getAliases();
+ method @NonNull public java.util.List<android.text.FontConfig.FontFamily> getFontFamilies();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.text.FontConfig> CREATOR;
+ }
+
+ public static final class FontConfig.Alias implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public String getName();
+ method @NonNull public String getOriginal();
+ method @IntRange(from=0, to=1000) public int getWeight();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.text.FontConfig.Alias> CREATOR;
+ }
+
+ public static final class FontConfig.Font implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.io.File getFile();
+ method @Nullable public String getFontFamilyName();
+ method @NonNull public String getFontVariationSettings();
+ method @NonNull public android.graphics.fonts.FontStyle getStyle();
+ method public int getTtcIndex();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.text.FontConfig.Font> CREATOR;
+ }
+
+ public static final class FontConfig.FontFamily implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.util.List<android.text.FontConfig.Font> getFontList();
+ method @NonNull public android.os.LocaleList getLocaleList();
+ method @Nullable public String getName();
+ method public int getVariant();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.text.FontConfig.FontFamily> CREATOR;
+ field public static final int VARIANT_COMPACT = 1; // 0x1
+ field public static final int VARIANT_DEFAULT = 0; // 0x0
+ field public static final int VARIANT_ELEGANT = 2; // 0x2
+ }
+
public static final class Selection.MemoryTextWatcher implements android.text.TextWatcher {
ctor public Selection.MemoryTextWatcher();
method public void afterTextChanged(android.text.Editable);
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 5b0ad22..e084c01 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -72,6 +72,7 @@
import android.content.rollback.RollbackManagerFrameworkInitializer;
import android.debug.AdbManager;
import android.debug.IAdbManager;
+import android.graphics.fonts.FontManager;
import android.hardware.ConsumerIrManager;
import android.hardware.ISerialManager;
import android.hardware.SensorManager;
@@ -216,6 +217,7 @@
import com.android.internal.app.IBatteryStats;
import com.android.internal.app.ISoundTriggerService;
import com.android.internal.appwidget.IAppWidgetService;
+import com.android.internal.graphics.fonts.IFontManager;
import com.android.internal.net.INetworkWatchlistManager;
import com.android.internal.os.IDropBoxManagerService;
import com.android.internal.policy.PhoneLayoutInflater;
@@ -344,6 +346,14 @@
return new TextClassificationManager(ctx);
}});
+ registerService(Context.FONT_SERVICE, FontManager.class,
+ new CachedServiceFetcher<FontManager>() {
+ @Override
+ public FontManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.FONT_SERVICE);
+ return FontManager.create(IFontManager.Stub.asInterface(b));
+ }});
+
registerService(Context.CLIPBOARD_SERVICE, ClipboardManager.class,
new CachedServiceFetcher<ClipboardManager>() {
@Override
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 3f7479b..6df4304 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4478,6 +4478,18 @@
/**
* Use with {@link #getSystemService(String)} to retrieve a
+ * {@link android.graphics.fonts.FontManager} for font services.
+ *
+ * @see #getSystemService(String)
+ * @see android.graphics.fonts.FontManager
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ public static final String FONT_SERVICE = "font";
+
+ /**
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link com.android.server.attention.AttentionManagerService} for attention services.
*
* @see #getSystemService(String)
diff --git a/core/java/android/graphics/fonts/FontManager.java b/core/java/android/graphics/fonts/FontManager.java
new file mode 100644
index 0000000..ea6cf2f
--- /dev/null
+++ b/core/java/android/graphics/fonts/FontManager.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2021 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.graphics.fonts;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.annotation.TestApi;
+import android.content.Context;
+import android.os.RemoteException;
+import android.text.FontConfig;
+import android.util.Log;
+
+import com.android.internal.graphics.fonts.IFontManager;
+
+import java.util.Objects;
+
+/**
+ * This class gives you control of system installed font files.
+ * @hide
+ */
+@SystemApi
+@TestApi
+@SystemService(Context.FONT_SERVICE)
+public class FontManager {
+ private static final String TAG = "FontManager";
+ private final @NonNull IFontManager mIFontManager;
+
+ private FontManager(@NonNull IFontManager iFontManager) {
+ mIFontManager = iFontManager;
+ }
+
+ /**
+ * Returns the system font configuration.
+ *
+ * This information is expected to be used by system font updater. If you are looking for APIs
+ * about drawing text and/or high-level system font information, use
+ * {@link android.graphics.Typeface} or {@link SystemFonts} instead.
+ *
+ * @return The current font configuration. null if failed to fetch information from the system
+ * service.
+ */
+ public @Nullable FontConfig getFontConfig() {
+ try {
+ return mIFontManager.getFontConfig();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to call getFontConfig", e);
+ return null;
+ }
+ }
+
+ /**
+ * Factory method of the FontManager.
+ *
+ * Do not use this method directly. Use getSystemService(Context.FONT_SERVICE) instead.
+ *
+ * @return A new instance of FontManager
+ * @hide
+ */
+ public static FontManager create(@NonNull IFontManager iFontManager) {
+ Objects.requireNonNull(iFontManager);
+ return new FontManager(iFontManager);
+ }
+}
diff --git a/core/java/android/graphics/fonts/SystemFontState.aidl b/core/java/android/graphics/fonts/SystemFontState.aidl
new file mode 100644
index 0000000..19b20f2
--- /dev/null
+++ b/core/java/android/graphics/fonts/SystemFontState.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2021 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.graphics.fonts;
+
+/** @hide */
+parcelable SystemFontState;
\ No newline at end of file
diff --git a/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl b/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl
index aced9c7..c3b6c05 100644
--- a/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl
+++ b/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl
@@ -22,7 +22,9 @@
oneway interface IUdfpsOverlayController {
const int REASON_UNKNOWN = 0;
const int REASON_ENROLL = 1;
- const int REASON_AUTH = 2;
+ const int REASON_AUTH_BP = 2; // BiometricPrompt
+ const int REASON_AUTH_FPM_KEYGUARD = 3; // FingerprintManager usage from Keyguard
+ const int REASON_AUTH_FPM_OTHER = 4; // Other FingerprintManager usage
// Shows the overlay.
void showUdfpsOverlay(int sensorId, int reason);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 743713c..ac685f7 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10347,6 +10347,7 @@
* or moving onto external storage. (0 = false, 1 = true)
* @hide
*/
+ @Readable
public static final String FORCE_ALLOW_ON_EXTERNAL = "force_allow_on_external";
/**
diff --git a/core/java/android/service/voice/VoiceInteractionServiceInfo.java b/core/java/android/service/voice/VoiceInteractionServiceInfo.java
index e1a9a05..f7710e6 100644
--- a/core/java/android/service/voice/VoiceInteractionServiceInfo.java
+++ b/core/java/android/service/voice/VoiceInteractionServiceInfo.java
@@ -17,6 +17,7 @@
package android.service.voice;
import android.Manifest;
+import android.annotation.NonNull;
import android.app.AppGlobals;
import android.content.ComponentName;
import android.content.pm.PackageManager;
@@ -28,6 +29,7 @@
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -47,24 +49,27 @@
private boolean mSupportsLaunchFromKeyguard;
private boolean mSupportsLocalInteraction;
- public VoiceInteractionServiceInfo(PackageManager pm, ComponentName comp)
- throws PackageManager.NameNotFoundException {
- this(pm, pm.getServiceInfo(comp, PackageManager.GET_META_DATA));
- }
-
- public VoiceInteractionServiceInfo(PackageManager pm, ComponentName comp, int userHandle)
+ /**
+ * Loads the service metadata published by the component. Success is indicated by
+ * {@link #getParseError()}.
+ *
+ * @param pm A PackageManager from which the XML can be loaded.
+ * @param comp The {@link VoiceInteractionService} component.
+ */
+ public VoiceInteractionServiceInfo(
+ @NonNull PackageManager pm, @NonNull ComponentName comp, int userHandle)
throws PackageManager.NameNotFoundException {
this(pm, getServiceInfoOrThrow(comp, userHandle));
}
- static ServiceInfo getServiceInfoOrThrow(ComponentName comp, int userHandle)
+ @NonNull
+ private static ServiceInfo getServiceInfoOrThrow(@NonNull ComponentName comp, int userHandle)
throws PackageManager.NameNotFoundException {
try {
ServiceInfo si = AppGlobals.getPackageManager().getServiceInfo(comp,
PackageManager.GET_META_DATA
| PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
- | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
userHandle);
if (si != null) {
return si;
@@ -74,20 +79,23 @@
throw new PackageManager.NameNotFoundException(comp.toString());
}
- public VoiceInteractionServiceInfo(PackageManager pm, ServiceInfo si) {
- if (si == null) {
- mParseError = "Service not available";
- return;
- }
+ /**
+ * Loads the service metadata published by the component. Success is indicated by
+ * {@link #getParseError()}.
+ *
+ * @param pm A PackageManager from which the XML can be loaded; usually the PackageManager
+ * from which {@code si} was originally retrieved.
+ * @param si The {@link VoiceInteractionService} info.
+ */
+ public VoiceInteractionServiceInfo(@NonNull PackageManager pm, @NonNull ServiceInfo si) {
if (!Manifest.permission.BIND_VOICE_INTERACTION.equals(si.permission)) {
mParseError = "Service does not require permission "
+ Manifest.permission.BIND_VOICE_INTERACTION;
return;
}
- XmlResourceParser parser = null;
- try {
- parser = si.loadXmlMetaData(pm, VoiceInteractionService.SERVICE_META_DATA);
+ try (XmlResourceParser parser = si.loadXmlMetaData(pm,
+ VoiceInteractionService.SERVICE_META_DATA)) {
if (parser == null) {
mParseError = "No " + VoiceInteractionService.SERVICE_META_DATA
+ " meta-data for " + si.packageName;
@@ -134,20 +142,10 @@
mParseError = "No recognitionService specified";
return;
}
- } catch (XmlPullParserException e) {
+ } catch (XmlPullParserException | IOException | PackageManager.NameNotFoundException e) {
mParseError = "Error parsing voice interation service meta-data: " + e;
Log.w(TAG, "error parsing voice interaction service meta-data", e);
return;
- } catch (IOException e) {
- mParseError = "Error parsing voice interation service meta-data: " + e;
- Log.w(TAG, "error parsing voice interaction service meta-data", e);
- return;
- } catch (PackageManager.NameNotFoundException e) {
- mParseError = "Error parsing voice interation service meta-data: " + e;
- Log.w(TAG, "error parsing voice interaction service meta-data", e);
- return;
- } finally {
- if (parser != null) parser.close();
}
mServiceInfo = si;
}
diff --git a/core/java/android/text/FontConfig.java b/core/java/android/text/FontConfig.java
index 8492363..82d7399 100644
--- a/core/java/android/text/FontConfig.java
+++ b/core/java/android/text/FontConfig.java
@@ -22,51 +22,66 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.fonts.FontStyle;
import android.graphics.fonts.FontVariationAxis;
import android.os.Build;
import android.os.LocaleList;
+import android.os.Parcel;
+import android.os.Parcelable;
import java.io.File;
import java.lang.annotation.Retention;
+import java.util.ArrayList;
import java.util.List;
/**
* Font configuration descriptions for System fonts.
- * @hide // TODO Make this SystemApi.
+ *
+ * FontConfig represents the configuration for the fonts installed on the system. It is made of list
+ * of font families and aliases.
+ *
+ * @see FontFamily
+ * @see Alias
+ * @hide
*/
-public final class FontConfig {
- private final @NonNull List<Family> mFamilies;
+@SystemApi
+@TestApi
+public final class FontConfig implements Parcelable {
+ private final @NonNull List<FontFamily> mFamilies;
private final @NonNull List<Alias> mAliases;
/**
- * Construct a SystemFontConfig instance.
+ * Construct a FontConfig instance.
*
* @param families a list of font families.
* @param aliases a list of aliases.
*
* @hide Only system server can create this instance and passed via IPC.
*/
- public FontConfig(@NonNull List<Family> families, @NonNull List<Alias> aliases) {
+ public FontConfig(@NonNull List<FontFamily> families, @NonNull List<Alias> aliases) {
mFamilies = families;
mAliases = aliases;
}
/**
- * Returns the ordered list of families included in the system fonts.
+ * Returns the ordered list of font families available in the system.
*
* @return a list of font families.
+ * @see FontFamily
*/
- public @NonNull List<Family> getFontFamilies() {
+ public @NonNull List<FontFamily> getFontFamilies() {
return mFamilies;
}
/**
- * Returns the list of aliases defined for the font families in the system fonts.
+ * Returns the list of aliases for mapping font families with other names.
*
* @return a list of font families.
+ * @see Alias
*/
public @NonNull List<Alias> getAliases() {
return mAliases;
@@ -75,106 +90,167 @@
/**
* Returns the ordered list of families included in the system fonts.
* @deprecated Use getFontFamilies instead.
+ * @hide
*/
@Deprecated
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public @NonNull Family[] getFamilies() {
- return mFamilies.toArray(new Family[0]);
+ public @NonNull FontFamily[] getFamilies() {
+ return mFamilies.toArray(new FontFamily[0]);
}
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeParcelableList(mFamilies, flags);
+ dest.writeParcelableList(mAliases, flags);
+ }
+
+ public static final @NonNull Creator<FontConfig> CREATOR = new Creator<FontConfig>() {
+ @Override
+ public FontConfig createFromParcel(Parcel source) {
+ List<FontFamily> families = source.readParcelableList(new ArrayList<>(),
+ FontFamily.class.getClassLoader());
+ List<Alias> aliases = source.readParcelableList(new ArrayList<>(),
+ Alias.class.getClassLoader());
+ return new FontConfig(families, aliases);
+ }
+
+ @Override
+ public FontConfig[] newArray(int size) {
+ return new FontConfig[size];
+ }
+ };
+
/**
- * A class represents single font entry in system font configuration.
+ * Represents single font entry in system font configuration.
+ *
+ * A font is the most primitive unit of drawing character shapes. A font in system configuration
+ * is always referring a single OpenType compliant regular file in the file system.
+ *
+ * @see android.graphics.fonts.Font
*/
- public static final class Font {
- private final @NonNull File mFilePath;
- private final @Nullable File mOriginalPath;
+ public static final class Font implements Parcelable {
+ private final @NonNull File mFile;
+ private final @Nullable File mOriginalFile;
private final @NonNull FontStyle mStyle;
private final @IntRange(from = 0) int mIndex;
private final @NonNull String mFontVariationSettings;
- private final @Nullable String mFallback;
+ private final @Nullable String mFontFamilyName;
/**
* Construct a Font instance.
*
* @hide Only system server can create this instance and passed via IPC.
*/
- public Font(@NonNull File filePath, @Nullable File originalPath, @NonNull FontStyle style,
+ public Font(@NonNull File file, @Nullable File originalFile, @NonNull FontStyle style,
@IntRange(from = 0) int index, @NonNull String fontVariationSettings,
- @Nullable String fallback) {
- mFilePath = filePath;
- mOriginalPath = originalPath;
+ @Nullable String fontFamilyName) {
+ mFile = file;
+ mOriginalFile = originalFile;
mStyle = style;
mIndex = index;
mFontVariationSettings = fontVariationSettings;
- mFallback = fallback;
+ mFontFamilyName = fontFamilyName;
}
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString8(mFile.getAbsolutePath());
+ dest.writeString8(mOriginalFile == null ? null : mOriginalFile.getAbsolutePath());
+ dest.writeInt(mStyle.getWeight());
+ dest.writeInt(mStyle.getSlant());
+ dest.writeInt(mIndex);
+ dest.writeString8(mFontVariationSettings);
+ dest.writeString8(mFontFamilyName);
+ }
+
+ public static final @NonNull Creator<Font> CREATOR = new Creator<Font>() {
+
+ @Override
+ public Font createFromParcel(Parcel source) {
+ File path = new File(source.readString8());
+ String originalPathStr = source.readString8();
+ File originalPath = originalPathStr == null ? null : new File(originalPathStr);
+ int weight = source.readInt();
+ int slant = source.readInt();
+ int index = source.readInt();
+ String varSettings = source.readString8();
+ String fallback = source.readString8();
+
+ return new Font(path, originalPath, new FontStyle(weight, slant), index,
+ varSettings, fallback);
+ }
+
+ @Override
+ public Font[] newArray(int size) {
+ return new Font[size];
+ }
+ };
+
/**
- * Returns a file to the font file.
- *
- * @return a font file.
+ * Returns the font file.
*/
- public @NonNull File getFilePath() {
- return mFilePath;
+ public @NonNull File getFile() {
+ return mFile;
}
/**
- * Returns an original font file in the system directory.
+ * Returns the original font file in the system directory.
*
* If the font file is not updated, returns null.
*
* @return returns the original font file in the system if the font file is updated. Returns
* null if the font file is not updated.
+ * @hide
*/
- public @Nullable File getOriginalPath() {
- return mOriginalPath;
+ public @Nullable File getOriginalFile() {
+ return mOriginalFile;
}
/**
- * Returns a font style.
- *
- * @return a font style.
+ * Returns the font style.
*/
public @NonNull FontStyle getStyle() {
return mStyle;
}
- /**
- * Returns a font index.
- *
- * @return a font index.
- */
- public @IntRange(from = 0) int getIndex() {
- return mIndex;
- }
/**
* Return a font variation settings.
- *
- * @return a font variation settings.
*/
public @NonNull String getFontVariationSettings() {
return mFontVariationSettings;
}
/**
- * Returns font family name that uses this font as a fallback.
+ * A {@link Font} can be configured to be in the {@code Fallback List} for a
+ * {@link FontFamily}.
*
- * If this font is a fallback for the default font family, this is null.
+ * For example a serif Hebrew [Font] can be defined in the {@code Fallback List} for
+ * {@code "serif"} {@link FontFamily}.
*
- * @return a font family name.
+ * If the return value is not {@code null}, then the font will be used in the
+ * {@code Fallback List} of that {@link FontFamily}.
+ *
+ * If the return value is {@code null}, then the font will be used in {@code Fallback List}
+ * of all {@link FontFamily}s.
*/
- public @Nullable String getFallback() {
- return mFallback;
+ public @Nullable String getFontFamilyName() {
+ return mFontFamilyName;
}
/**
* Returns the index to be used to access this font when accessing a TTC file.
- * @deprecated Use getIndex instead.
- * @hide
*/
- @Deprecated
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public int getTtcIndex() {
return mIndex;
}
@@ -214,48 +290,46 @@
}
/**
- * A class represents alias between named font families.
+ * Alias provides an alternative name for an existing font family.
*
- * In the system font configuration, an font family can be an alias of another font family with
+ * In the system font configuration, a font family can be an alias of another font family with
* different font weight. For example, "sans-serif-medium" can be a medium weight of
- * sans-serif font family.
+ * "sans-serif" font family. In this example, {@link #getName()} returns "sans-serif-medium" and
+ * {@link #getOriginal()} return "sans-serif". The font family that doesn't have name can not be
+ * an original of the alias.
*/
- public static final class Alias {
- private final @NonNull String mAliasName;
- private final @NonNull String mReferName;
+ public static final class Alias implements Parcelable {
+ private final @NonNull String mName;
+ private final @NonNull String mOriginal;
private final @IntRange(from = 0, to = 1000) int mWeight;
/**
* Construct an alias instance.
*
- * @param aliasName an alias of the named font family.
- * @param referName a referring font family name.
- * @param weight a font weight of the referring font family.
+ * @param name alias for the font family.
+ * @param original original font family name.
+ * @param weight font weight of the original font family.
* @hide Only system server can create this instance and passed via IPC.
*/
- public Alias(@NonNull String aliasName, @NonNull String referName,
+ public Alias(@NonNull String name, @NonNull String original,
@IntRange(from = 0, to = 1000) int weight) {
- mAliasName = aliasName;
- mReferName = referName;
+ mName = name;
+ mOriginal = original;
mWeight = weight;
}
/**
- * An alias of the named font family.
- *
- * @return an alias of the named font family.
+ * Alias for the font family
*/
- public @NonNull String getAliasName() {
- return mAliasName;
+ public @NonNull String getName() {
+ return mName;
}
/**
- * A name of font family referring from {@link #getAliasName()}
- *
- * @return a referring font family name.
+ * The name of the original font family.
*/
- public @NonNull String getReferName() {
- return mReferName;
+ public @NonNull String getOriginal() {
+ return mOriginal;
}
/**
@@ -266,17 +340,47 @@
public @IntRange(from = 0, to = 1000) int getWeight() {
return mWeight;
}
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString8(mName);
+ dest.writeString8(mOriginal);
+ dest.writeInt(mWeight);
+ }
+
+ public static final @NonNull Creator<Alias> CREATOR = new Creator<Alias>() {
+
+ @Override
+ public Alias createFromParcel(Parcel source) {
+ String alias = source.readString8();
+ String referName = source.readString8();
+ int weight = source.readInt();
+ return new Alias(alias, referName, weight);
+ }
+
+ @Override
+ public Alias[] newArray(int size) {
+ return new Alias[size];
+ }
+ };
}
/**
- * A class represents single font family entry in system font configuration.
+ * Represents a font family in the system font configuration.
*
- * <p>
- * A font family is a bundle of fonts for drawing text in various styles.
- * For example, regular style font and bold style font can be bundled into a single font family,
- * then system will select the correct style font from family for drawing.
+ * A {@link FontFamily} is a list of {@link Font}s for drawing text in various styles such as
+ * weight, slant.
+ *
+ * For example, a {@link FontFamily} can include the regular and bold styles of a {@link Font}.
+ *
+ * @see android.graphics.fonts.FontFamily
*/
- public static final class Family {
+ public static final class FontFamily implements Parcelable {
private final @NonNull List<Font> mFonts;
private final @Nullable String mName;
private final @Nullable LocaleList mLocaleList;
@@ -319,7 +423,7 @@
*
* @hide Only system server can create this instance and passed via IPC.
*/
- public Family(@NonNull List<Font> fonts, @Nullable String name,
+ public FontFamily(@NonNull List<Font> fonts, @Nullable String name,
@Nullable LocaleList localeList, @Variant int variant) {
mFonts = fonts;
mName = name;
@@ -328,7 +432,7 @@
}
/**
- * Returns a list of font files in this family.
+ * Returns the list of {@link Font}s in this {@link FontFamily}.
*
* @return a list of font files.
*/
@@ -337,61 +441,77 @@
}
/**
- * Returns a family name if this family defines a new fallback.
+ * Returns the name of the {@link FontFamily}.
*
- * @return non-null if a family name is associated. Otherwise null.
+ * When the name of a {@link FontFamily} is not null, this name is used to create a new
+ * {@code Fallback List}, and that {@code Fallback List}. Fallback List is the
+ * main building block for a {@link android.graphics.Typeface}.
+ *
+ * For example, if the {@link FontFamily} has the name "serif", then the system will create
+ * a “serif” {@code Fallback List} and it can be used by creating a Typeface via
+ * {@code Typeface.create("serif", Typeface.NORMAL);}
+ *
+ * When the name of a {@link FontFamily} is null, it will be appended to all of the
+ * {@code Fallback List}s.
*/
- public @Nullable String getFallbackName() {
+ public @Nullable String getName() {
return mName;
}
/**
- * Returns a locale list if associated.
+ * Returns the locale list if available.
*
- * @return non-null if a locale list is associated. Otherwise null.
+ * The locale list will be used for deciding which font family should be used in fallback
+ * list.
+ *
+ * @return non-null if a locale list is available. Otherwise null.
*/
public @NonNull LocaleList getLocaleList() {
return mLocaleList;
}
/**
- * Returns a text height variant.
- *
- * @return text height variant.
+ * Returns the text height variant.
*/
- public @Variant int getTextHeightVariant() {
- return mVariant;
- }
-
- /**
- * Returns a family variant associated.
- *
- * @return a family variant.
- * @deprecated Use getTextHeightVariant instead.
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public @Variant int getVariant() {
return mVariant;
}
- /**
- * Returns a family name if associated.
- *
- * @return non-null if a family name is associated. Otherwise null.
- * @deprecated Use getFallbackName instead.
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public @Nullable String getName() {
- return mName;
+ @Override
+ public int describeContents() {
+ return 0;
}
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeParcelableList(mFonts, flags);
+ dest.writeString8(mName);
+ dest.writeString8(mLocaleList.toLanguageTags());
+ dest.writeInt(mVariant);
+ }
+
+ public static final @NonNull Creator<FontFamily> CREATOR = new Creator<FontFamily>() {
+
+ @Override
+ public FontFamily createFromParcel(Parcel source) {
+ List<Font> fonts = source.readParcelableList(
+ new ArrayList<>(), Font.class.getClassLoader());
+ String name = source.readString8();
+ String langTags = source.readString8();
+ int variant = source.readInt();
+
+ return new FontFamily(fonts, name, LocaleList.forLanguageTags(langTags), variant);
+ }
+
+ @Override
+ public FontFamily[] newArray(int size) {
+ return new FontFamily[size];
+ }
+ };
+
/**
* Returns the list of fonts included in this family.
- * @deprecated Use getFontFiles instead
+ * @deprecated Use getFontList instead
* @hide
*/
@Deprecated
diff --git a/core/java/android/text/method/TranslationTransformationMethod.java b/core/java/android/text/method/TranslationTransformationMethod.java
new file mode 100644
index 0000000..cf66ac7
--- /dev/null
+++ b/core/java/android/text/method/TranslationTransformationMethod.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.text.method;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.Rect;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.view.translation.TranslationRequest;
+import android.widget.TextView;
+
+import java.util.regex.Pattern;
+
+/**
+ * Transforms source text into an translated string.
+ *
+ * @hide
+ */
+public class TranslationTransformationMethod implements TransformationMethod2 {
+
+ private static final String TAG = "TranslationTransformationMethod";
+ private static final Pattern PATTERN_WHITESPACE = Pattern.compile("\\s+");
+
+ @NonNull
+ private TranslationRequest mTranslationRequest;
+ @Nullable
+ private TransformationMethod mOriginalTranslationMethod;
+ private boolean mAllowLengthChanges;
+
+ /**
+ * @param request the translated result from translation service.
+ * @param method the {@link TextView}'s original {@link TransformationMethod}
+ */
+ public TranslationTransformationMethod(@NonNull TranslationRequest request,
+ @Nullable TransformationMethod method) {
+ mTranslationRequest = request;
+ mOriginalTranslationMethod = method;
+ }
+
+ /**
+ * Returns the {@link TextView}'s original {@link TransformationMethod}. This can be used to
+ * restore to show if the user pauses or finish the ui translation.
+ */
+ public TransformationMethod getOriginalTransformationMethod() {
+ return mOriginalTranslationMethod;
+ }
+
+ @Override
+ public CharSequence getTransformation(CharSequence source, View view) {
+ if (!mAllowLengthChanges) {
+ Log.w(TAG, "Caller did not enable length changes; not transforming to translated text");
+ return source;
+ }
+ CharSequence translatedText = mTranslationRequest.getTranslationText();
+ if (TextUtils.isEmpty(translatedText) || isWhitespace(translatedText.toString())) {
+ return source;
+ } else {
+ // TODO(b/174283799): apply the spans to the text
+ return translatedText;
+ }
+ }
+
+ @Override
+ public void onFocusChanged(View view, CharSequence sourceText,
+ boolean focused, int direction,
+ Rect previouslyFocusedRect) {
+ // do nothing
+ }
+
+ @Override
+ public void setLengthChangesAllowed(boolean allowLengthChanges) {
+ mAllowLengthChanges = allowLengthChanges;
+ }
+
+ private boolean isWhitespace(String text) {
+ return PATTERN_WHITESPACE.matcher(text.substring(0, text.length())).matches();
+ }
+}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 04fe897..5c0e156 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -139,6 +139,7 @@
import android.view.inspector.InspectableProperty;
import android.view.inspector.InspectableProperty.EnumEntry;
import android.view.inspector.InspectableProperty.FlagEntry;
+import android.view.translation.TranslationRequest;
import android.widget.Checkable;
import android.widget.FrameLayout;
import android.widget.ScrollBarDrawable;
@@ -30630,4 +30631,72 @@
mPrivateFlags4 &= ~PFLAG4_DETACHED;
}
}
+
+ /**
+ * Returns a {@link TranslationRequest} to the {@link onStartUiTranslation} which represents
+ * the content to be translated.
+ *
+ * <p>The default implementation does nothing and return null.</p>
+ *
+ * @hide
+ *
+ * @return the {@link TranslationRequest} which contains the information to be translated.
+ */
+ @Nullable
+ //TODO(b/178046780): initial version for demo. Will mark public when the design is reviewed.
+ public TranslationRequest onCreateTranslationRequest() {
+ return null;
+ }
+
+ /**
+ * Called when the user wants to show the original text instead of the translated text.
+ *
+ * @hide
+ *
+ * <p> The default implementation does nothing.
+ */
+ //TODO(b/178046780): initial version for demo. Will mark public when the design is reviewed.
+ public void onPauseUiTranslation() {
+ // no-op
+ }
+
+ /**
+ * User can switch back to show the original text, this method called when the user wants to
+ * re-show the translated text again.
+ *
+ * @hide
+ *
+ * <p> The default implementation does nothing.</p>
+ */
+ //TODO(b/178046780): initial version for demo. Will mark public when the design is reviewed.
+ public void onRestoreUiTranslation() {
+ // no-op
+ }
+
+ /**
+ * Called when the user finish the Ui translation and no longer to show the translated text.
+ *
+ * @hide
+ *
+ * <p> The default implementation does nothing.</p>
+ */
+ //TODO(b/178046780): initial version for demo. Will mark public when the design is reviewed.
+ public void onFinishUiTranslation() {
+ // no-op
+ }
+
+ /**
+ * Called when the request from {@link onStartUiTranslation} is completed by the translation
+ * service so that the translation result can be shown.
+ *
+ * @hide
+ *
+ * <p> The default implementation does nothing.</p>
+ *
+ * @param request the translated information which can be shown in the view.
+ */
+ //TODO(b/178046780): initial version for demo. Will mark public when the design is reviewed.
+ public void onTranslationComplete(@NonNull TranslationRequest request) {
+ // no-op
+ }
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index b866025..8cfbca8 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -129,6 +129,7 @@
import android.text.method.TimeKeyListener;
import android.text.method.TransformationMethod;
import android.text.method.TransformationMethod2;
+import android.text.method.TranslationTransformationMethod;
import android.text.method.WordIterator;
import android.text.style.CharacterStyle;
import android.text.style.ClickableSpan;
@@ -193,6 +194,7 @@
import android.view.textclassifier.TextLinks;
import android.view.textservice.SpellCheckerSubtype;
import android.view.textservice.TextServicesManager;
+import android.view.translation.TranslationRequest;
import android.widget.RemoteViews.RemoteView;
import com.android.internal.annotations.VisibleForTesting;
@@ -732,6 +734,7 @@
private MovementMethod mMovement;
private TransformationMethod mTransformation;
+ private TranslationTransformationMethod mTranslationTransformation;
@UnsupportedAppUsage
private boolean mAllowTransformationLengthChange;
@UnsupportedAppUsage
@@ -13814,4 +13817,121 @@
Log.d(LOG_TAG, location + ": " + String.format(msgFormat, msgArgs));
}
}
+
+ /**
+ * Provides a {@link TranslationRequest} that represents the content to be translated via
+ * translation service.
+ *
+ * <p>NOTE: When overriding the method, it should not translate the password. We also suggest
+ * that not translating the text is selectable or editable. We use the transformation method to
+ * implement showing the translated text. The TextView does not support the transformation
+ * method text length change. If the text is selectable or editable, it will crash while
+ * selecting the text. To support it, it needs broader changes to text APIs, we only allow to
+ * translate non selectable and editable text now.
+ *
+ * @hide
+ */
+ @Nullable
+ @Override
+ public TranslationRequest onCreateTranslationRequest() {
+ if (mText == null || mText.length() == 0) {
+ return null;
+ }
+ // Not translate password, editable text and not important for translation
+ // TODO(b/177214256): support selectable text translation. It needs to broader changes to
+ // text selection apis, not support in S.
+ boolean isPassword = isAnyPasswordInputType() || hasPasswordTransformationMethod();
+ if (isTextEditable() || isPassword || isTextSelectable()) {
+ return null;
+ }
+ // TODO(b/176488462): apply the view's important for translation property
+ // TODO(b/174283799): remove the spans from the mText and save the spans informatopn
+ TranslationRequest request =
+ new TranslationRequest.Builder()
+ .setAutofillId(getAutofillId())
+ .setTranslationText(mText)
+ .build();
+ return request;
+ }
+
+ /**
+ * Provides the implementation that pauses the ongoing Ui translation, it will show the original
+ * text instead of the translated text and restore the original transformation method.
+ *
+ * <p>NOTE: If this method is overridden, other translation related methods such as
+ * {@link onRestoreUiTranslation}, {@link onFinishUiTranslation}, {@link onTranslationComplete}
+ * should also be overridden.
+ *
+ * @hide
+ */
+ @Override
+ public void onPauseUiTranslation() {
+ // Restore to original text content.
+ if (mTranslationTransformation != null) {
+ setTransformationMethod(mTranslationTransformation.getOriginalTransformationMethod());
+ }
+ }
+
+ /**
+ * Provides the implementation that restoes the paused Ui translation, it will show the
+ * translated text again if the text had been translated. This method will replace the current
+ * tansformation method with {@link TranslationTransformationMethod}.
+ *
+ * <p>NOTE: If this method is overridden, other translation related methods such as
+ * {@link onPauseUiTranslation}, {@link onFinishUiTranslation}, {@link onTranslationComplete}
+ * should also be overridden.
+ *
+ * @hide
+ */
+ @Override
+ public void onRestoreUiTranslation() {
+ if (mTranslationTransformation != null) {
+ setTransformationMethod(mTranslationTransformation);
+ } else {
+ Log.w(LOG_TAG, "onResumeTranslatedText(): no translated text.");
+ }
+ }
+
+ /**
+ * Provides the implementation that finishes the current Ui translation and it's no longer to
+ * show the translated text. This method restores the original transformation method and resets
+ * the saved {@link TranslationTransformationMethod}.
+ *
+ * <p>NOTE: If this method is overridden, other translation related methods such as
+ * {@link onPauseUiTranslation}, {@link onRestoreUiTranslation}, {@link onTranslationComplete}
+ * should also be overridden.
+ *
+ * @hide
+ */
+ @Override
+ public void onFinishUiTranslation() {
+ // Restore to original text content and clear TranslationTransformation
+ if (mTranslationTransformation != null) {
+ setTransformationMethod(mTranslationTransformation.getOriginalTransformationMethod());
+ mTranslationTransformation = null;
+ }
+ }
+
+ /**
+ * Default {@link TextView} implementation after the translation request is done by the
+ * translation service, it's ok to show the translated text. This method will save the original
+ * transformation method and replace the current transformation method with
+ * {@link TranslationTransformationMethod}.
+ *
+ * <p>NOTE: If this method is overridden, other translation related methods such as
+ * {@link onPauseUiTranslation}, {@link onRestoreUiTranslation}, {@link onFinishUiTranslation}
+ * should also be overridden.
+ *
+ * @hide
+ */
+ @Override
+ public void onTranslationComplete(@NonNull TranslationRequest data) {
+ // Show the translated text.
+ TransformationMethod originalTranslationMethod = mTranslationTransformation != null
+ ? mTranslationTransformation.getOriginalTransformationMethod() : mTransformation;
+ mTranslationTransformation =
+ new TranslationTransformationMethod(data, originalTranslationMethod);
+ // TODO(b/178353965): well-handle setTransformationMethod.
+ setTransformationMethod(mTranslationTransformation);
+ }
}
diff --git a/core/java/com/android/internal/graphics/fonts/IFontManager.aidl b/core/java/com/android/internal/graphics/fonts/IFontManager.aidl
new file mode 100644
index 0000000..a11c7ef
--- /dev/null
+++ b/core/java/com/android/internal/graphics/fonts/IFontManager.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 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.internal.graphics.fonts;
+
+import android.text.FontConfig;
+import android.graphics.fonts.SystemFontState;
+
+/**
+ * System private interface for talking with
+ * {@link com.android.server.graphics.fonts.FontManagerService}.
+ * @hide
+ */
+interface IFontManager {
+ FontConfig getFontConfig();
+}
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 4b343af..fda87be 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -103,7 +103,7 @@
*/
public static final int PROFILE_FROM_SHELL = 1 << 15;
- /**
+ /*
* Enable using the ART app image startup cache
*/
public static final int USE_APP_IMAGE_STARTUP_CACHE = 1 << 16;
@@ -116,6 +116,13 @@
*/
public static final int DEBUG_IGNORE_APP_SIGNAL_HANDLER = 1 << 17;
+ /**
+ * Disable runtime access to {@link android.annotation.TestApi} annotated members.
+ *
+ * <p>This only takes effect if Hidden API access restrictions are enabled as well.
+ */
+ public static final int DISABLE_TEST_API_ENFORCEMENT_POLICY = 1 << 18;
+
public static final int MEMORY_TAG_LEVEL_MASK = (1 << 19) | (1 << 20);
/**
* Enable pointer tagging in this process.
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 60157bd..43a14dc 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -203,8 +203,7 @@
<string name="sensor_notification_service" msgid="7474531979178682676">"የዳሳሽ ማሳወቂያ አገልግሎት"</string>
<string name="twilight_service" msgid="8964898045693187224">"የውጋገን አገልግሎት"</string>
<string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"የሰዓት ሰቅ አንባቢ (ግንኙነት የለም)"</string>
- <!-- no translation found for gnss_time_update_service (9039489496037616095) -->
- <skip />
+ <string name="gnss_time_update_service" msgid="9039489496037616095">"የGNSS ጊዜ ዝመኔ አገልግሎት"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"የእርስዎ መሣሪያ ይደመሰሳል"</string>
<string name="factory_reset_message" msgid="2657049595153992213">"የአስተዳዳሪ መተግበሪያ ስራ ላይ ሊውል አይችልም። የእርስዎን መሣሪያ አሁን ይደመሰሳል።\n\nጥያቄዎች ካለዎት የድርጅትዎን አስተዳዳሪ ያነጋግሩ።"</string>
<string name="printing_disabled_by" msgid="3517499806528864633">"ማተም በ<xliff:g id="OWNER_APP">%s</xliff:g> ተሰናክሏል።"</string>
@@ -2205,12 +2204,8 @@
<string name="window_magnification_prompt_content" msgid="4166711383253283838">"አሁን የተወሰነ ወይም ሁሉንም ማያ ገጽዎን ማጉላት ይችላሉ"</string>
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"በቅንብሮች ውስጥ ያብሩ"</string>
<string name="dismiss_action" msgid="1728820550388704784">"አሰናብት"</string>
- <!-- no translation found for sensor_privacy_start_use_mic_notification_content (8063355861118105607) -->
- <skip />
- <!-- no translation found for sensor_privacy_start_use_camera_notification_content (4738005643315863736) -->
- <skip />
- <!-- no translation found for sensor_privacy_start_use_dialog_turn_on_button (7921147002346108119) -->
- <skip />
- <!-- no translation found for sensor_privacy_notification_channel_label (936036783155261349) -->
- <skip />
+ <string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"ለመቀጠል፣ <b><xliff:g id="APP">%s</xliff:g></b> ወደ መሳሪያዎ ማይክሮፎን መድረስ ይፈልጋል።"</string>
+ <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"ለመቀጠል፣ <b><xliff:g id="APP">%s</xliff:g></b> የመሣሪያዎን ካሜራ መድረስ ይፈልጋል።"</string>
+ <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"አብራ"</string>
+ <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"ዳሳሽ ግላዊነት"</string>
</resources>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index c413c33..b6eb959 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -203,8 +203,7 @@
<string name="sensor_notification_service" msgid="7474531979178682676">"ছেন্সৰ জাননী সেৱা"</string>
<string name="twilight_service" msgid="8964898045693187224">"Twilight সেৱা"</string>
<string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"সময় মণ্ডল চিনাক্তকাৰী (সংযোগ নাই)"</string>
- <!-- no translation found for gnss_time_update_service (9039489496037616095) -->
- <skip />
+ <string name="gnss_time_update_service" msgid="9039489496037616095">"GNSS সময় আপডে’ট প্ৰদান কৰা সেৱা"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"আপোনাৰ ডিভাইচৰ ডেটা মচা হ\'ব"</string>
<string name="factory_reset_message" msgid="2657049595153992213">"এই প্ৰশাসক এপটো ব্যৱহাৰ কৰিব নোৱাৰি। এতিয়া আপোনাৰ ডিভাইচটোৰ ডেটা মচা হ\'ব।\n\nআপোনাৰ কিবা প্ৰশ্ন থাকিলে আপোনাৰ প্ৰতিষ্ঠানৰ প্ৰশাসকৰ সৈতে যোগাযোগ কৰক।"</string>
<string name="printing_disabled_by" msgid="3517499806528864633">"প্ৰিণ্ট কৰা কাৰ্য <xliff:g id="OWNER_APP">%s</xliff:g>এ অক্ষম কৰি ৰাখিছে।"</string>
@@ -2205,12 +2204,8 @@
<string name="window_magnification_prompt_content" msgid="4166711383253283838">"আপুনি সকলো অথবা কেইখনমান স্ক্ৰীন বিবৰ্ধন কৰিব পাৰে"</string>
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ছেটিঙত অন কৰক"</string>
<string name="dismiss_action" msgid="1728820550388704784">"অগ্ৰাহ্য কৰক"</string>
- <!-- no translation found for sensor_privacy_start_use_mic_notification_content (8063355861118105607) -->
- <skip />
- <!-- no translation found for sensor_privacy_start_use_camera_notification_content (4738005643315863736) -->
- <skip />
- <!-- no translation found for sensor_privacy_start_use_dialog_turn_on_button (7921147002346108119) -->
- <skip />
- <!-- no translation found for sensor_privacy_notification_channel_label (936036783155261349) -->
- <skip />
+ <string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"অব্যাহত ৰাখিবলৈ <b><xliff:g id="APP">%s</xliff:g></b>এ আপোনাৰ ডিভাইচৰ মাইক্ৰ’ফ’ন এক্সেছ কৰাৰ আৱশ্যক।"</string>
+ <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"অব্যাহত ৰাখিবলৈ <b><xliff:g id="APP">%s</xliff:g></b>এ আপোনাৰ ডিভাইচৰ কেমেৰা এক্সেছ কৰাৰ আৱশ্যক।"</string>
+ <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"অন কৰক"</string>
+ <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"ছেন্সৰ সম্পৰ্কীয় গোপনীয়তাৰ নীতি"</string>
</resources>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 51ca3da..6c54eb1 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -205,8 +205,7 @@
<string name="sensor_notification_service" msgid="7474531979178682676">"Usluga obavještavanja putem senzora"</string>
<string name="twilight_service" msgid="8964898045693187224">"Usluga Twilight"</string>
<string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detektor vremenske zone (nije povezan)"</string>
- <!-- no translation found for gnss_time_update_service (9039489496037616095) -->
- <skip />
+ <string name="gnss_time_update_service" msgid="9039489496037616095">"GNSS usluga za ažuriranje vremena"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Uređaj će biti izbrisan"</string>
<string name="factory_reset_message" msgid="2657049595153992213">"Nije moguće koristiti aplikaciju administratora. Potpuno će se izbrisati podaci na vašem uređaju.\n\nAko imate pitanja, obratite se administratoru svoje organizacije."</string>
<string name="printing_disabled_by" msgid="3517499806528864633">"Štampanje je onemogućila aplikacija <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -2239,12 +2238,8 @@
<string name="window_magnification_prompt_content" msgid="4166711383253283838">"Sada možete uvećati dio ekrana ili cijeli ekran"</string>
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Uključite u Postavkama"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Odbaci"</string>
- <!-- no translation found for sensor_privacy_start_use_mic_notification_content (8063355861118105607) -->
- <skip />
- <!-- no translation found for sensor_privacy_start_use_camera_notification_content (4738005643315863736) -->
- <skip />
- <!-- no translation found for sensor_privacy_start_use_dialog_turn_on_button (7921147002346108119) -->
- <skip />
- <!-- no translation found for sensor_privacy_notification_channel_label (936036783155261349) -->
- <skip />
+ <string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Da nastavite, aplikaciji <b><xliff:g id="APP">%s</xliff:g></b> je potreban pristup mikrofonu vašeg uređaja."</string>
+ <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Da nastavite, aplikaciji <b><xliff:g id="APP">%s</xliff:g></b> je potreban pristup kameri vašeg uređaja."</string>
+ <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Uključi"</string>
+ <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Privatnost senzora"</string>
</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 084250e..98d715b 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -203,8 +203,7 @@
<string name="sensor_notification_service" msgid="7474531979178682676">"سرویس اعلان حسگر"</string>
<string name="twilight_service" msgid="8964898045693187224">"سرویس Twilight"</string>
<string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"شناساگر منطقه زمانی (بدون اتصال)"</string>
- <!-- no translation found for gnss_time_update_service (9039489496037616095) -->
- <skip />
+ <string name="gnss_time_update_service" msgid="9039489496037616095">"سرویس بهروزرسانی زمان GNSS"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"دستگاهتان پاک خواهد شد"</string>
<string name="factory_reset_message" msgid="2657049595153992213">"برنامه سرپرست سیستم را نمیتوان استفاده کرد. دستگاه شما در این لحظه پاک میشود.\n\nاگر سؤالی دارید، با سرپرست سیستم سازمانتان تماس بگیرید."</string>
<string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> چاپ کردن را غیرفعال کرده است."</string>
@@ -2205,12 +2204,8 @@
<string name="window_magnification_prompt_content" msgid="4166711383253283838">"اکنون میتوانید بخشی از صفحه یا کل آن را درشت کنید"</string>
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"روشن کردن در «تنظیمات»"</string>
<string name="dismiss_action" msgid="1728820550388704784">"رد شدن"</string>
- <!-- no translation found for sensor_privacy_start_use_mic_notification_content (8063355861118105607) -->
- <skip />
- <!-- no translation found for sensor_privacy_start_use_camera_notification_content (4738005643315863736) -->
- <skip />
- <!-- no translation found for sensor_privacy_start_use_dialog_turn_on_button (7921147002346108119) -->
- <skip />
- <!-- no translation found for sensor_privacy_notification_channel_label (936036783155261349) -->
- <skip />
+ <string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"برای ادامه دادن، <b><xliff:g id="APP">%s</xliff:g></b> باید به میکروفون دستگاه دسترسی داشته باشد."</string>
+ <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"برای ادامه دادن، <b><xliff:g id="APP">%s</xliff:g></b> باید به دوربین دستگاه دسترسی داشته باشد."</string>
+ <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"روشن کردن"</string>
+ <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"حریمخصوصی حسگر"</string>
</resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 58d47c4..e34bf8b 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -203,8 +203,7 @@
<string name="sensor_notification_service" msgid="7474531979178682676">"Service de notification de capteur"</string>
<string name="twilight_service" msgid="8964898045693187224">"Service de crépuscule"</string>
<string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Détecteur de fuseau horaire (aucune connectivité)"</string>
- <!-- no translation found for gnss_time_update_service (9039489496037616095) -->
- <skip />
+ <string name="gnss_time_update_service" msgid="9039489496037616095">"Service d\'actualisation de l\'heure GNSS"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"Le contenu de votre appareil sera effacé"</string>
<string name="factory_reset_message" msgid="2657049595153992213">"Impossible d\'utiliser l\'application d\'administration. Les données de votre appareil vont maintenant être effacées.\n\nSi vous avez des questions, communiquez avec l\'administrateur de votre organisation."</string>
<string name="printing_disabled_by" msgid="3517499806528864633">"Impression désactivée par <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
@@ -2205,12 +2204,8 @@
<string name="window_magnification_prompt_content" msgid="4166711383253283838">"Vous pouvez agrandir une partie ou la totalité de votre écran"</string>
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activer dans les paramètres"</string>
<string name="dismiss_action" msgid="1728820550388704784">"Fermer"</string>
- <!-- no translation found for sensor_privacy_start_use_mic_notification_content (8063355861118105607) -->
- <skip />
- <!-- no translation found for sensor_privacy_start_use_camera_notification_content (4738005643315863736) -->
- <skip />
- <!-- no translation found for sensor_privacy_start_use_dialog_turn_on_button (7921147002346108119) -->
- <skip />
- <!-- no translation found for sensor_privacy_notification_channel_label (936036783155261349) -->
- <skip />
+ <string name="sensor_privacy_start_use_mic_notification_content" msgid="8063355861118105607">"Pour continuer, vous devez accorder l\'accès au microphone de votre appareil à l\'application <b><xliff:g id="APP">%s</xliff:g></b>."</string>
+ <string name="sensor_privacy_start_use_camera_notification_content" msgid="4738005643315863736">"Pour continuer, vous devez accorder l\'accès à l\'appareil photo de votre appareil à l\'application <b><xliff:g id="APP">%s</xliff:g></b>."</string>
+ <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7921147002346108119">"Activer"</string>
+ <string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Confidentialité des capteurs"</string>
</resources>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index fac6dbc..b309e4a 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -57,7 +57,7 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"आगमन कलर ID"</string>
- <string name="ClirMmi" msgid="6752346475055446417">"बहिर्गमन कल गर्ने व्यक्तिको ID लुकाउनुहोस्"</string>
+ <string name="ClirMmi" msgid="6752346475055446417">"आफ्नो नाम र टेलिफोन नम्बर लुकाएर टेलिफोन गर्नुहोस्"</string>
<string name="ColpMmi" msgid="4736462893284419302">"लाइन ID जोडियो"</string>
<string name="ColrMmi" msgid="5889782479745764278">"जोडिएको लाइन ID प्रतिबन्ध"</string>
<string name="CfMmi" msgid="8390012691099787178">"कल अगाडि बढाउँदै"</string>
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index ff38117..c8ff95d 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -100,10 +100,10 @@
@NonNull FontCustomizationParser.Result customization,
@Nullable Map<String, File> updatableFontMap)
throws XmlPullParserException, IOException {
- List<FontConfig.Family> families = new ArrayList<>();
+ List<FontConfig.FontFamily> families = new ArrayList<>();
List<FontConfig.Alias> aliases = new ArrayList<>(customization.getAdditionalAliases());
- Map<String, FontConfig.Family> oemNamedFamilies =
+ Map<String, FontConfig.FontFamily> oemNamedFamilies =
customization.getAdditionalNamedFamilies();
parser.require(XmlPullParser.START_TAG, null, "familyset");
@@ -111,8 +111,8 @@
if (parser.getEventType() != XmlPullParser.START_TAG) continue;
String tag = parser.getName();
if (tag.equals("family")) {
- FontConfig.Family family = readFamily(parser, fontDir, updatableFontMap);
- String name = family.getFallbackName();
+ FontConfig.FontFamily family = readFamily(parser, fontDir, updatableFontMap);
+ String name = family.getName();
if (name == null || !oemNamedFamilies.containsKey(name)) {
// The OEM customization overrides system named family. Skip if OEM
// customization XML defines the same named family.
@@ -132,7 +132,7 @@
/**
* Read family tag in fonts.xml or oem_customization.xml
*/
- public static FontConfig.Family readFamily(XmlPullParser parser, String fontDir,
+ public static FontConfig.FontFamily readFamily(XmlPullParser parser, String fontDir,
@Nullable Map<String, File> updatableFontMap)
throws XmlPullParserException, IOException {
final String name = parser.getAttributeValue(null, "name");
@@ -148,15 +148,15 @@
skip(parser);
}
}
- int intVariant = FontConfig.Family.VARIANT_DEFAULT;
+ int intVariant = FontConfig.FontFamily.VARIANT_DEFAULT;
if (variant != null) {
if (variant.equals("compact")) {
- intVariant = FontConfig.Family.VARIANT_COMPACT;
+ intVariant = FontConfig.FontFamily.VARIANT_COMPACT;
} else if (variant.equals("elegant")) {
- intVariant = FontConfig.Family.VARIANT_ELEGANT;
+ intVariant = FontConfig.FontFamily.VARIANT_ELEGANT;
}
}
- return new FontConfig.Family(fonts, name, LocaleList.forLanguageTags(lang), intVariant);
+ return new FontConfig.FontFamily(fonts, name, LocaleList.forLanguageTags(lang), intVariant);
}
/** Matches leading and trailing XML whitespace. */
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index f1866cd..a0568bf 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -1151,10 +1151,10 @@
for (int i = 0; i < aliases.size(); ++i) {
final FontConfig.Alias alias = aliases.get(i);
- if (outSystemFontMap.containsKey(alias.getAliasName())) {
+ if (outSystemFontMap.containsKey(alias.getName())) {
continue; // If alias and named family are conflict, use named family.
}
- final Typeface base = outSystemFontMap.get(alias.getReferName());
+ final Typeface base = outSystemFontMap.get(alias.getOriginal());
if (base == null) {
// The missing target is a valid thing, some configuration don't have font files,
// e.g. wear devices. Just skip this alias.
@@ -1163,7 +1163,7 @@
final int weight = alias.getWeight();
final Typeface newFace = weight == 400 ? base :
new Typeface(nativeCreateWeightAlias(base.native_instance, weight));
- outSystemFontMap.put(alias.getAliasName(), newFace);
+ outSystemFontMap.put(alias.getName(), newFace);
}
}
diff --git a/graphics/java/android/graphics/fonts/FontCustomizationParser.java b/graphics/java/android/graphics/fonts/FontCustomizationParser.java
index 1ad6fbe..42033ba 100644
--- a/graphics/java/android/graphics/fonts/FontCustomizationParser.java
+++ b/graphics/java/android/graphics/fonts/FontCustomizationParser.java
@@ -17,7 +17,7 @@
package android.graphics.fonts;
import static android.text.FontConfig.Alias;
-import static android.text.FontConfig.Family;
+import static android.text.FontConfig.FontFamily;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -46,7 +46,7 @@
* Represents a customization XML
*/
public static class Result {
- private final Map<String, Family> mAdditionalNamedFamilies;
+ private final Map<String, FontFamily> mAdditionalNamedFamilies;
private final List<Alias> mAdditionalAliases;
public Result() {
@@ -54,13 +54,13 @@
mAdditionalAliases = Collections.emptyList();
}
- public Result(Map<String, Family> additionalNamedFamilies,
+ public Result(Map<String, FontFamily> additionalNamedFamilies,
List<Alias> additionalAliases) {
mAdditionalNamedFamilies = additionalNamedFamilies;
mAdditionalAliases = additionalAliases;
}
- public Map<String, Family> getAdditionalNamedFamilies() {
+ public Map<String, FontFamily> getAdditionalNamedFamilies() {
return mAdditionalNamedFamilies;
}
@@ -85,11 +85,11 @@
return readFamilies(parser, fontDir, updatableFontMap);
}
- private static Map<String, Family> validateAndTransformToMap(List<Family> families) {
- HashMap<String, Family> namedFamily = new HashMap<>();
+ private static Map<String, FontFamily> validateAndTransformToMap(List<FontFamily> families) {
+ HashMap<String, FontFamily> namedFamily = new HashMap<>();
for (int i = 0; i < families.size(); ++i) {
- final Family family = families.get(i);
- final String name = family.getFallbackName();
+ final FontFamily family = families.get(i);
+ final String name = family.getName();
if (name == null) {
throw new IllegalArgumentException("new-named-family requires name attribute");
}
@@ -106,7 +106,7 @@
@NonNull String fontDir,
@Nullable Map<String, File> updatableFontMap
) throws XmlPullParserException, IOException {
- List<Family> families = new ArrayList<>();
+ List<FontFamily> families = new ArrayList<>();
List<Alias> aliases = new ArrayList<>();
parser.require(XmlPullParser.START_TAG, null, "fonts-modification");
while (parser.next() != XmlPullParser.END_TAG) {
@@ -126,7 +126,7 @@
private static void readFamily(
@NonNull XmlPullParser parser,
@NonNull String fontDir,
- @NonNull List<Family> out,
+ @NonNull List<FontFamily> out,
@Nullable Map<String, File> updatableFontMap)
throws XmlPullParserException, IOException {
final String customizationType = parser.getAttributeValue(null, "customizationType");
diff --git a/graphics/java/android/graphics/fonts/FontFamily.java b/graphics/java/android/graphics/fonts/FontFamily.java
index 2f0c26f..c29c194 100644
--- a/graphics/java/android/graphics/fonts/FontFamily.java
+++ b/graphics/java/android/graphics/fonts/FontFamily.java
@@ -109,7 +109,7 @@
* @return a font family
*/
public @NonNull FontFamily build() {
- return build("", FontConfig.Family.VARIANT_DEFAULT, true /* isCustomFallback */);
+ return build("", FontConfig.FontFamily.VARIANT_DEFAULT, true /* isCustomFallback */);
}
/** @hide */
diff --git a/graphics/java/android/graphics/fonts/SystemFonts.java b/graphics/java/android/graphics/fonts/SystemFonts.java
index 6aa50db..a41215f 100644
--- a/graphics/java/android/graphics/fonts/SystemFonts.java
+++ b/graphics/java/android/graphics/fonts/SystemFonts.java
@@ -117,12 +117,12 @@
}
}
- private static void pushFamilyToFallback(@NonNull FontConfig.Family xmlFamily,
+ private static void pushFamilyToFallback(@NonNull FontConfig.FontFamily xmlFamily,
@NonNull ArrayMap<String, ArrayList<FontFamily>> fallbackMap,
@NonNull Map<String, ByteBuffer> cache) {
final String languageTags = xmlFamily.getLocaleList().toLanguageTags();
- final int variant = xmlFamily.getTextHeightVariant();
+ final int variant = xmlFamily.getVariant();
final ArrayList<FontConfig.Font> defaultFonts = new ArrayList<>();
final ArrayMap<String, ArrayList<FontConfig.Font>> specificFallbackFonts =
@@ -130,7 +130,7 @@
// Collect default fallback and specific fallback fonts.
for (final FontConfig.Font font : xmlFamily.getFonts()) {
- final String fallbackName = font.getFallback();
+ final String fallbackName = font.getFontFamilyName();
if (fallbackName == null) {
defaultFonts.add(font);
} else {
@@ -144,14 +144,14 @@
}
final FontFamily defaultFamily = defaultFonts.isEmpty() ? null : createFontFamily(
- xmlFamily.getFallbackName(), defaultFonts, languageTags, variant, cache);
+ xmlFamily.getName(), defaultFonts, languageTags, variant, cache);
// Insert family into fallback map.
for (int i = 0; i < fallbackMap.size(); i++) {
String name = fallbackMap.keyAt(i);
final ArrayList<FontConfig.Font> fallback = specificFallbackFonts.get(name);
if (fallback == null) {
- String familyName = xmlFamily.getFallbackName();
+ String familyName = xmlFamily.getName();
if (defaultFamily != null
// do not add myself to the fallback chain.
&& (familyName == null || !familyName.equals(name))) {
@@ -159,7 +159,7 @@
}
} else {
final FontFamily family = createFontFamily(
- xmlFamily.getFallbackName(), fallback, languageTags, variant, cache);
+ xmlFamily.getName(), fallback, languageTags, variant, cache);
if (family != null) {
fallbackMap.valueAt(i).add(family);
} else if (defaultFamily != null) {
@@ -174,7 +174,7 @@
private static @Nullable FontFamily createFontFamily(@NonNull String familyName,
@NonNull List<FontConfig.Font> fonts,
@NonNull String languageTags,
- @FontConfig.Family.Variant int variant,
+ @FontConfig.FontFamily.Variant int variant,
@NonNull Map<String, ByteBuffer> cache) {
if (fonts.size() == 0) {
return null;
@@ -183,7 +183,7 @@
FontFamily.Builder b = null;
for (int i = 0; i < fonts.size(); i++) {
final FontConfig.Font fontConfig = fonts.get(i);
- final String fullPath = fontConfig.getFilePath().getAbsolutePath();
+ final String fullPath = fontConfig.getFile().getAbsolutePath();
ByteBuffer buffer = cache.get(fullPath);
if (buffer == null) {
if (cache.containsKey(fullPath)) {
@@ -201,7 +201,7 @@
font = new Font.Builder(buffer, new File(fullPath), languageTags)
.setWeight(fontConfig.getStyle().getWeight())
.setSlant(fontConfig.getStyle().getSlant())
- .setTtcIndex(fontConfig.getIndex())
+ .setTtcIndex(fontConfig.getTtcIndex())
.setFontVariationSettings(fontConfig.getFontVariationSettings())
.build();
} catch (IOException e) {
@@ -217,13 +217,13 @@
return b == null ? null : b.build(languageTags, variant, false /* isCustomFallback */);
}
- private static void appendNamedFamily(@NonNull FontConfig.Family xmlFamily,
+ private static void appendNamedFamily(@NonNull FontConfig.FontFamily xmlFamily,
@NonNull HashMap<String, ByteBuffer> bufferCache,
@NonNull ArrayMap<String, ArrayList<FontFamily>> fallbackListMap) {
- final String familyName = xmlFamily.getFallbackName();
+ final String familyName = xmlFamily.getName();
final FontFamily family = createFontFamily(
familyName, xmlFamily.getFontList(),
- xmlFamily.getLocaleList().toLanguageTags(), xmlFamily.getTextHeightVariant(),
+ xmlFamily.getLocaleList().toLanguageTags(), xmlFamily.getVariant(),
bufferCache);
if (family == null) {
return;
@@ -281,12 +281,12 @@
public static Map<String, FontFamily[]> buildSystemFallback(FontConfig fontConfig) {
final Map<String, FontFamily[]> fallbackMap = new HashMap<>();
final HashMap<String, ByteBuffer> bufferCache = new HashMap<>();
- final List<FontConfig.Family> xmlFamilies = fontConfig.getFontFamilies();
+ final List<FontConfig.FontFamily> xmlFamilies = fontConfig.getFontFamilies();
final ArrayMap<String, ArrayList<FontFamily>> fallbackListMap = new ArrayMap<>();
// First traverse families which have a 'name' attribute to create fallback map.
- for (final FontConfig.Family xmlFamily : xmlFamilies) {
- final String familyName = xmlFamily.getFallbackName();
+ for (final FontConfig.FontFamily xmlFamily : xmlFamilies) {
+ final String familyName = xmlFamily.getName();
if (familyName == null) {
continue;
}
@@ -295,10 +295,10 @@
// Then, add fallback fonts to the each fallback map.
for (int i = 0; i < xmlFamilies.size(); i++) {
- final FontConfig.Family xmlFamily = xmlFamilies.get(i);
+ final FontConfig.FontFamily xmlFamily = xmlFamilies.get(i);
// The first family (usually the sans-serif family) is always placed immediately
// after the primary family in the fallback.
- if (i == 0 || xmlFamily.getFallbackName() == null) {
+ if (i == 0 || xmlFamily.getName() == null) {
pushFamilyToFallback(xmlFamily, fallbackListMap, bufferCache);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
index dd43139..1df2a4a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
@@ -157,7 +157,6 @@
});
options.setLaunchCookie(launchCookie);
options.setLaunchWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
- options.setTaskAlwaysOnTop(true);
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index 67f4cd2..29458ef 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -140,6 +140,7 @@
+ getBubbleKey());
}
try {
+ options.setTaskAlwaysOnTop(true);
if (!mIsOverflow && mBubble.hasMetadataShortcutId()) {
options.setApplyActivityFlagsForBubbles(true);
mTaskView.startShortcutActivity(mBubble.getShortcutInfo(),
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java
index eb03ab0..4e582c2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java
@@ -129,7 +129,6 @@
verify(mOrganizer).setPendingLaunchCookieListener(any(), eq(mTaskView));
assertThat(options.getLaunchWindowingMode()).isEqualTo(WINDOWING_MODE_MULTI_WINDOW);
- assertThat(options.getTaskAlwaysOnTop()).isTrue();
}
@Test
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index 2a3704d..d40de76 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -28,7 +28,7 @@
import java.util.TreeSet;
/**
- * Class to provide information about the audio devices.
+ * Provides information about an audio device.
*/
public final class AudioDeviceInfo {
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 7192c07..4d835b2 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -23,7 +23,6 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.app.ActivityManager;
import android.content.Context;
import android.hardware.tv.tuner.V1_0.Constants;
import android.media.tv.TvInputService;
@@ -54,6 +53,7 @@
import android.os.HandlerExecutor;
import android.os.Looper;
import android.os.Message;
+import android.os.Process;
import android.util.Log;
import com.android.internal.util.FrameworkStatsLog;
@@ -352,7 +352,7 @@
profile, new HandlerExecutor(mHandler), mResourceListener, clientId);
mClientId = clientId[0];
- mUserId = ActivityManager.getCurrentUser();
+ mUserId = Process.myUid();
}
/**
diff --git a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
index 597278b..d70b8c2 100644
--- a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
+++ b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
@@ -20,13 +20,13 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.app.ActivityManager;
import android.hardware.tv.tuner.V1_0.Constants;
import android.media.tv.tuner.Tuner;
import android.media.tv.tuner.Tuner.Result;
import android.media.tv.tuner.TunerUtils;
import android.media.tv.tuner.filter.Filter;
import android.os.ParcelFileDescriptor;
+import android.os.Process;
import android.util.Log;
import com.android.internal.util.FrameworkStatsLog;
@@ -98,7 +98,7 @@
private native long nativeRead(byte[] bytes, long offset, long size);
private DvrPlayback() {
- mUserId = ActivityManager.getCurrentUser();
+ mUserId = Process.myUid();
mSegmentId = (sInstantId & 0x0000ffff) << 16;
sInstantId++;
}
diff --git a/media/java/android/media/tv/tuner/dvr/DvrRecorder.java b/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
index 2f2cd96..0f9f2e7 100644
--- a/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
+++ b/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
@@ -19,12 +19,12 @@
import android.annotation.BytesLong;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.app.ActivityManager;
import android.media.tv.tuner.Tuner;
import android.media.tv.tuner.Tuner.Result;
import android.media.tv.tuner.TunerUtils;
import android.media.tv.tuner.filter.Filter;
import android.os.ParcelFileDescriptor;
+import android.os.Process;
import android.util.Log;
import com.android.internal.util.FrameworkStatsLog;
@@ -61,7 +61,7 @@
private native long nativeWrite(byte[] bytes, long offset, long size);
private DvrRecorder() {
- mUserId = ActivityManager.getCurrentUser();
+ mUserId = Process.myUid();
mSegmentId = (sInstantId & 0x0000ffff) << 16;
sInstantId++;
}
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index b9fccf9..d1954a6 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -416,10 +416,8 @@
<string name="quick_settings_screen_record_label" msgid="1594046461509776676">"የማያ ገጽ ቀረጻ"</string>
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ጀምር"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"አቁም"</string>
- <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) -->
- <skip />
- <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) -->
- <skip />
+ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"ለመቀጠል፣ <b><xliff:g id="APP">%s</xliff:g></b> ወደ መሳሪያዎ ማይክሮፎን መድረስ ይፈልጋል።"</string>
+ <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"ለመቀጠል፣ <b><xliff:g id="APP">%s</xliff:g></b> የመሣሪያዎን ካሜራ መድረስ ይፈልጋል።"</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"መሣሪያ"</string>
<string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"መተግበሪያዎችን ለመቀየር ወደ ላይ ያንሸራትቱ"</string>
<string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"መተግበሪያዎችን በፍጥነት ለመቀየር ወደ ቀኝ ይጎትቱ"</string>
@@ -442,8 +440,7 @@
<string name="notification_tap_again" msgid="4477318164947497249">"ለመክፈት ዳግም መታ ያድርጉ"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"ለመክፈት በጣት ወደ ላይ ጠረግ ያድርጉ"</string>
<string name="keyguard_retry" msgid="886802522584053523">"እንደገና ለመሞከር ወደ ላይ ይጥረጉ"</string>
- <!-- no translation found for require_unlock_for_nfc (1305686454823018831) -->
- <skip />
+ <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCን ለመጠቀም ይክፈቱ"</string>
<string name="do_disclosure_generic" msgid="4896482821974707167">"ይህ መሣሪያ የድርጅትዎ ነው"</string>
<string name="do_disclosure_with_name" msgid="2091641464065004091">"ይህ መሳሪያ ንብረትነቱ የ<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ነው"</string>
<string name="phone_hint" msgid="6682125338461375925">"ለስልክ ከአዶ ላይ ጠረግ ያድርጉ"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 39f9b86..8abb5ed 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -416,10 +416,8 @@
<string name="quick_settings_screen_record_label" msgid="1594046461509776676">"স্ক্ৰীন ৰেকর্ড"</string>
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"আৰম্ভ কৰক"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"বন্ধ কৰক"</string>
- <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) -->
- <skip />
- <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) -->
- <skip />
+ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"অব্যাহত ৰাখিবলৈ <b><xliff:g id="APP">%s</xliff:g></b>এ আপোনাৰ ডিভাইচৰ মাইক্ৰ’ফ’ন এক্সেছ কৰাৰ আৱশ্যক।"</string>
+ <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"অব্যাহত ৰাখিবলৈ <b><xliff:g id="APP">%s</xliff:g></b>এ আপোনাৰ ডিভাইচৰ কেমেৰা এক্সেছ কৰাৰ আৱশ্যক।"</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"ডিভাইচ"</string>
<string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"আনটো এপ্ ব্য়ৱহাৰ কৰিবলৈ ওপৰলৈ ছোৱাইপ কৰক"</string>
<string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"খৰতকীয়াকৈ আনটো এপ্ ব্য়ৱহাৰ কৰিবলৈ সোঁফালে টানক"</string>
@@ -442,8 +440,7 @@
<string name="notification_tap_again" msgid="4477318164947497249">"খুলিবলৈ পুনৰাই টিপক"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"খুলিবলৈ ওপৰলৈ ছোৱাইপ কৰক"</string>
<string name="keyguard_retry" msgid="886802522584053523">"পুনৰ চেষ্টা কৰিবলৈ ওপৰলৈ ছোৱাইপ কৰক"</string>
- <!-- no translation found for require_unlock_for_nfc (1305686454823018831) -->
- <skip />
+ <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ব্যৱহাৰ কৰিবলৈ আনলক কৰক"</string>
<string name="do_disclosure_generic" msgid="4896482821974707167">"এই ডিভাইচটো আপোনাৰ প্ৰতিষ্ঠানৰ"</string>
<string name="do_disclosure_with_name" msgid="2091641464065004091">"এই ডিভাইচটো <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>ৰ"</string>
<string name="phone_hint" msgid="6682125338461375925">"ফ\'নৰ বাবে আইকনৰপৰা ছোৱাইপ কৰক"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index aa80bd8..d2f0c0d 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -418,10 +418,8 @@
<string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Snimanje ekrana"</string>
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Započnite"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Zaustavite"</string>
- <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) -->
- <skip />
- <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) -->
- <skip />
+ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Da nastavite, aplikaciji <b><xliff:g id="APP">%s</xliff:g></b> je potreban pristup mikrofonu vašeg uređaja."</string>
+ <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Da nastavite, aplikaciji <b><xliff:g id="APP">%s</xliff:g></b> je potreban pristup kameri vašeg uređaja."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Uređaj"</string>
<string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Prevucite prema gore za promjenu aplikacije"</string>
<string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Prevucite udesno za brzu promjenu aplikacija"</string>
@@ -444,8 +442,7 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Dodirnite ponovo da otvorite"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Prevucite da otvorite"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Prevucite prema gore da pokušate ponovo"</string>
- <!-- no translation found for require_unlock_for_nfc (1305686454823018831) -->
- <skip />
+ <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Otključajte da koristite NFC"</string>
<string name="do_disclosure_generic" msgid="4896482821974707167">"Ovaj uređaj pripada vašoj organizaciji"</string>
<string name="do_disclosure_with_name" msgid="2091641464065004091">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Prevucite preko ikone da otvorite telefon"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 6f7044c..dccea5a 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -416,10 +416,8 @@
<string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ضبط کردن صفحهنمایش"</string>
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"شروع"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"توقف"</string>
- <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) -->
- <skip />
- <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) -->
- <skip />
+ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"برای ادامه دادن، <b><xliff:g id="APP">%s</xliff:g></b> باید به میکروفون دستگاه دسترسی داشته باشد."</string>
+ <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"برای ادامه دادن، <b><xliff:g id="APP">%s</xliff:g></b> باید به دوربین دستگاه دسترسی داشته باشد."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"دستگاه"</string>
<string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"برای تغییر برنامهها، تند بهبالا بکشید"</string>
<string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"برای جابهجایی سریع میان برنامهها، به چپ بکشید"</string>
@@ -442,8 +440,7 @@
<string name="notification_tap_again" msgid="4477318164947497249">"دوباره ضربه بزنید تا باز شود"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"برای باز کردن، انگشتتان را تند بهبالا بکشید"</string>
<string name="keyguard_retry" msgid="886802522584053523">"برای امتحان مجدد، انگشتتان را تند بهبالا بکشید"</string>
- <!-- no translation found for require_unlock_for_nfc (1305686454823018831) -->
- <skip />
+ <string name="require_unlock_for_nfc" msgid="1305686454823018831">"برای استفاده از NFC، قفل را باز کنید"</string>
<string name="do_disclosure_generic" msgid="4896482821974707167">"این دستگاه به سازمان شما تعلق دارد"</string>
<string name="do_disclosure_with_name" msgid="2091641464065004091">"این دستگاه به <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> تعلق دارد"</string>
<string name="phone_hint" msgid="6682125338461375925">"انگشتتان را از نماد تلفن تند بکشید"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index a2df616..2e36a92 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -416,10 +416,8 @@
<string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Enregistrement d\'écran"</string>
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Démarrer"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Arrêter"</string>
- <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) -->
- <skip />
- <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) -->
- <skip />
+ <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Pour continuer, vous devez accorder l\'accès au microphone de votre appareil à l\'application <b><xliff:g id="APP">%s</xliff:g></b>."</string>
+ <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Pour continuer, vous devez accorder l\'accès à l\'appareil photo de votre appareil à l\'application <b><xliff:g id="APP">%s</xliff:g></b>."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Appareil"</string>
<string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Balayez vers le haut pour changer d\'application"</string>
<string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Balayez l\'écran vers la droite pour changer rapidement d\'application"</string>
@@ -442,8 +440,7 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Touchez à nouveau pour ouvrir"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Balayez l\'écran vers le haut pour ouvrir"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Balayez l\'écran vers le haut pour réessayer"</string>
- <!-- no translation found for require_unlock_for_nfc (1305686454823018831) -->
- <skip />
+ <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Déverrouillez l\'écran pour utiliser la NFC"</string>
<string name="do_disclosure_generic" msgid="4896482821974707167">"Cet appareil appartient à votre organisation"</string>
<string name="do_disclosure_with_name" msgid="2091641464065004091">"Cet appareil appartient à <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="6682125338461375925">"Balayez à partir de l\'icône pour accéder au téléphone"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 93d2f75..0a17828 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -86,10 +86,10 @@
<bool name="config_navigation_bar_enable_auto_dim_no_visible_wallpaper">true</bool>
<!-- The maximum number of tiles in the QuickQSPanel -->
- <integer name="quick_qs_panel_max_columns">4</integer>
+ <integer name="quick_qs_panel_max_columns">6</integer>
<!-- The number of columns in the QuickSettings -->
- <integer name="quick_settings_num_columns">4</integer>
+ <integer name="quick_settings_num_columns">3</integer>
<!-- The number of rows in the QuickSettings -->
<integer name="quick_settings_max_rows">3</integer>
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimation.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimation.java
new file mode 100644
index 0000000..5fc2e53
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimation.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 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.biometrics;
+
+import android.content.Context;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+
+import androidx.annotation.NonNull;
+
+import com.android.systemui.R;
+
+/**
+ * Abstract base class for animations that should be drawn when the finger is not touching the
+ * sensor area.
+ */
+public abstract class UdfpsAnimation extends Drawable {
+ abstract void updateColor();
+
+ @NonNull protected final Context mContext;
+ @NonNull protected final Drawable mFingerprintDrawable;
+
+ public UdfpsAnimation(@NonNull Context context) {
+ mContext = context;
+ mFingerprintDrawable = context.getResources().getDrawable(R.drawable.ic_fingerprint, null);
+ }
+
+ public void onSensorRectUpdated(@NonNull RectF sensorRect) {
+ int margin = (int) (sensorRect.bottom - sensorRect.top) / 5;
+ mFingerprintDrawable.setBounds(
+ (int) sensorRect.left + margin,
+ (int) sensorRect.top + margin,
+ (int) sensorRect.right - margin,
+ (int) sensorRect.bottom - margin);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationEnroll.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationEnroll.java
new file mode 100644
index 0000000..1a2a492
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationEnroll.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2021 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.biometrics;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.RectF;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.systemui.R;
+
+/**
+ * UDFPS animations that should be shown when enrolling.
+ */
+public class UdfpsAnimationEnroll extends UdfpsAnimation {
+ private static final String TAG = "UdfpsAnimationEnroll";
+
+ @Nullable private RectF mSensorRect;
+ @NonNull private final Paint mSensorPaint;
+
+ UdfpsAnimationEnroll(@NonNull Context context) {
+ super(context);
+
+ mSensorPaint = new Paint(0 /* flags */);
+ mSensorPaint.setAntiAlias(true);
+ mSensorPaint.setColor(Color.WHITE);
+ mSensorPaint.setShadowLayer(UdfpsView.SENSOR_SHADOW_RADIUS, 0, 0, Color.BLACK);
+ mSensorPaint.setStyle(Paint.Style.FILL);
+ }
+
+ @Override
+ void updateColor() {
+ mFingerprintDrawable.setTint(mContext.getColor(R.color.udfps_enroll_icon));
+ }
+
+ @Override
+ public void onSensorRectUpdated(@NonNull RectF sensorRect) {
+ super.onSensorRectUpdated(sensorRect);
+ mSensorRect = sensorRect;
+ }
+
+ @Override
+ public void draw(@NonNull Canvas canvas) {
+ final boolean isNightMode = (mContext.getResources().getConfiguration().uiMode
+ & Configuration.UI_MODE_NIGHT_YES) != 0;
+ if (!isNightMode) {
+ if (mSensorRect != null) {
+ canvas.drawOval(mSensorRect, mSensorPaint);
+ }
+ }
+ mFingerprintDrawable.draw(canvas);
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+
+ }
+
+ @Override
+ public void setColorFilter(@Nullable ColorFilter colorFilter) {
+
+ }
+
+ @Override
+ public int getOpacity() {
+ return 0;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationFpmOther.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationFpmOther.java
new file mode 100644
index 0000000..7563e73
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationFpmOther.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 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.biometrics;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+/**
+ * UDFPS animations that should be shown when authenticating via FingerprintManager, excluding
+ * keyguard.
+ */
+public class UdfpsAnimationFpmOther extends UdfpsAnimation {
+
+ UdfpsAnimationFpmOther(@NonNull Context context) {
+ super(context);
+ }
+
+ @Override
+ void updateColor() {
+
+ }
+
+ @Override
+ public void draw(@NonNull Canvas canvas) {
+ mFingerprintDrawable.draw(canvas);
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+
+ }
+
+ @Override
+ public void setColorFilter(@Nullable ColorFilter colorFilter) {
+
+ }
+
+ @Override
+ public int getOpacity() {
+ return 0;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationKeyguard.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationKeyguard.java
new file mode 100644
index 0000000..3e46a65
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationKeyguard.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2021 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.biometrics;
+
+import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.util.MathUtils;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.internal.graphics.ColorUtils;
+import com.android.settingslib.Utils;
+import com.android.systemui.R;
+import com.android.systemui.doze.DozeReceiver;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+
+/**
+ * UDFPS animations that should be shown when authenticating on keyguard.
+ */
+public class UdfpsAnimationKeyguard extends UdfpsAnimation implements DozeReceiver,
+ StatusBarStateController.StateListener {
+
+ private static final String TAG = "UdfpsAnimationKeyguard";
+
+ @NonNull private final View mParent;
+ @NonNull private final Context mContext;
+ private final int mMaxBurnInOffsetX;
+ private final int mMaxBurnInOffsetY;
+
+ // AOD anti-burn-in offsets
+ private float mInterpolatedDarkAmount;
+ private float mBurnInOffsetX;
+ private float mBurnInOffsetY;
+
+ UdfpsAnimationKeyguard(@NonNull View parent, @NonNull Context context,
+ @NonNull StatusBarStateController statusBarStateController) {
+ super(context);
+ mParent = parent;
+ mContext = context;
+
+ mMaxBurnInOffsetX = context.getResources()
+ .getDimensionPixelSize(R.dimen.udfps_burn_in_offset_x);
+ mMaxBurnInOffsetY = context.getResources()
+ .getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y);
+
+ statusBarStateController.addCallback(this);
+ }
+
+ private void updateAodPositionAndColor() {
+ mBurnInOffsetX = MathUtils.lerp(0f,
+ getBurnInOffset(mMaxBurnInOffsetX * 2, true /* xAxis */)
+ - mMaxBurnInOffsetX,
+ mInterpolatedDarkAmount);
+ mBurnInOffsetY = MathUtils.lerp(0f,
+ getBurnInOffset(mMaxBurnInOffsetY * 2, false /* xAxis */)
+ - 0.5f * mMaxBurnInOffsetY,
+ mInterpolatedDarkAmount);
+ updateColor();
+ mParent.postInvalidate();
+ }
+
+ @Override
+ public void dozeTimeTick() {
+ updateAodPositionAndColor();
+ }
+
+ @Override
+ public void onDozeAmountChanged(float linear, float eased) {
+ mInterpolatedDarkAmount = eased;
+ updateAodPositionAndColor();
+ }
+
+ @Override
+ public void draw(@NonNull Canvas canvas) {
+ canvas.save();
+ canvas.translate(mBurnInOffsetX, mBurnInOffsetY);
+ mFingerprintDrawable.draw(canvas);
+ canvas.restore();
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+
+ }
+
+ @Override
+ public void setColorFilter(@Nullable ColorFilter colorFilter) {
+
+ }
+
+ @Override
+ public int getOpacity() {
+ return 0;
+ }
+
+ @Override
+ public void updateColor() {
+ final int lockScreenIconColor = Utils.getColorAttrDefaultColor(mContext,
+ R.attr.wallpaperTextColor);
+ final int ambientDisplayIconColor = Color.WHITE;
+ mFingerprintDrawable.setTint(ColorUtils.blendARGB(lockScreenIconColor,
+ ambientDisplayIconColor, mInterpolatedDarkAmount));
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 1cafb4c..a2b2bea8 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -81,6 +81,7 @@
private final WindowManager mWindowManager;
private final SystemSettings mSystemSettings;
private final DelayableExecutor mFgExecutor;
+ private final StatusBarStateController mStatusBarStateController;
// Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
// sensors, this, in addition to a lot of the code here, will be updated.
@VisibleForTesting final FingerprintSensorPropertiesInternal mSensorProps;
@@ -181,6 +182,7 @@
mWindowManager = windowManager;
mSystemSettings = systemSettings;
mFgExecutor = fgExecutor;
+ mStatusBarStateController = statusBarStateController;
mSensorProps = findFirstUdfps();
// At least one UDFPS sensor exists
@@ -208,7 +210,6 @@
mHbmSupported = !TextUtils.isEmpty(mHbmPath);
mView.setHbmSupported(mHbmSupported);
- statusBarStateController.addCallback(mView);
// This range only consists of the minimum and maximum values, which only cover
// non-high-brightness mode.
@@ -340,7 +341,7 @@
if (!mIsOverlayShowing) {
try {
Log.v(TAG, "showUdfpsOverlay | adding window");
- mView.setShowReason(reason);
+ mView.setUdfpsAnimation(getUdfpsAnimationForReason(reason));
mWindowManager.addView(mView, computeLayoutParams());
mView.setOnTouchListener(mOnTouchListener);
mIsOverlayShowing = true;
@@ -353,11 +354,27 @@
});
}
+ @Nullable
+ private UdfpsAnimation getUdfpsAnimationForReason(int reason) {
+ Log.d(TAG, "getUdfpsAnimationForReason: " + reason);
+ switch (reason) {
+ case IUdfpsOverlayController.REASON_ENROLL:
+ return new UdfpsAnimationEnroll(mContext);
+ case IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD:
+ return new UdfpsAnimationKeyguard(mView, mContext, mStatusBarStateController);
+ case IUdfpsOverlayController.REASON_AUTH_FPM_OTHER:
+ return new UdfpsAnimationFpmOther(mContext);
+ default:
+ Log.d(TAG, "Animation for reason " + reason + " not supported yet");
+ return null;
+ }
+ }
+
private void hideUdfpsOverlay() {
mFgExecutor.execute(() -> {
if (mIsOverlayShowing) {
Log.v(TAG, "hideUdfpsOverlay | removing window");
- mView.setShowReason(IUdfpsOverlayController.REASON_UNKNOWN);
+ mView.setUdfpsAnimation(null);
mView.setOnTouchListener(null);
// Reset the controller back to its starting state.
onFingerUp();
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
index 033a355..4cb8101 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
@@ -16,45 +16,34 @@
package com.android.systemui.biometrics;
-import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
-import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.hardware.fingerprint.IUdfpsOverlayController;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
-import android.util.MathUtils;
import android.view.Surface;
import android.view.View;
import android.view.ViewTreeObserver;
-import com.android.internal.graphics.ColorUtils;
-import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.doze.DozeReceiver;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
/**
* A full screen view with a configurable illumination dot and scrim.
*/
-public class UdfpsView extends View implements DozeReceiver,
- StatusBarStateController.StateListener {
+public class UdfpsView extends View implements DozeReceiver {
private static final String TAG = "UdfpsView";
// Values in pixels.
- private static final float SENSOR_SHADOW_RADIUS = 2.0f;
- private static final float SENSOR_OUTLINE_WIDTH = 2.0f;
+ public static final float SENSOR_SHADOW_RADIUS = 2.0f;
private static final int DEBUG_TEXT_SIZE_PX = 32;
@@ -65,8 +54,7 @@
@NonNull private final RectF mSensorRect;
@NonNull private final Paint mSensorPaint;
private final float mSensorTouchAreaCoefficient;
- private final int mMaxBurnInOffsetX;
- private final int mMaxBurnInOffsetY;
+
// Stores rounded up values from mSensorRect. Necessary for APIs that only take Rect (not RecF).
@NonNull private final Rect mTouchableRegion;
@@ -75,17 +63,11 @@
// mInsetsListener to restrict the touchable region and allow the touches outside of the sensor
// to propagate to the rest of the UI.
@NonNull private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsListener;
- @NonNull private final Drawable mFingerprintDrawable;
+ @Nullable private UdfpsAnimation mUdfpsAnimation;
// Used to obtain the sensor location.
@NonNull private FingerprintSensorPropertiesInternal mSensorProps;
- // AOD anti-burn-in offsets
- private float mInterpolatedDarkAmount;
- private float mBurnInOffsetX;
- private float mBurnInOffsetY;
-
- private int mShowReason;
private boolean mShowScrimAndDot;
private boolean mIsHbmSupported;
@Nullable private String mDebugMessage;
@@ -110,10 +92,6 @@
a.recycle();
}
- mMaxBurnInOffsetX = getResources()
- .getDimensionPixelSize(R.dimen.udfps_burn_in_offset_x);
- mMaxBurnInOffsetY = getResources()
- .getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y);
mScrimRect = new Rect();
mScrimPaint = new Paint(0 /* flags */);
@@ -131,8 +109,6 @@
mDebugTextPaint.setColor(Color.BLUE);
mDebugTextPaint.setTextSize(DEBUG_TEXT_SIZE_PX);
- mFingerprintDrawable = getResources().getDrawable(R.drawable.ic_fingerprint, null);
-
mTouchableRegion = new Rect();
// When the device is rotated, it's important that mTouchableRegion is updated before
// this listener is called. This listener is usually called shortly after onLayout.
@@ -149,39 +125,20 @@
mSensorProps = properties;
}
- /**
- * @param reason See {@link android.hardware.fingerprint.IUdfpsOverlayController}
- */
- void setShowReason(int reason) {
- mShowReason = reason;
+ void setUdfpsAnimation(@Nullable UdfpsAnimation animation) {
+ mUdfpsAnimation = animation;
}
+
@Override
public void dozeTimeTick() {
- updateAodPositionAndColor();
- }
-
- @Override
- public void onDozeAmountChanged(float linear, float eased) {
- mInterpolatedDarkAmount = eased;
- updateAodPositionAndColor();
- }
-
- private void updateAodPositionAndColor() {
- mBurnInOffsetX = MathUtils.lerp(0f,
- getBurnInOffset(mMaxBurnInOffsetX * 2, true /* xAxis */)
- - mMaxBurnInOffsetX,
- mInterpolatedDarkAmount);
- mBurnInOffsetY = MathUtils.lerp(0f,
- getBurnInOffset(mMaxBurnInOffsetY * 2, false /* xAxis */)
- - 0.5f * mMaxBurnInOffsetY,
- mInterpolatedDarkAmount);
- updateColor();
- postInvalidate();
+ if (mUdfpsAnimation instanceof DozeReceiver) {
+ ((DozeReceiver) mUdfpsAnimation).dozeTimeTick();
+ }
}
// The "h" and "w" are the display's height and width relative to its current rotation.
- private void updateSensorRect(int h, int w) {
+ protected void updateSensorRect(int h, int w) {
// mSensorProps coordinates assume portrait mode.
mSensorRect.set(mSensorProps.sensorLocationX - mSensorProps.sensorRadius,
mSensorProps.sensorLocationY - mSensorProps.sensorRadius,
@@ -202,12 +159,9 @@
// Do nothing to stay in portrait mode.
}
- int margin = (int) (mSensorRect.bottom - mSensorRect.top) / 5;
- mFingerprintDrawable.setBounds(
- (int) mSensorRect.left + margin,
- (int) mSensorRect.top + margin,
- (int) mSensorRect.right - margin,
- (int) mSensorRect.bottom - margin);
+ if (mUdfpsAnimation != null) {
+ mUdfpsAnimation.onSensorRectUpdated(new RectF(mSensorRect));
+ }
}
@Override
@@ -239,14 +193,8 @@
}
private void updateColor() {
- if (mShowReason == IUdfpsOverlayController.REASON_AUTH) {
- final int lockScreenIconColor = Utils.getColorAttrDefaultColor(mContext,
- com.android.systemui.R.attr.wallpaperTextColor);
- final int ambientDisplayIconColor = Color.WHITE;
- mFingerprintDrawable.setTint(ColorUtils.blendARGB(lockScreenIconColor,
- ambientDisplayIconColor, mInterpolatedDarkAmount));
- } else if (mShowReason == IUdfpsOverlayController.REASON_ENROLL) {
- mFingerprintDrawable.setTint(mContext.getColor(R.color.udfps_enroll_icon));
+ if (mUdfpsAnimation != null) {
+ mUdfpsAnimation.updateColor();
}
}
@@ -266,9 +214,6 @@
canvas.drawRect(mScrimRect, mScrimPaint);
}
- // Translation should affect everything but the scrim.
- canvas.save();
- canvas.translate(mBurnInOffsetX, mBurnInOffsetY);
if (!TextUtils.isEmpty(mDebugMessage)) {
canvas.drawText(mDebugMessage, 0, 160, mDebugTextPaint);
}
@@ -277,17 +222,11 @@
// draw dot (white circle)
canvas.drawOval(mSensorRect, mSensorPaint);
} else {
- final boolean isNightMode = (getResources().getConfiguration().uiMode
- & Configuration.UI_MODE_NIGHT_YES) != 0;
- if (mShowReason == IUdfpsOverlayController.REASON_ENROLL && !isNightMode) {
- canvas.drawOval(mSensorRect, mSensorPaint);
+ if (mUdfpsAnimation != null) {
+ mUdfpsAnimation.draw(canvas);
}
- // draw fingerprint icon
- mFingerprintDrawable.draw(canvas);
}
- canvas.restore();
-
if (mShowScrimAndDot && mRunAfterShowingScrimAndDot != null) {
post(mRunAfterShowingScrimAndDot);
mRunAfterShowingScrimAndDot = null;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index c2c4ad8..d7a3537 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -92,6 +92,10 @@
private static final int MAX_LONG_PRESS_TIMEOUT = SystemProperties.getInt(
"gestures.back_timeout", 250);
+ // Temporary log until b/176302696 is resolved
+ static final boolean DEBUG_MISSING_GESTURE = true;
+ static final String DEBUG_MISSING_GESTURE_TAG = "NoBackGesture";
+
private ISystemGestureExclusionListener mGestureExclusionListener =
new ISystemGestureExclusionListener.Stub() {
@Override
@@ -223,8 +227,12 @@
new NavigationEdgeBackPlugin.BackCallback() {
@Override
public void triggerBack() {
- sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
- sendEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
+ boolean sendDown = sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
+ boolean sendUp = sendEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
+ if (DEBUG_MISSING_GESTURE) {
+ Log.d(DEBUG_MISSING_GESTURE_TAG, "Triggered back: down=" + sendDown
+ + ", up=" + sendUp);
+ }
mOverviewProxyService.notifyBackAction(true, (int) mDownPoint.x,
(int) mDownPoint.y, false /* isButton */, !mIsOnLeftEdge);
@@ -694,6 +702,9 @@
if (action == MotionEvent.ACTION_POINTER_DOWN) {
if (mAllowGesture) {
logGesture(SysUiStatsLog.BACK_GESTURE__TYPE__INCOMPLETE_MULTI_TOUCH);
+ if (DEBUG_MISSING_GESTURE) {
+ Log.d(DEBUG_MISSING_GESTURE_TAG, "Cancel back: multitouch");
+ }
// We do not support multi touch for back gesture
cancelGesture(ev);
}
@@ -704,6 +715,12 @@
if (mAllowGesture) {
logGesture(SysUiStatsLog.BACK_GESTURE__TYPE__INCOMPLETE_LONG_PRESS);
cancelGesture(ev);
+ if (DEBUG_MISSING_GESTURE) {
+ Log.d(DEBUG_MISSING_GESTURE_TAG, "Cancel back [longpress]: "
+ + ev.getEventTime()
+ + " " + ev.getDownTime()
+ + " " + mLongPressTimeout);
+ }
}
mLogGesture = false;
return;
@@ -714,6 +731,10 @@
if (mAllowGesture) {
logGesture(SysUiStatsLog.BACK_GESTURE__TYPE__INCOMPLETE_VERTICAL_MOVE);
cancelGesture(ev);
+ if (DEBUG_MISSING_GESTURE) {
+ Log.d(DEBUG_MISSING_GESTURE_TAG, "Cancel back [vertical move]: "
+ + dy + " " + dx + " " + mTouchSlop);
+ }
}
mLogGesture = false;
return;
@@ -769,7 +790,7 @@
}
}
- private void sendEvent(int action, int code) {
+ private boolean sendEvent(int action, int code) {
long when = SystemClock.uptimeMillis();
final KeyEvent ev = new KeyEvent(when, when, action, code, 0 /* repeat */,
0 /* metaState */, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */,
@@ -777,7 +798,8 @@
InputDevice.SOURCE_KEYBOARD);
ev.setDisplayId(mContext.getDisplay().getDisplayId());
- InputManager.getInstance().injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
+ return InputManager.getInstance()
+ .injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
}
public void setInsets(int leftInset, int rightInset) {
@@ -803,6 +825,7 @@
pw.println(" mEdgeWidthRight=" + mEdgeWidthRight);
pw.println(" mIsNavBarShownTransiently=" + mIsNavBarShownTransiently);
pw.println(" mPredictionLog=" + String.join(";", mPredictionLog));
+ pw.println(" mEdgeBackPlugin=" + mEdgeBackPlugin);
}
private boolean isGestureBlockingActivityRunning() {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
index fbbda5f..ac9f183 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
@@ -18,6 +18,9 @@
import static android.view.Display.DEFAULT_DISPLAY;
+import static com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler.DEBUG_MISSING_GESTURE;
+import static com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler.DEBUG_MISSING_GESTURE_TAG;
+
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Configuration;
@@ -29,6 +32,7 @@
import android.graphics.Rect;
import android.os.SystemClock;
import android.os.VibrationEffect;
+import android.util.Log;
import android.util.MathUtils;
import android.view.ContextThemeWrapper;
import android.view.Gravity;
@@ -461,6 +465,10 @@
handleMoveEvent(event);
break;
case MotionEvent.ACTION_UP:
+ if (DEBUG_MISSING_GESTURE) {
+ Log.d(DEBUG_MISSING_GESTURE_TAG,
+ "NavigationBarEdgePanel ACTION_UP, mTriggerBack=" + mTriggerBack);
+ }
if (mTriggerBack) {
triggerBack();
} else {
@@ -471,6 +479,9 @@
mVelocityTracker = null;
break;
case MotionEvent.ACTION_CANCEL:
+ if (DEBUG_MISSING_GESTURE) {
+ Log.d(DEBUG_MISSING_GESTURE_TAG, "NavigationBarEdgePanel ACTION_CANCEL");
+ }
cancelBack();
mRegionSamplingHelper.stop();
mVelocityTracker.recycle();
@@ -661,6 +672,9 @@
mAngleOffset = 0;
mTranslationAnimation.setSpring(mRegularTranslationSpring);
// Reset the arrow to the side
+ if (DEBUG_MISSING_GESTURE) {
+ Log.d(DEBUG_MISSING_GESTURE_TAG, "reset mTriggerBack=false");
+ }
setTriggerBack(false /* triggerBack */, false /* animated */);
setDesiredTranslation(0, false /* animated */);
setCurrentTranslation(0);
@@ -696,6 +710,9 @@
mDisappearAmount = 0.0f;
setAlpha(1f);
// And animate it go to back by default!
+ if (DEBUG_MISSING_GESTURE) {
+ Log.d(DEBUG_MISSING_GESTURE_TAG, "set mTriggerBack=true");
+ }
setTriggerBack(true /* triggerBack */, true /* animated */);
}
@@ -736,6 +753,14 @@
if (Math.abs(yOffset) > Math.abs(x - mStartX) * 2) {
triggerBack = false;
}
+ if (DEBUG_MISSING_GESTURE && mTriggerBack != triggerBack) {
+ Log.d(DEBUG_MISSING_GESTURE_TAG, "set mTriggerBack=" + triggerBack
+ + ", mTotalTouchDelta=" + mTotalTouchDelta
+ + ", mMinDeltaForSwitch=" + mMinDeltaForSwitch
+ + ", yOffset=" + yOffset
+ + ", x=" + x
+ + ", mStartX=" + mStartX);
+ }
setTriggerBack(triggerBack, true /* animated */);
if (!mTriggerBack) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
index 2dfac1b..fa1f7c4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
@@ -146,7 +146,8 @@
RecyclerView recyclerView = mView.getRecyclerView();
recyclerView.setAdapter(mTileAdapter);
mTileAdapter.getItemTouchHelper().attachToRecyclerView(recyclerView);
- GridLayoutManager layout = new GridLayoutManager(getContext(), TileAdapter.NUM_COLUMNS) {
+ GridLayoutManager layout =
+ new GridLayoutManager(getContext(), mTileAdapter.getNumColumns()) {
@Override
public void onInitializeAccessibilityNodeInfoForItem(RecyclerView.Recycler recycler,
RecyclerView.State state, View host, AccessibilityNodeInfoCompat info) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 036fa86..507048c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -61,7 +61,6 @@
private static final long DRAG_LENGTH = 100;
private static final float DRAG_SCALE = 1.2f;
public static final long MOVE_DURATION = 150;
- public static final int NUM_COLUMNS = 4;
private static final int TYPE_TILE = 0;
private static final int TYPE_EDIT = 1;
@@ -99,6 +98,7 @@
private final UiEventLogger mUiEventLogger;
private final AccessibilityDelegateCompat mAccessibilityDelegate;
private RecyclerView mRecyclerView;
+ private final int mNumColumns;
@Inject
public TileAdapter(Context context, QSTileHost qsHost, UiEventLogger uiEventLogger) {
@@ -109,6 +109,7 @@
mDecoration = new TileItemDecoration(context);
mMarginDecoration = new MarginTileDecoration();
mMinNumTiles = context.getResources().getInteger(R.integer.quick_settings_min_num_tiles);
+ mNumColumns = context.getResources().getInteger(R.integer.quick_settings_num_columns);
mAccessibilityDelegate = new TileAdapterDelegate();
}
@@ -122,6 +123,10 @@
mRecyclerView = null;
}
+ public int getNumColumns() {
+ return mNumColumns;
+ }
+
public ItemTouchHelper getItemTouchHelper() {
return mItemTouchHelper;
}
@@ -602,7 +607,7 @@
public int getSpanSize(int position) {
final int type = getItemViewType(position);
if (type == TYPE_EDIT || type == TYPE_DIVIDER || type == TYPE_HEADER) {
- return NUM_COLUMNS;
+ return mNumColumns;
} else {
return 1;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index c052563..ed3cf9a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -162,7 +162,7 @@
@Test
public void showUdfpsOverlay_addsViewToWindow() throws RemoteException {
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
- IUdfpsOverlayController.REASON_AUTH);
+ IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
mFgExecutor.runAllReady();
verify(mWindowManager).addView(eq(mUdfpsView), any());
}
@@ -170,7 +170,7 @@
@Test
public void hideUdfpsOverlay_removesViewFromWindow() throws RemoteException {
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
- IUdfpsOverlayController.REASON_AUTH);
+ IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
mOverlayController.hideUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
mFgExecutor.runAllReady();
verify(mWindowManager).removeView(eq(mUdfpsView));
@@ -184,7 +184,7 @@
// GIVEN that the overlay is showing
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
- IUdfpsOverlayController.REASON_AUTH);
+ IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
mFgExecutor.runAllReady();
// WHEN ACTION_DOWN is received
verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture());
@@ -205,7 +205,7 @@
public void aodInterrupt() throws RemoteException {
// GIVEN that the overlay is showing
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
- IUdfpsOverlayController.REASON_AUTH);
+ IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
mFgExecutor.runAllReady();
// WHEN fingerprint is requested because of AOD interrupt
mUdfpsController.onAodInterrupt(0, 0, 2f, 3f);
@@ -223,7 +223,7 @@
public void cancelAodInterrupt() throws RemoteException {
// GIVEN AOD interrupt
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
- IUdfpsOverlayController.REASON_AUTH);
+ IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
mFgExecutor.runAllReady();
mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
// WHEN it is cancelled
@@ -236,7 +236,7 @@
public void aodInterruptTimeout() throws RemoteException {
// GIVEN AOD interrupt
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
- IUdfpsOverlayController.REASON_AUTH);
+ IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
mFgExecutor.runAllReady();
mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
// WHEN it times out
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 9aadcf8..b6232a0 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -325,8 +325,6 @@
private boolean mRestrictBackground;
private final Context mContext;
- // The Context is created for UserHandle.ALL.
- private final Context mUserAllContext;
private final Dependencies mDeps;
// 0 is full bad, 100 is full good
private int mDefaultInetConditionPublished = 0;
@@ -1162,8 +1160,8 @@
intentFilter.addAction(Intent.ACTION_USER_REMOVED);
intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
- mUserAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */);
- mUserAllContext.registerReceiver(
+ final Context userAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */);
+ userAllContext.registerReceiver(
mIntentReceiver,
intentFilter,
null /* broadcastPermission */,
@@ -1179,7 +1177,7 @@
intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
intentFilter.addDataScheme("package");
- mUserAllContext.registerReceiver(
+ userAllContext.registerReceiver(
mIntentReceiver,
intentFilter,
null /* broadcastPermission */,
@@ -1188,7 +1186,7 @@
// Listen to lockdown VPN reset.
intentFilter = new IntentFilter();
intentFilter.addAction(LockdownVpnTracker.ACTION_LOCKDOWN_RESET);
- mUserAllContext.registerReceiver(
+ userAllContext.registerReceiver(
mIntentReceiver, intentFilter, NETWORK_STACK, mHandler);
mNetworkActivityTracker = new LegacyNetworkActivityTracker(mContext, mNMS);
@@ -2352,7 +2350,7 @@
intent.addFlags(Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
}
try {
- mUserAllContext.sendStickyBroadcast(intent, options);
+ mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL, options);
} finally {
Binder.restoreCallingIdentity(ident);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 780c026..7fe1ccc 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6043,10 +6043,18 @@
abiOverride, zygotePolicyFlags);
}
- // TODO: Move to ProcessList?
@GuardedBy("this")
final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
boolean disableHiddenApiChecks, String abiOverride, int zygotePolicyFlags) {
+ return addAppLocked(info, customProcess, isolated, disableHiddenApiChecks,
+ false /* disableTestApiChecks */, abiOverride, zygotePolicyFlags);
+ }
+
+ // TODO: Move to ProcessList?
+ @GuardedBy("this")
+ final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
+ boolean disableHiddenApiChecks, boolean disableTestApiChecks,
+ String abiOverride, int zygotePolicyFlags) {
ProcessRecord app;
if (!isolated) {
app = getProcessRecordLocked(customProcess != null ? customProcess : info.processName,
@@ -6081,7 +6089,7 @@
mPersistentStartingProcesses.add(app);
mProcessList.startProcessLocked(app, new HostingRecord("added application",
customProcess != null ? customProcess : app.processName),
- zygotePolicyFlags, disableHiddenApiChecks, abiOverride);
+ zygotePolicyFlags, disableHiddenApiChecks, disableTestApiChecks, abiOverride);
}
return app;
@@ -14398,10 +14406,11 @@
mUsageStatsService.reportEvent(ii.targetPackage, userId,
UsageEvents.Event.SYSTEM_INTERACTION);
}
- app = addAppLocked(ai, defProcess, false, disableHiddenApiChecks, abiOverride,
- ZYGOTE_POLICY_FLAG_EMPTY);
+ app = addAppLocked(ai, defProcess, false, disableHiddenApiChecks,
+ disableTestApiChecks, abiOverride, ZYGOTE_POLICY_FLAG_EMPTY);
}
+
app.setActiveInstrumentation(activeInstr);
activeInstr.mFinished = false;
activeInstr.mSourceUid = callingUid;
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 1c98fd6..2273779 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -1748,7 +1748,8 @@
*/
@GuardedBy("mService")
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
- int zygotePolicyFlags, boolean disableHiddenApiChecks, String abiOverride) {
+ int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,
+ String abiOverride) {
if (app.pendingStart) {
return true;
}
@@ -1888,6 +1889,10 @@
throw new IllegalStateException("Invalid API policy: " + policy);
}
runtimeFlags |= policyBits;
+
+ if (disableTestApiChecks) {
+ runtimeFlags |= Zygote.DISABLE_TEST_API_ENFORCEMENT_POLICY;
+ }
}
String useAppImageCache = SystemProperties.get(
@@ -2337,7 +2342,8 @@
final boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
int zygotePolicyFlags, String abiOverride) {
return startProcessLocked(app, hostingRecord, zygotePolicyFlags,
- false /* disableHiddenApiChecks */, abiOverride);
+ false /* disableHiddenApiChecks */, false /* disableTestApiChecks */,
+ abiOverride);
}
@GuardedBy("mService")
diff --git a/services/core/java/com/android/server/biometrics/Utils.java b/services/core/java/com/android/server/biometrics/Utils.java
index 55ac248..d87af42 100644
--- a/services/core/java/com/android/server/biometrics/Utils.java
+++ b/services/core/java/com/android/server/biometrics/Utils.java
@@ -50,6 +50,7 @@
import android.hardware.biometrics.PromptInfo;
import android.hardware.biometrics.SensorProperties;
import android.hardware.biometrics.SensorPropertiesInternal;
+import android.hardware.fingerprint.IUdfpsOverlayController;
import android.os.Binder;
import android.os.Build;
import android.os.RemoteException;
@@ -61,6 +62,7 @@
import com.android.internal.R;
import com.android.internal.widget.LockPatternUtils;
+import com.android.server.biometrics.sensors.AuthenticationClient;
import com.android.server.biometrics.sensors.BaseClientMonitor;
import java.util.List;
@@ -478,4 +480,14 @@
throw new IllegalArgumentException("Unknown strength: " + strength);
}
}
+
+ public static int getUdfpsAuthReason(@NonNull AuthenticationClient<?> client) {
+ if (client.isKeyguard()) {
+ return IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD;
+ } else if (client.isBiometricPrompt()) {
+ return IUdfpsOverlayController.REASON_AUTH_BP;
+ } else {
+ return IUdfpsOverlayController.REASON_AUTH_FPM_OTHER;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
index 3f6ae64..14433fb 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -53,6 +53,7 @@
@Nullable private final TaskStackListener mTaskStackListener;
private final LockoutTracker mLockoutTracker;
private final boolean mIsRestricted;
+ private final boolean mIsKeyguard;
protected final long mOperationId;
@@ -65,7 +66,7 @@
int targetUserId, long operationId, boolean restricted, @NonNull String owner,
int cookie, boolean requireConfirmation, int sensorId, boolean isStrongBiometric,
int statsModality, int statsClient, @Nullable TaskStackListener taskStackListener,
- @NonNull LockoutTracker lockoutTracker) {
+ @NonNull LockoutTracker lockoutTracker, boolean isKeyguard) {
super(context, lazyDaemon, token, listener, targetUserId, owner, cookie, sensorId,
statsModality, BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient);
mIsStrongBiometric = isStrongBiometric;
@@ -75,6 +76,7 @@
mTaskStackListener = taskStackListener;
mLockoutTracker = lockoutTracker;
mIsRestricted = restricted;
+ mIsKeyguard = isKeyguard;
}
public @LockoutTracker.LockoutMode int handleFailedAttempt(int userId) {
@@ -114,6 +116,10 @@
return mIsRestricted;
}
+ public boolean isKeyguard() {
+ return mIsKeyguard;
+ }
+
@Override
protected boolean isCryptoOperation() {
return mOperationId != 0;
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
index 80f337f..a7bfc4b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
@@ -67,11 +67,11 @@
@NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
boolean restricted, String owner, int cookie, boolean requireConfirmation, int sensorId,
boolean isStrongBiometric, int statsClient, @NonNull UsageStats usageStats,
- @NonNull LockoutCache lockoutCache) {
+ @NonNull LockoutCache lockoutCache, boolean isKeyguard) {
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */,
- lockoutCache);
+ lockoutCache, isKeyguard);
mUsageStats = usageStats;
mLockoutCache = lockoutCache;
mNotificationManager = context.getSystemService(NotificationManager.class);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
index 632cc4b..d60bb79 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
@@ -116,9 +116,9 @@
try {
// TODO(b/172593978): Pass features.
// TODO(b/174619156): Handle accessibility enrollment.
- mCancellationSignal = getFreshDaemon().enroll(mSequentialId, EnrollmentType.DEFAULT,
+ mCancellationSignal = getFreshDaemon().enroll(mSequentialId,
HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken),
- mPreviewSurface);
+ EnrollmentType.DEFAULT, new byte[0], mPreviewSurface);
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception when requesting enroll", e);
onError(BiometricFaceConstants.FACE_ERROR_UNABLE_TO_PROCESS, 0 /* vendorCode */);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
index 20318e3..f7feffd 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
@@ -451,7 +451,7 @@
mContext, mSensors.get(sensorId).getLazySession(), token, callback, userId,
operationId, restricted, opPackageName, cookie,
false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient,
- mUsageStats, mSensors.get(sensorId).getLockoutCache());
+ mUsageStats, mSensors.get(sensorId).getLockoutCache(), isKeyguard);
mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
} catch (RemoteException e) {
Slog.e(getTag(), "Remote exception when scheduling authenticate", e);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
index 9b00ba6..f49601a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
@@ -357,6 +357,16 @@
}
@Override
+ public void onFeaturesRetrieved(byte[] features, int enrollmentId) {
+
+ }
+
+ @Override
+ public void onFeatureSet(int enrollmentId, byte feature) {
+
+ }
+
+ @Override
public void onEnrollmentsRemoved(int[] enrollmentIds) {
mHandler.post(() -> {
final BaseClientMonitor client = mScheduler.getCurrentClient();
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestHal.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestHal.java
index dc1efa0..1d57073 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestHal.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestHal.java
@@ -49,8 +49,8 @@
}
@Override
- public ICancellationSignal enroll(int cookie, byte enrollmentType,
- HardwareAuthToken hat, NativeHandle previewSurface) {
+ public ICancellationSignal enroll(int cookie, HardwareAuthToken hat,
+ byte enrollmentType, byte[] features, NativeHandle previewSurface) {
return null;
}
@@ -75,6 +75,17 @@
}
@Override
+ public void getFeatures(int cookie, int enrollmentId) {
+
+ }
+
+ @Override
+ public void setFeature(int cookie, HardwareAuthToken hat, int enrollmentId,
+ byte feature, boolean enabled) {
+
+ }
+
+ @Override
public void getAuthenticatorId(int cookie) {
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java
index 189c726..23e6988 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java
@@ -50,8 +50,8 @@
}
@Override
- public ICancellationSignal enroll(int cookie, byte enrollmentType, HardwareAuthToken hat,
- NativeHandle previewSurface) {
+ public ICancellationSignal enroll(int cookie, HardwareAuthToken hat, byte enrollmentType,
+ byte[] features, NativeHandle previewSurface) {
return null;
}
@@ -86,6 +86,17 @@
}
@Override
+ public void getFeatures(int cookie, int enrollmentId) {
+
+ }
+
+ @Override
+ public void setFeature(int cookie, HardwareAuthToken hat, int enrollmentId, byte feature,
+ boolean enabled) {
+
+ }
+
+ @Override
public void getAuthenticatorId(int cookie) {
Slog.d(TAG, "getAuthenticatorId");
// Immediately return a value so the framework can continue with subsequent requests.
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
index 7010d96..775d8d4 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
@@ -646,7 +646,7 @@
final FaceAuthenticationClient client = new FaceAuthenticationClient(mContext,
mLazyDaemon, token, receiver, userId, operationId, restricted, opPackageName,
cookie, false /* requireConfirmation */, mSensorId, isStrongBiometric,
- statsClient, mLockoutTracker, mUsageStats);
+ statsClient, mLockoutTracker, mUsageStats, isKeyguard);
mScheduler.scheduleClientMonitor(client);
});
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
index 9dc8439..0b78dd0 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
@@ -66,12 +66,12 @@
@NonNull LazyDaemon<IBiometricsFace> lazyDaemon, @NonNull IBinder token,
@NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
boolean restricted, String owner, int cookie, boolean requireConfirmation, int sensorId,
- boolean isStrongBiometric, int statsClient,
- @NonNull LockoutTracker lockoutTracker, @NonNull UsageStats usageStats) {
+ boolean isStrongBiometric, int statsClient, @NonNull LockoutTracker lockoutTracker,
+ @NonNull UsageStats usageStats, boolean isKeyguard) {
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */,
- lockoutTracker);
+ lockoutTracker, isKeyguard);
mNotificationManager = context.getSystemService(NotificationManager.class);
mUsageStats = usageStats;
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
index bd57fea..f9527d9 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -30,6 +30,7 @@
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.Utils;
import com.android.server.biometrics.sensors.AuthenticationClient;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.LockoutCache;
@@ -58,11 +59,11 @@
boolean restricted, @NonNull String owner, int cookie, boolean requireConfirmation,
int sensorId, boolean isStrongBiometric, int statsClient,
@Nullable TaskStackListener taskStackListener, @NonNull LockoutCache lockoutCache,
- @Nullable IUdfpsOverlayController udfpsOverlayController) {
+ @Nullable IUdfpsOverlayController udfpsOverlayController, boolean isKeyguard) {
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted, owner,
cookie, requireConfirmation, sensorId, isStrongBiometric,
BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener,
- lockoutCache);
+ lockoutCache, isKeyguard);
mLockoutCache = lockoutCache;
mUdfpsOverlayController = udfpsOverlayController;
}
@@ -87,7 +88,7 @@
@Override
protected void startHalOperation() {
- UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_AUTH,
+ UdfpsHelper.showUdfpsOverlay(getSensorId(), Utils.getUdfpsAuthReason(this),
mUdfpsOverlayController);
try {
mCancellationSignal = getFreshDaemon().authenticate(mSequentialId, mOperationId);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
index b4bb4f8..9611192 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
@@ -70,7 +70,8 @@
@Override
protected void startHalOperation() {
- UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_AUTH,
+ UdfpsHelper.showUdfpsOverlay(getSensorId(),
+ IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD,
mUdfpsOverlayController);
try {
mCancellationSignal = getFreshDaemon().detectInteraction(mSequentialId);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
index 727184f..f845024 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
@@ -466,7 +466,7 @@
operationId, restricted, opPackageName, cookie,
false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient,
mTaskStackListener, mSensors.get(sensorId).getLockoutCache(),
- mUdfpsOverlayController);
+ mUdfpsOverlayController, isKeyguard);
mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
} catch (RemoteException e) {
Slog.e(getTag(), "Remote exception when scheduling authenticate", e);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
index 589db6c..83a3d94 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
@@ -30,6 +30,7 @@
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.Utils;
import com.android.server.biometrics.sensors.AuthenticationClient;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.LockoutTracker;
@@ -48,7 +49,6 @@
private static final String TAG = "Biometrics/FingerprintAuthClient";
- private final boolean mIsKeyguard;
private final LockoutFrameworkImpl mLockoutFrameworkImpl;
@Nullable private final IUdfpsOverlayController mUdfpsOverlayController;
@@ -63,10 +63,9 @@
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener,
- lockoutTracker);
+ lockoutTracker, isKeyguard);
mLockoutFrameworkImpl = lockoutTracker;
mUdfpsOverlayController = udfpsOverlayController;
- mIsKeyguard = isKeyguard;
}
@Override
@@ -120,7 +119,7 @@
@Override
protected void startHalOperation() {
- UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_AUTH,
+ UdfpsHelper.showUdfpsOverlay(getSensorId(), Utils.getUdfpsAuthReason(this),
mUdfpsOverlayController);
try {
// GroupId was never used. In fact, groupId is always the same as userId.
@@ -170,8 +169,4 @@
}
}
}
-
- public boolean isKeyguard() {
- return mIsKeyguard;
- }
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
index 6318139..7989dca 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
@@ -83,7 +83,8 @@
@Override
protected void startHalOperation() {
- UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_AUTH,
+ UdfpsHelper.showUdfpsOverlay(getSensorId(),
+ IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD,
mUdfpsOverlayController);
try {
getFreshDaemon().authenticate(0 /* operationId */, getTargetUserId());
diff --git a/services/core/java/com/android/server/graphics/fonts/FontManagerService.java b/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
index 425e3ab..bda4240 100644
--- a/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
+++ b/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
@@ -23,12 +23,17 @@
import android.graphics.fonts.FontFamily;
import android.graphics.fonts.FontFileUtil;
import android.graphics.fonts.SystemFonts;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
import android.os.SharedMemory;
import android.system.ErrnoException;
import android.text.FontConfig;
+import android.util.IndentingPrintWriter;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.graphics.fonts.IFontManager;
+import com.android.internal.util.DumpUtils;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.security.FileIntegrityService;
@@ -38,6 +43,7 @@
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
+import java.io.PrintWriter;
import java.nio.ByteBuffer;
import java.nio.NioUtils;
import java.nio.channels.FileChannel;
@@ -46,21 +52,25 @@
/** A service for managing system fonts. */
// TODO(b/173619554): Add API to update fonts.
-public final class FontManagerService {
-
+public final class FontManagerService extends IFontManager.Stub {
private static final String TAG = "FontManagerService";
// TODO: make this a DeviceConfig flag.
private static final boolean ENABLE_FONT_UPDATES = false;
private static final String FONT_FILES_DIR = "/data/fonts/files";
+ @Override
+ public FontConfig getFontConfig() throws RemoteException {
+ return getCurrentFontSettings().getSystemFontConfig();
+ }
+
/** Class to manage FontManagerService's lifecycle. */
public static final class Lifecycle extends SystemService {
private final FontManagerService mService;
public Lifecycle(@NonNull Context context) {
super(context);
- mService = new FontManagerService();
+ mService = new FontManagerService(context);
}
@Override
@@ -76,10 +86,11 @@
return mService.getCurrentFontSettings().getSerializedSystemFontMap();
}
});
+ publishBinderService(Context.FONT_SERVICE, mService);
}
}
- private static class OtfFontFileParser implements UpdatableFontDir.FontFileParser {
+ /* package */ static class OtfFontFileParser implements UpdatableFontDir.FontFileParser {
@Override
public String getPostScriptName(File file) throws IOException {
ByteBuffer buffer = mmap(file);
@@ -133,7 +144,8 @@
@Nullable
private SystemFontSettings mCurrentFontSettings = null;
- private FontManagerService() {
+ private FontManagerService(Context context) {
+ mContext = context;
mUpdatableFontDir = createUpdatableFontDir();
}
@@ -148,8 +160,16 @@
new OtfFontFileParser(), new FsverityUtilImpl());
}
+
@NonNull
- private SystemFontSettings getCurrentFontSettings() {
+ private final Context mContext;
+
+ @NonNull
+ public Context getContext() {
+ return mContext;
+ }
+
+ @NonNull /* package */ SystemFontSettings getCurrentFontSettings() {
synchronized (FontManagerService.this) {
if (mCurrentFontSettings == null) {
mCurrentFontSettings = SystemFontSettings.create(mUpdatableFontDir);
@@ -174,7 +194,22 @@
}
}
- private static class SystemFontSettings {
+ @Override
+ public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer,
+ @Nullable String[] args) {
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
+ new FontManagerShellCommand(this).dumpAll(new IndentingPrintWriter(writer, " "));
+ }
+
+ @Override
+ public int handleShellCommand(@NonNull ParcelFileDescriptor in,
+ @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err,
+ @NonNull String[] args) {
+ return new FontManagerShellCommand(this).exec(this,
+ in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(), args);
+ }
+
+ /* package */ static class SystemFontSettings {
private final @NonNull SharedMemory mSerializedSystemFontMap;
private final @NonNull FontConfig mSystemFontConfig;
private final @NonNull Map<String, FontFamily[]> mSystemFallbackMap;
diff --git a/services/core/java/com/android/server/graphics/fonts/FontManagerShellCommand.java b/services/core/java/com/android/server/graphics/fonts/FontManagerShellCommand.java
new file mode 100644
index 0000000..acb5826
--- /dev/null
+++ b/services/core/java/com/android/server/graphics/fonts/FontManagerShellCommand.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2021 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.graphics.fonts;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.graphics.fonts.Font;
+import android.graphics.fonts.FontFamily;
+import android.graphics.fonts.FontVariationAxis;
+import android.os.ShellCommand;
+import android.text.FontConfig;
+import android.util.IndentingPrintWriter;
+
+import com.android.internal.util.DumpUtils;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A shell command implementation of font service.
+ */
+public class FontManagerShellCommand extends ShellCommand {
+ private static final String TAG = "FontManagerShellCommand";
+
+ @NonNull private final FontManagerService mService;
+
+ FontManagerShellCommand(@NonNull FontManagerService service) {
+ mService = service;
+ }
+
+ @Override
+ public int onCommand(String cmd) {
+ return execCommand(this, cmd);
+ }
+
+ @Override
+ public void onHelp() {
+ dumpHelp(getOutPrintWriter());
+ }
+
+ /* package */ void dumpAll(@NonNull IndentingPrintWriter w) {
+ final FontManagerService.SystemFontSettings settings = mService.getCurrentFontSettings();
+ dumpFontConfig(w, settings.getSystemFontConfig());
+ }
+
+ private void dumpSingleFontConfig(
+ @NonNull IndentingPrintWriter w,
+ @NonNull FontConfig.Font font
+ ) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("style = ");
+ sb.append(font.getStyle());
+ sb.append(", path = ");
+ sb.append(font.getFile().getAbsolutePath());
+ if (font.getTtcIndex() != 0) {
+ sb.append(", index = ");
+ sb.append(font.getTtcIndex());
+ }
+ if (!font.getFontVariationSettings().isEmpty()) {
+ sb.append(", axes = ");
+ sb.append(font.getFontVariationSettings());
+ }
+ if (font.getFontFamilyName() != null) {
+ sb.append(", fallback = ");
+ sb.append(font.getFontFamilyName());
+ }
+ w.println(sb.toString());
+
+ if (font.getOriginalFile() != null) {
+ w.increaseIndent();
+ w.println("Font is updated from " + font.getOriginalFile());
+ w.decreaseIndent();
+ }
+ }
+
+ private void dumpFontConfig(
+ @NonNull IndentingPrintWriter w,
+ @NonNull FontConfig fontConfig
+ ) {
+ // Dump named font family first.
+ List<FontConfig.FontFamily> families = fontConfig.getFontFamilies();
+
+ w.println("Named Font Families");
+ w.increaseIndent();
+ for (int i = 0; i < families.size(); ++i) {
+ final FontConfig.FontFamily family = families.get(i);
+
+ // Here, only dump the named family only.
+ if (family.getName() == null) continue;
+
+ w.println("Named Family (" + family.getName() + ")");
+ final List<FontConfig.Font> fonts = family.getFontList();
+ w.increaseIndent();
+ for (int j = 0; j < fonts.size(); ++j) {
+ dumpSingleFontConfig(w, fonts.get(j));
+ }
+ w.decreaseIndent();
+ }
+ w.decreaseIndent();
+
+ // Dump Fallback fonts.
+ w.println("Dump Fallback Families");
+ w.increaseIndent();
+ int c = 0;
+ for (int i = 0; i < families.size(); ++i) {
+ final FontConfig.FontFamily family = families.get(i);
+
+ // Skip named font family since they are already dumped.
+ if (family.getName() != null) continue;
+
+ StringBuilder sb = new StringBuilder("Fallback Family [");
+ sb.append(c++);
+ sb.append("]: lang=\"");
+ sb.append(family.getLocaleList().toLanguageTags());
+ if (family.getVariant() != FontConfig.FontFamily.VARIANT_DEFAULT) {
+ sb.append("\", variant=");
+ switch (family.getVariant()) {
+ case FontConfig.FontFamily.VARIANT_COMPACT:
+ sb.append("Compact");
+ break;
+ case FontConfig.FontFamily.VARIANT_ELEGANT:
+ sb.append("Elegant");
+ break;
+ default:
+ sb.append("Unknown");
+ break;
+ }
+ }
+ w.println(sb.toString());
+
+ final List<FontConfig.Font> fonts = family.getFontList();
+ w.increaseIndent();
+ for (int j = 0; j < fonts.size(); ++j) {
+ dumpSingleFontConfig(w, fonts.get(j));
+ }
+ w.decreaseIndent();
+ }
+ w.decreaseIndent();
+
+ // Dump aliases
+ w.println("Dump Family Aliases");
+ w.increaseIndent();
+ List<FontConfig.Alias> aliases = fontConfig.getAliases();
+ for (int i = 0; i < aliases.size(); ++i) {
+ final FontConfig.Alias alias = aliases.get(i);
+ w.println("alias = " + alias.getName() + ", reference = " + alias.getOriginal()
+ + ", width = " + alias.getWeight());
+ }
+ w.decreaseIndent();
+ }
+
+ private static void dumpHelp(@NonNull PrintWriter w) {
+ w.println("Font service (font) commands");
+ w.println("help");
+ w.println(" Print this help text.");
+ w.println();
+ w.println("dump [family name]");
+ w.println(" Dump all font files in the specified family name.");
+ w.println(" Dump current system font configuration if no family name was specified.");
+ }
+
+ private void dumpFallback(@NonNull IndentingPrintWriter writer,
+ @NonNull FontFamily[] families) {
+ for (FontFamily family : families) {
+ dumpFamily(writer, family);
+ }
+ }
+
+ private void dumpFamily(@NonNull IndentingPrintWriter writer, @NonNull FontFamily family) {
+ StringBuilder sb = new StringBuilder("Family:");
+ if (family.getLangTags() != null) {
+ sb.append(" langTag = ");
+ sb.append(family.getLangTags());
+ }
+ if (family.getVariant() != FontConfig.FontFamily.VARIANT_DEFAULT) {
+ sb.append(" variant = ");
+ switch (family.getVariant()) {
+ case FontConfig.FontFamily.VARIANT_COMPACT:
+ sb.append("Compact");
+ break;
+ case FontConfig.FontFamily.VARIANT_ELEGANT:
+ sb.append("Elegant");
+ break;
+ default:
+ sb.append("UNKNOWN");
+ break;
+ }
+
+ }
+ writer.println(sb.toString());
+ for (int i = 0; i < family.getSize(); ++i) {
+ writer.increaseIndent();
+ try {
+ dumpFont(writer, family.getFont(i));
+ } finally {
+ writer.decreaseIndent();
+ }
+ }
+ }
+
+ private void dumpFont(@NonNull IndentingPrintWriter writer, @NonNull Font font) {
+ File file = font.getFile();
+ StringBuilder sb = new StringBuilder();
+ sb.append(font.getStyle());
+ sb.append(", path = ");
+ sb.append(file == null ? "[Not a file]" : file.getAbsolutePath());
+ if (font.getTtcIndex() != 0) {
+ sb.append(", index = ");
+ sb.append(font.getTtcIndex());
+ }
+ FontVariationAxis[] axes = font.getAxes();
+ if (axes != null && axes.length != 0) {
+ sb.append(", axes = \"");
+ sb.append(FontVariationAxis.toFontVariationSettings(axes));
+ sb.append("\"");
+ }
+ writer.println(sb.toString());
+ }
+
+ private int execCommand(@NonNull ShellCommand shell, @NonNull String cmd) {
+ final Context ctx = mService.getContext();
+ if (cmd == null) {
+ return shell.handleDefaultCommands(null);
+ }
+
+ final FontManagerService.SystemFontSettings settings = mService.getCurrentFontSettings();
+
+ switch (cmd) {
+ case "dump":
+ if (!DumpUtils.checkDumpPermission(ctx, TAG, shell.getErrPrintWriter())) {
+ return 1;
+ }
+ final IndentingPrintWriter writer =
+ new IndentingPrintWriter(shell.getOutPrintWriter(), " ");
+ String nextArg = shell.getNextArg();
+ if (nextArg == null) {
+ dumpFontConfig(writer, settings.getSystemFontConfig());
+ } else {
+ final Map<String, FontFamily[]> fallbackMap = settings.getSystemFallbackMap();
+ FontFamily[] families = fallbackMap.get(nextArg);
+ if (families == null) {
+ writer.println("Font Family \"" + nextArg + "\" not found");
+ } else {
+ dumpFallback(writer, families);
+ }
+ }
+ return 0;
+ default:
+ shell.handleDefaultCommands(cmd);
+ }
+ return 0;
+ }
+}
diff --git a/services/core/java/com/android/server/wm/LaunchParamsController.java b/services/core/java/com/android/server/wm/LaunchParamsController.java
index 35653f9..285145a 100644
--- a/services/core/java/com/android/server/wm/LaunchParamsController.java
+++ b/services/core/java/com/android/server/wm/LaunchParamsController.java
@@ -277,7 +277,8 @@
@interface Phase {}
/**
- * Stops once we are done with preferred display calculation.
+ * Stops once we are done with preferred display calculation. The result returned from this
+ * phase is only guaranteed to have a display area which display is the launch display.
*/
int PHASE_DISPLAY = 0;
@@ -287,9 +288,14 @@
int PHASE_WINDOWING_MODE = 1;
/**
+ * Stops once we are done with display area calculation.
+ */
+ int PHASE_DISPLAY_AREA = 2;
+
+ /**
* Stops once we are done with window bounds calculation.
*/
- int PHASE_BOUNDS = 2;
+ int PHASE_BOUNDS = 3;
/**
* Returns the launch params that the provided activity launch params should be overridden
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index 12f8611..37a73fc 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -89,6 +89,8 @@
private final Rect mTmpStableBounds = new Rect();
private final int[] mTmpDirections = new int[2];
+ private TaskDisplayArea mTmpDisplayArea;
+
private StringBuilder mLogBuilder;
TaskLaunchParamsModifier(ActivityTaskSupervisor supervisor) {
@@ -127,15 +129,15 @@
return RESULT_SKIP;
}
- // STEP 1: Determine the display area to launch the activity/task.
- final TaskDisplayArea taskDisplayArea = getPreferredLaunchTaskDisplayArea(task,
+ // STEP 1: Determine the suggested display area to launch the activity/task.
+ final TaskDisplayArea suggestedDisplayArea = getPreferredLaunchTaskDisplayArea(task,
options, source, currentParams, activity, request);
- outParams.mPreferredTaskDisplayArea = taskDisplayArea;
- // TODO(b/152116619): Update the usages of display to use taskDisplayArea below.
- final DisplayContent display = taskDisplayArea.mDisplayContent;
+ outParams.mPreferredTaskDisplayArea = suggestedDisplayArea;
+ final DisplayContent display = suggestedDisplayArea.mDisplayContent;
if (DEBUG) {
- appendLog("task-display-area=" + outParams.mPreferredTaskDisplayArea
- + " display-area-windowing-mode=" + taskDisplayArea.getWindowingMode());
+ appendLog("display-id=" + display.getDisplayId()
+ + " display-windowing-mode=" + display.getWindowingMode()
+ + " suggested-display-area=" + suggestedDisplayArea);
}
if (phase == PHASE_DISPLAY) {
@@ -204,9 +206,11 @@
// We inherit launch params from previous modifiers or LaunchParamsController if options,
// layout and display conditions are not contradictory to their suggestions. It's important
// to carry over their values because LaunchParamsController doesn't automatically do that.
+ // We only check if display matches because display area can be changed later.
if (!currentParams.isEmpty() && !hasInitialBounds
&& (currentParams.mPreferredTaskDisplayArea == null
- || currentParams.mPreferredTaskDisplayArea == taskDisplayArea)) {
+ || currentParams.mPreferredTaskDisplayArea.getDisplayId()
+ == display.getDisplayId())) {
// Only set windowing mode if display is in freeform. If the display is in fullscreen
// mode we should only launch a task in fullscreen mode.
if (currentParams.hasWindowingMode() && display.inFreeformWindowingMode()) {
@@ -255,14 +259,48 @@
return RESULT_CONTINUE;
}
- // STEP 3: Determine final launch bounds based on resolved windowing mode and activity
+ // STEP 3: Finalize the display area. Here we allow WM shell route all launches that match
+ // certain criteria to specific task display areas.
+ final int resolvedMode = (launchMode != WINDOWING_MODE_UNDEFINED) ? launchMode
+ : display.getWindowingMode();
+ TaskDisplayArea taskDisplayArea = suggestedDisplayArea;
+ // If launch task display area is set in options we should just use it. We assume the
+ // suggestedDisplayArea has the right one in this case.
+ if (options == null || options.getLaunchTaskDisplayArea() == null) {
+ final int activityType =
+ mSupervisor.mRootWindowContainer.resolveActivityType(root, options, task);
+ display.forAllTaskDisplayAreas(displayArea -> {
+ final Task launchRoot = displayArea.getLaunchRootTask(
+ resolvedMode, activityType, null /* ActivityOptions */);
+ if (launchRoot == null) {
+ return false;
+ }
+ mTmpDisplayArea = displayArea;
+ return true;
+ });
+ if (mTmpDisplayArea != null) {
+ taskDisplayArea = mTmpDisplayArea;
+ mTmpDisplayArea = null;
+ appendLog("overridden-display-area=["
+ + WindowConfiguration.activityTypeToString(activityType) + ", "
+ + WindowConfiguration.windowingModeToString(resolvedMode) + ", "
+ + taskDisplayArea + "]");
+ }
+ }
+ appendLog("display-area=" + taskDisplayArea);
+ outParams.mPreferredTaskDisplayArea = taskDisplayArea;
+
+ if (phase == PHASE_DISPLAY_AREA) {
+ return RESULT_CONTINUE;
+ }
+ // TODO(b/152116619): Update the usages of display to use taskDisplayArea below.
+
+ // STEP 4: Determine final launch bounds based on resolved windowing mode and activity
// requested orientation. We set bounds to empty for fullscreen mode and keep bounds as is
// for all other windowing modes that's not freeform mode. One can read comments in
// relevant methods to further understand this step.
//
// We skip making adjustments if the params are fully resolved from previous results.
- final int resolvedMode = (launchMode != WINDOWING_MODE_UNDEFINED) ? launchMode
- : display.getWindowingMode();
if (fullyResolvedCurrentParam) {
if (resolvedMode == WINDOWING_MODE_FREEFORM) {
// Make sure bounds are in the display if it's possibly in a different display/area.
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
index 832f918..90ce6cb 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
@@ -34,7 +34,6 @@
import android.os.Binder;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
-import android.util.proto.ProtoOutputStream;
import androidx.annotation.NonNull;
import androidx.test.InstrumentationRegistry;
@@ -279,7 +278,8 @@
super(context, lazyDaemon, token, listener, 0 /* targetUserId */, 0 /* operationId */,
false /* restricted */, TAG, 1 /* cookie */, false /* requireConfirmation */,
TEST_SENSOR_ID, true /* isStrongBiometric */, 0 /* statsModality */,
- 0 /* statsClient */, null /* taskStackListener */, mock(LockoutTracker.class));
+ 0 /* statsClient */, null /* taskStackListener */, mock(LockoutTracker.class),
+ false /* isKeyguard */);
}
@Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index 9c1e8ed..4984799 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
@@ -32,6 +33,7 @@
import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
+import static android.window.DisplayAreaOrganizer.FEATURE_RUNTIME_TASK_CONTAINER_FIRST;
import static com.android.server.wm.ActivityStarter.Request;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS;
@@ -109,9 +111,9 @@
assertEquals(RESULT_SKIP, new CalculateRequestBuilder().setActivity(null).calculate());
}
- // =============================
- // Display ID Related Tests
- // =============================
+ // =======================
+ // Display Related Tests
+ // =======================
@Test
public void testDefaultToPrimaryDisplayArea() {
createNewDisplayContent(WINDOWING_MODE_FREEFORM);
@@ -287,7 +289,7 @@
when(mActivity.getProcessName()).thenReturn(processName);
when(mActivity.getUid()).thenReturn(uid);
doReturn(controller)
- .when(mSupervisor.mService)
+ .when(mAtm)
.getProcessController(processName, uid);
assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
@@ -308,11 +310,11 @@
when(mActivity.getProcessName()).thenReturn(processName);
when(mActivity.getUid()).thenReturn(uid);
doReturn(null)
- .when(mSupervisor.mService)
+ .when(mAtm)
.getProcessController(processName, uid);
doReturn(controller)
- .when(mSupervisor.mService)
+ .when(mAtm)
.getProcessController(mActivity.launchedFromPid, mActivity.launchedFromUid);
assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
@@ -340,10 +342,10 @@
.thenReturn(expectedTaskDisplayArea);
doReturn(controllerForApplication)
- .when(mSupervisor.mService)
+ .when(mAtm)
.getProcessController(processName, uid);
doReturn(controllerForLaunching)
- .when(mSupervisor.mService)
+ .when(mAtm)
.getProcessController(mActivity.launchedFromPid, mActivity.launchedFromUid);
assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
@@ -365,15 +367,15 @@
when(controller.getTopActivityDisplayArea()).thenReturn(expectedTaskDisplayArea);
doReturn(null)
- .when(mSupervisor.mService)
+ .when(mAtm)
.getProcessController(mActivity.processName, mActivity.info.applicationInfo.uid);
doReturn(null)
- .when(mSupervisor.mService)
+ .when(mAtm)
.getProcessController(mActivity.launchedFromPid, mActivity.launchedFromUid);
doReturn(controller)
- .when(mSupervisor.mService)
+ .when(mAtm)
.getProcessController(request.realCallingPid, request.realCallingUid);
assertEquals(RESULT_CONTINUE,
@@ -385,11 +387,11 @@
@Test
public void testUsesDefaultDisplayAreaIfWindowProcessControllerIsNotPresent() {
doReturn(null)
- .when(mSupervisor.mService)
+ .when(mAtm)
.getProcessController(mActivity.processName, mActivity.info.applicationInfo.uid);
doReturn(null)
- .when(mSupervisor.mService)
+ .when(mAtm)
.getProcessController(mActivity.launchedFromPid, mActivity.launchedFromUid);
assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
@@ -397,6 +399,80 @@
assertEquals(DEFAULT_DISPLAY, mResult.mPreferredTaskDisplayArea.getDisplayId());
}
+ @Test
+ public void testOverridesDisplayAreaWithStandardTypeAndFullscreenMode() {
+ final TaskDisplayArea secondaryDisplayArea = createTaskDisplayArea(mDefaultDisplay,
+ mWm, "SecondaryDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST);
+ final Task launchRoot = createTaskStackOnTaskDisplayArea(WINDOWING_MODE_FULLSCREEN,
+ ACTIVITY_TYPE_STANDARD, secondaryDisplayArea);
+ launchRoot.mCreatedByOrganizer = true;
+
+ secondaryDisplayArea.setLaunchRootTask(launchRoot, new int[] { WINDOWING_MODE_FULLSCREEN },
+ new int[] { ACTIVITY_TYPE_STANDARD });
+
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
+
+ assertEquals(secondaryDisplayArea, mResult.mPreferredTaskDisplayArea);
+ }
+
+ @Test
+ public void testOverridesDisplayAreaWithHomeTypeAndFullscreenMode() {
+ final TaskDisplayArea secondaryDisplayArea = createTaskDisplayArea(mDefaultDisplay,
+ mWm, "SecondaryDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST);
+ final Task launchRoot = createTaskStackOnTaskDisplayArea(WINDOWING_MODE_FULLSCREEN,
+ ACTIVITY_TYPE_STANDARD, secondaryDisplayArea);
+ launchRoot.mCreatedByOrganizer = true;
+
+ mActivity.setActivityType(ACTIVITY_TYPE_HOME);
+ secondaryDisplayArea.setLaunchRootTask(launchRoot, new int[] { WINDOWING_MODE_FULLSCREEN },
+ new int[] { ACTIVITY_TYPE_HOME });
+
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
+
+ assertEquals(secondaryDisplayArea, mResult.mPreferredTaskDisplayArea);
+ }
+
+ @Test
+ public void testOverridesDisplayAreaWithStandardTypeAndFreeformMode() {
+ final TestDisplayContent freeformDisplay = createNewDisplayContent(
+ WINDOWING_MODE_FREEFORM);
+ final TaskDisplayArea secondaryDisplayArea = createTaskDisplayArea(freeformDisplay,
+ mWm, "SecondaryDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST);
+ final Task launchRoot = createTaskStackOnTaskDisplayArea(WINDOWING_MODE_FULLSCREEN,
+ ACTIVITY_TYPE_STANDARD, secondaryDisplayArea);
+ launchRoot.mCreatedByOrganizer = true;
+
+ secondaryDisplayArea.setLaunchRootTask(launchRoot, new int[] { WINDOWING_MODE_FREEFORM },
+ new int[] { ACTIVITY_TYPE_STANDARD });
+
+ mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea();
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
+
+ assertEquals(secondaryDisplayArea, mResult.mPreferredTaskDisplayArea);
+ }
+
+ @Test
+ public void testNotOverrideDisplayAreaWhenActivityOptionsHasDisplayArea() {
+ final TaskDisplayArea secondaryDisplayArea = createTaskDisplayArea(mDefaultDisplay,
+ mWm, "SecondaryDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST);
+ final Task launchRoot = createTaskStackOnTaskDisplayArea(WINDOWING_MODE_FULLSCREEN,
+ ACTIVITY_TYPE_STANDARD, secondaryDisplayArea);
+ launchRoot.mCreatedByOrganizer = true;
+
+ secondaryDisplayArea.setLaunchRootTask(launchRoot, new int[] { WINDOWING_MODE_FULLSCREEN },
+ new int[] { ACTIVITY_TYPE_STANDARD });
+
+ ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchTaskDisplayArea(
+ mDefaultDisplay.getDefaultTaskDisplayArea().mRemoteToken.toWindowContainerToken());
+
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
+
+ assertEquals(
+ mDefaultDisplay.getDefaultTaskDisplayArea(), mResult.mPreferredTaskDisplayArea);
+ }
+
// =====================================
// Launch Windowing Mode Related Tests
// =====================================
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 26de11a..b1e6683 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -1170,6 +1170,12 @@
return "DEVICE_SHUTDOWN";
case Event.DEVICE_STARTUP:
return "DEVICE_STARTUP";
+ case Event.USER_UNLOCKED:
+ return "USER_UNLOCKED";
+ case Event.USER_STOPPED:
+ return "USER_STOPPED";
+ case Event.LOCUS_ID_SET:
+ return "LOCUS_ID_SET";
default:
return "UNKNOWN_TYPE_" + eventType;
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 9f203e1..a5fea34 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -238,7 +238,6 @@
private boolean mSafeMode;
private int mCurUser;
- private boolean mCurUserUnlocked;
private boolean mCurUserSupported;
@GuardedBy("this")
@@ -494,7 +493,6 @@
FgThread.getHandler().post(() -> {
synchronized (this) {
setCurrentUserLocked(userHandle);
- mCurUserUnlocked = false;
switchImplementationIfNeededLocked(false);
}
});
@@ -585,53 +583,43 @@
VoiceInteractionServiceInfo findAvailInteractor(int userHandle, String packageName) {
List<ResolveInfo> available =
mContext.getPackageManager().queryIntentServicesAsUser(
- new Intent(VoiceInteractionService.SERVICE_INTERFACE),
- PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
- | PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userHandle);
+ new Intent(VoiceInteractionService.SERVICE_INTERFACE)
+ .setPackage(packageName),
+ PackageManager.GET_META_DATA
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
int numAvailable = available.size();
-
if (numAvailable == 0) {
Slog.w(TAG, "no available voice interaction services found for user " + userHandle);
return null;
- } else {
- // Find first system package. We never want to allow third party services to
- // be automatically selected, because those require approval of the user.
- VoiceInteractionServiceInfo foundInfo = null;
- for (int i=0; i<numAvailable; i++) {
- ServiceInfo cur = available.get(i).serviceInfo;
- if ((cur.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
- ComponentName comp = new ComponentName(cur.packageName, cur.name);
- try {
- VoiceInteractionServiceInfo info = new VoiceInteractionServiceInfo(
- mContext.getPackageManager(), comp, userHandle);
- if (info.getParseError() == null) {
- if (packageName == null || info.getServiceInfo().packageName.equals(
- packageName)) {
- if (foundInfo == null) {
- foundInfo = info;
- } else {
- Slog.w(TAG, "More than one voice interaction service, "
- + "picking first "
- + new ComponentName(
- foundInfo.getServiceInfo().packageName,
- foundInfo.getServiceInfo().name)
- + " over "
- + new ComponentName(cur.packageName, cur.name));
- }
- }
- } else {
- Slog.w(TAG, "Bad interaction service " + comp + ": "
- + info.getParseError());
- }
- } catch (PackageManager.NameNotFoundException e) {
- Slog.w(TAG, "Failure looking up interaction service " + comp);
- }
- }
- }
-
- return foundInfo;
}
+ // Find first system package. We never want to allow third party services to
+ // be automatically selected, because those require approval of the user.
+ VoiceInteractionServiceInfo foundInfo = null;
+ for (int i = 0; i < numAvailable; i++) {
+ ServiceInfo cur = available.get(i).serviceInfo;
+ if ((cur.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+ continue;
+ }
+ VoiceInteractionServiceInfo info =
+ new VoiceInteractionServiceInfo(mContext.getPackageManager(), cur);
+ if (info.getParseError() != null) {
+ Slog.w(TAG,
+ "Bad interaction service " + cur.packageName + "/"
+ + cur.name + ": " + info.getParseError());
+ } else if (foundInfo == null) {
+ foundInfo = info;
+ } else {
+ Slog.w(TAG, "More than one voice interaction service, "
+ + "picking first "
+ + new ComponentName(
+ foundInfo.getServiceInfo().packageName,
+ foundInfo.getServiceInfo().name)
+ + " over "
+ + new ComponentName(cur.packageName, cur.name));
+ }
+ }
+ return foundInfo;
}
ComponentName getCurInteractor(int userHandle) {
@@ -661,7 +649,6 @@
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
int numAvailable = available.size();
-
if (numAvailable == 0) {
Slog.w(TAG, "no available voice recognition services found for user " + userHandle);
return null;
@@ -1458,7 +1445,6 @@
pw.println(" mEnableService: " + mEnableService);
pw.println(" mTemporarilyDisabled: " + mTemporarilyDisabled);
pw.println(" mCurUser: " + mCurUser);
- pw.println(" mCurUserUnlocked: " + mCurUserUnlocked);
pw.println(" mCurUserSupported: " + mCurUserSupported);
dumpSupportedUsers(pw, " ");
mDbHelper.dump(pw);
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index 03c2ef9..484c318 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -283,6 +283,8 @@
*
* @param cid The identifier of the data call which is provided in {@link DataCallResponse}
* @param callback The result callback for this request.
+ *
+ * @hide
*/
public void startHandover(int cid, @NonNull DataServiceCallback callback) {
// The default implementation is to return unsupported.
@@ -303,6 +305,8 @@
*
* @param cid The identifier of the data call which is provided in {@link DataCallResponse}
* @param callback The result callback for this request.
+ *
+ * @hide
*/
public void cancelHandover(int cid, @NonNull DataServiceCallback callback) {
// The default implementation is to return unsupported.
diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java
index f56c19b..ca1f861 100644
--- a/telephony/java/android/telephony/data/DataServiceCallback.java
+++ b/telephony/java/android/telephony/data/DataServiceCallback.java
@@ -191,6 +191,8 @@
* Called to indicate result for the request {@link DataService#startHandover}.
*
* @param result The result code. Must be one of the {@link ResultCode}
+ *
+ * @hide
*/
public void onHandoverStarted(@ResultCode int result) {
if (mCallback != null) {
@@ -209,6 +211,8 @@
* Called to indicate result for the request {@link DataService#cancelHandover}.
*
* @param result The result code. Must be one of the {@link ResultCode}
+ *
+ * @hide
*/
public void onHandoverCancelled(@ResultCode int result) {
if (mCallback != null) {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
index a625dfd..1d69fe4 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
@@ -16,6 +16,7 @@
package com.android.server.wm.flicker.close
+import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
import androidx.test.platform.app.InstrumentationRegistry
@@ -50,6 +51,7 @@
* Test app closes by pressing back button
* To run this test: `atest FlickerTests:CloseAppBackButtonTest`
*/
+@Presubmit
@RequiresDevice
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@@ -93,7 +95,7 @@
windowManagerTrace {
navBarWindowIsAlwaysVisible()
statusBarWindowIsAlwaysVisible()
- visibleWindowsShownMoreThanOneConsecutiveEntry(bugId = 174635878)
+ visibleWindowsShownMoreThanOneConsecutiveEntry(bugId = 173684672)
launcherReplacesAppWindowAsTopWindow(testApp)
wallpaperWindowBecomesVisible()
@@ -110,7 +112,7 @@
enabled = !configuration.startRotation.isRotated())
navBarLayerIsAlwaysVisible()
statusBarLayerIsAlwaysVisible()
- visibleLayersShownMoreThanOneConsecutiveEntry(bugId = 174635878)
+ visibleLayersShownMoreThanOneConsecutiveEntry(bugId = 173684672)
wallpaperLayerReplacesAppLayer(testApp)
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
index e88b10b..f1d08c2 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
@@ -16,6 +16,7 @@
package com.android.server.wm.flicker.close
+import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
import androidx.test.platform.app.InstrumentationRegistry
@@ -49,6 +50,7 @@
* Test app closes by pressing home button.
* To run this test: `atest FlickerTests:CloseAppHomeButtonTest`
*/
+@Presubmit
@RequiresDevice
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@@ -92,7 +94,7 @@
windowManagerTrace {
navBarWindowIsAlwaysVisible()
statusBarWindowIsAlwaysVisible()
- visibleWindowsShownMoreThanOneConsecutiveEntry(bugId = 174635878)
+ visibleWindowsShownMoreThanOneConsecutiveEntry(bugId = 173689015)
launcherReplacesAppWindowAsTopWindow(testApp)
wallpaperWindowBecomesVisible()
@@ -108,7 +110,7 @@
Surface.ROTATION_0, enabled = isRotation0)
navBarLayerIsAlwaysVisible()
statusBarLayerIsAlwaysVisible()
- visibleLayersShownMoreThanOneConsecutiveEntry(bugId = 174635878)
+ visibleLayersShownMoreThanOneConsecutiveEntry(bugId = 173689015)
wallpaperLayerReplacesAppLayer(testApp)
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
index e47e757..7911119 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
@@ -16,6 +16,7 @@
package com.android.server.wm.flicker.ime
+import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
import androidx.test.platform.app.InstrumentationRegistry
@@ -38,6 +39,7 @@
import com.android.server.wm.flicker.repetitions
import com.android.server.wm.flicker.startRotation
import com.android.server.wm.flicker.endRotation
+import com.android.server.wm.flicker.helpers.isRotated
import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
import com.android.server.wm.flicker.statusBarLayerRotatesScales
import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
@@ -51,6 +53,7 @@
* Test IME window opening transitions.
* To run this test: `atest FlickerTests:ReOpenImeWindowTest`
*/
+@Presubmit
@RequiresDevice
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@@ -109,9 +112,11 @@
layersTrace {
noUncoveredRegions(Surface.ROTATION_0, configuration.endRotation)
navBarLayerRotatesAndScales(Surface.ROTATION_0,
- configuration.endRotation)
+ configuration.endRotation,
+ enabled = !configuration.startRotation.isRotated())
statusBarLayerRotatesScales(Surface.ROTATION_0,
- configuration.endRotation)
+ configuration.endRotation,
+ enabled = !configuration.startRotation.isRotated())
statusBarLayerIsAlwaysVisible()
navBarLayerIsAlwaysVisible()
visibleLayersShownMoreThanOneConsecutiveEntry()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
index 3c8f469..c957b3f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
@@ -16,6 +16,7 @@
package com.android.server.wm.flicker.launch
+import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
import androidx.test.platform.app.InstrumentationRegistry
@@ -52,6 +53,7 @@
* Launch an app from the recents app view (the overview)
* To run this test: `atest FlickerTests:OpenAppFromOverviewTest`
*/
+@Presubmit
@RequiresDevice
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)