Merge "Fix smartspace disappears when unfold the device addViews, removeViews will be called after adding SplitshadeSmartspaceSection" into main
diff --git a/Android.bp b/Android.bp
index f6a9328..b139b7e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -132,6 +132,7 @@
":libcamera_client_aidl",
":libcamera_client_framework_aidl",
":libupdate_engine_aidl",
+ ":libupdate_engine_stable-V2-java-source",
":logd_aidl",
":resourcemanager_aidl",
":storaged_aidl",
diff --git a/core/api/current.txt b/core/api/current.txt
index 5abb92b..c7b921c 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -22102,7 +22102,7 @@
}
@FlaggedApi("android.media.audio.loudness_configurator_api") public class LoudnessCodecConfigurator {
- method @FlaggedApi("android.media.audio.loudness_configurator_api") public void addMediaCodec(@NonNull android.media.MediaCodec);
+ method @FlaggedApi("android.media.audio.loudness_configurator_api") public boolean addMediaCodec(@NonNull android.media.MediaCodec);
method @FlaggedApi("android.media.audio.loudness_configurator_api") @NonNull public static android.media.LoudnessCodecConfigurator create();
method @FlaggedApi("android.media.audio.loudness_configurator_api") @NonNull public static android.media.LoudnessCodecConfigurator create(@NonNull java.util.concurrent.Executor, @NonNull android.media.LoudnessCodecConfigurator.OnLoudnessCodecUpdateListener);
method @FlaggedApi("android.media.audio.loudness_configurator_api") @NonNull public android.os.Bundle getLoudnessCodecParams(@NonNull android.media.AudioTrack, @NonNull android.media.MediaCodec);
@@ -28825,6 +28825,8 @@
method public boolean isSecureNfcEnabled();
method public boolean isSecureNfcSupported();
method @FlaggedApi("android.nfc.enable_nfc_charging") public boolean isWlcEnabled();
+ method @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public void resetDiscoveryTechnology(@NonNull android.app.Activity);
+ method @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public void setDiscoveryTechnology(@NonNull android.app.Activity, int, int);
field public static final String ACTION_ADAPTER_STATE_CHANGED = "android.nfc.action.ADAPTER_STATE_CHANGED";
field public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED";
field @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static final String ACTION_PREFERRED_PAYMENT_CHANGED = "android.nfc.action.PREFERRED_PAYMENT_CHANGED";
@@ -28840,6 +28842,13 @@
field public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence";
field public static final String EXTRA_SECURE_ELEMENT_NAME = "android.nfc.extra.SECURE_ELEMENT_NAME";
field public static final String EXTRA_TAG = "android.nfc.extra.TAG";
+ field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_DISABLE = 0; // 0x0
+ field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_KEEP = -1; // 0xffffffff
+ field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_NFC_PASSIVE_A = 1; // 0x1
+ field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_NFC_PASSIVE_B = 2; // 0x2
+ field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_NFC_PASSIVE_F = 4; // 0x4
+ field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_READER_DISABLE = 0; // 0x0
+ field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_READER_KEEP = -1; // 0xffffffff
field public static final int FLAG_READER_NFC_A = 1; // 0x1
field public static final int FLAG_READER_NFC_B = 2; // 0x2
field public static final int FLAG_READER_NFC_BARCODE = 16; // 0x10
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 014ddd41..705b2ee 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -3481,24 +3481,26 @@
}
mResources = r;
- // only do this if the user already has more than one preferred locale
- if (android.content.res.Flags.defaultLocale()
- && r.getConfiguration().getLocales().size() > 1) {
- LocaleConfig lc;
- if (getUserId() < 0) {
- lc = LocaleConfig.fromContextIgnoringOverride(this);
- } else {
- // This is needed because the app might have locale config overrides that need to
- // be read from disk in order for resources to correctly choose which values to
- // load.
- StrictMode.ThreadPolicy policy = StrictMode.allowThreadDiskReads();
- try {
- lc = new LocaleConfig(this);
- } finally {
- StrictMode.setThreadPolicy(policy);
+ if (r != null) {
+ // only do this if the user already has more than one preferred locale
+ if (android.content.res.Flags.defaultLocale()
+ && r.getConfiguration().getLocales().size() > 1) {
+ LocaleConfig lc;
+ if (getUserId() < 0) {
+ lc = LocaleConfig.fromContextIgnoringOverride(this);
+ } else {
+ // This is needed because the app might have locale config overrides that need
+ // to be read from disk in order for resources to correctly choose which values
+ // to load.
+ StrictMode.ThreadPolicy policy = StrictMode.allowThreadDiskReads();
+ try {
+ lc = new LocaleConfig(this);
+ } finally {
+ StrictMode.setThreadPolicy(policy);
+ }
}
+ mResourcesManager.setLocaleConfig(lc);
}
- mResourcesManager.setLocaleConfig(lc);
}
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 7c52238..ee1d117b 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -4207,7 +4207,9 @@
* new state of quiet mode. This is only sent to registered receivers, not manifest receivers.
*
* <p>This broadcast is similar to {@link #ACTION_MANAGED_PROFILE_AVAILABLE} but functions as a
- * generic broadcast for all profile users.
+ * generic broadcast for all users of type {@link android.os.UserManager#isProfile()}}. In
+ * case of a managed profile, both {@link #ACTION_MANAGED_PROFILE_AVAILABLE} and
+ * {@link #ACTION_PROFILE_AVAILABLE} broadcasts are sent.
*/
@FlaggedApi(FLAG_ALLOW_PRIVATE_PROFILE)
public static final String ACTION_PROFILE_AVAILABLE =
@@ -4221,7 +4223,9 @@
* new state of quiet mode. This is only sent to registered receivers, not manifest receivers.
*
* <p>This broadcast is similar to {@link #ACTION_MANAGED_PROFILE_UNAVAILABLE} but functions as
- * a generic broadcast for all profile users.
+ * a generic broadcast for all users of type {@link android.os.UserManager#isProfile()}}. In
+ * case of a managed profile, both {@link #ACTION_MANAGED_PROFILE_UNAVAILABLE} and
+ * {@link #ACTION_PROFILE_UNAVAILABLE} broadcasts are sent.
*/
@FlaggedApi(FLAG_ALLOW_PRIVATE_PROFILE)
public static final String ACTION_PROFILE_UNAVAILABLE =
diff --git a/core/java/android/hardware/face/FaceAuthenticateOptions.java b/core/java/android/hardware/face/FaceAuthenticateOptions.java
index 1c6de04..518f902a 100644
--- a/core/java/android/hardware/face/FaceAuthenticateOptions.java
+++ b/core/java/android/hardware/face/FaceAuthenticateOptions.java
@@ -261,7 +261,7 @@
* The reason for this operation when requested by the system (sysui),
* otherwise AUTHENTICATE_REASON_UNKNOWN.
*
- * See frameworks/base/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
+ * See packages/SystemUI/src/com/android/systemui/deviceentry/shared/FaceAuthReason.kt
* for more details about each reason.
*/
@DataClass.Generated.Member
@@ -524,7 +524,7 @@
* The reason for this operation when requested by the system (sysui),
* otherwise AUTHENTICATE_REASON_UNKNOWN.
*
- * See frameworks/base/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
+ * See packages/SystemUI/src/com/android/systemui/deviceentry/shared/FaceAuthReason.kt
* for more details about each reason.
*/
@DataClass.Generated.Member
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index 967a0cc..286cf28 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -95,4 +95,6 @@
void registerWlcStateListener(in INfcWlcStateListener listener);
void unregisterWlcStateListener(in INfcWlcStateListener listener);
WlcLDeviceInfo getWlcLDeviceInfo();
+
+ void updateDiscoveryTechnology(IBinder b, int pollFlags, int listenFlags);
}
diff --git a/core/java/android/nfc/INfcCardEmulation.aidl b/core/java/android/nfc/INfcCardEmulation.aidl
index 191385a..f4b4604 100644
--- a/core/java/android/nfc/INfcCardEmulation.aidl
+++ b/core/java/android/nfc/INfcCardEmulation.aidl
@@ -43,4 +43,7 @@
ApduServiceInfo getPreferredPaymentService(int userHandle);
boolean setServiceEnabledForCategoryOther(int userHandle, in ComponentName app, boolean status);
boolean isDefaultPaymentRegistered();
+
+ boolean overrideRoutingTable(int userHandle, String protocol, String technology);
+ boolean recoverRoutingTable(int userHandle);
}
diff --git a/core/java/android/nfc/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java
index 8d75cac..f03fc0a 100644
--- a/core/java/android/nfc/NfcActivityManager.java
+++ b/core/java/android/nfc/NfcActivityManager.java
@@ -112,6 +112,9 @@
Bundle readerModeExtras = null;
Binder token;
+ int mPollTech = NfcAdapter.FLAG_USE_ALL_TECH;
+ int mListenTech = NfcAdapter.FLAG_USE_ALL_TECH;
+
public NfcActivityState(Activity activity) {
if (activity.isDestroyed()) {
throw new IllegalStateException("activity is already destroyed");
@@ -132,6 +135,9 @@
readerModeFlags = 0;
readerModeExtras = null;
token = null;
+
+ mPollTech = NfcAdapter.FLAG_USE_ALL_TECH;
+ mListenTech = NfcAdapter.FLAG_USE_ALL_TECH;
}
@Override
public String toString() {
@@ -278,6 +284,9 @@
int readerModeFlags = 0;
Bundle readerModeExtras = null;
Binder token;
+ int pollTech;
+ int listenTech;
+
synchronized (NfcActivityManager.this) {
NfcActivityState state = findActivityState(activity);
if (DBG) Log.d(TAG, "onResume() for " + activity + " " + state);
@@ -286,9 +295,15 @@
token = state.token;
readerModeFlags = state.readerModeFlags;
readerModeExtras = state.readerModeExtras;
+
+ pollTech = state.mPollTech;
+ listenTech = state.mListenTech;
}
if (readerModeFlags != 0) {
setReaderMode(token, readerModeFlags, readerModeExtras);
+ } else if (listenTech != NfcAdapter.FLAG_USE_ALL_TECH
+ || pollTech != NfcAdapter.FLAG_USE_ALL_TECH) {
+ changeDiscoveryTech(token, pollTech, listenTech);
}
requestNfcServiceCallback();
}
@@ -298,6 +313,9 @@
public void onActivityPaused(Activity activity) {
boolean readerModeFlagsSet;
Binder token;
+ int pollTech;
+ int listenTech;
+
synchronized (NfcActivityManager.this) {
NfcActivityState state = findActivityState(activity);
if (DBG) Log.d(TAG, "onPause() for " + activity + " " + state);
@@ -305,10 +323,17 @@
state.resumed = false;
token = state.token;
readerModeFlagsSet = state.readerModeFlags != 0;
+
+ pollTech = state.mPollTech;
+ listenTech = state.mListenTech;
}
if (readerModeFlagsSet) {
// Restore default p2p modes
setReaderMode(token, 0, null);
+ } else if (listenTech != NfcAdapter.FLAG_USE_ALL_TECH
+ || pollTech != NfcAdapter.FLAG_USE_ALL_TECH) {
+ changeDiscoveryTech(token,
+ NfcAdapter.FLAG_USE_ALL_TECH, NfcAdapter.FLAG_USE_ALL_TECH);
}
}
@@ -333,4 +358,53 @@
}
}
+ /** setDiscoveryTechnology() implementation */
+ public void setDiscoveryTech(Activity activity, int pollTech, int listenTech) {
+ boolean isResumed;
+ Binder token;
+ boolean readerModeFlagsSet;
+ synchronized (NfcActivityManager.this) {
+ NfcActivityState state = getActivityState(activity);
+ readerModeFlagsSet = state.readerModeFlags != 0;
+ state.mListenTech = listenTech;
+ state.mPollTech = pollTech;
+ token = state.token;
+ isResumed = state.resumed;
+ }
+ if (!readerModeFlagsSet && isResumed) {
+ changeDiscoveryTech(token, pollTech, listenTech);
+ } else if (readerModeFlagsSet) {
+ throw new IllegalStateException("Cannot be used when the Reader Mode is enabled");
+ }
+ }
+
+ /** resetDiscoveryTechnology() implementation */
+ public void resetDiscoveryTech(Activity activity) {
+ boolean isResumed;
+ Binder token;
+ boolean readerModeFlagsSet;
+ synchronized (NfcActivityManager.this) {
+ NfcActivityState state = getActivityState(activity);
+ readerModeFlagsSet = state.readerModeFlags != 0;
+ state.mListenTech = NfcAdapter.FLAG_USE_ALL_TECH;
+ state.mPollTech = NfcAdapter.FLAG_USE_ALL_TECH;
+ token = state.token;
+ isResumed = state.resumed;
+ }
+ if (readerModeFlagsSet) {
+ disableReaderMode(activity);
+ } else if (isResumed) {
+ changeDiscoveryTech(token, NfcAdapter.FLAG_USE_ALL_TECH, NfcAdapter.FLAG_USE_ALL_TECH);
+ }
+
+ }
+
+ private void changeDiscoveryTech(Binder token, int pollTech, int listenTech) {
+ try {
+ NfcAdapter.sService.updateDiscoveryTechnology(token, pollTech, listenTech);
+ } catch (RemoteException e) {
+ mAdapter.attemptDeadServiceRecovery(e);
+ }
+ }
+
}
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 21e23ae..5a40e42 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -333,6 +333,19 @@
*/
public static final int FLAG_READER_NFC_BARCODE = 0x10;
+ /** @hide */
+ @IntDef(flag = true, prefix = {"FLAG_READER_"}, value = {
+ FLAG_READER_KEEP,
+ FLAG_READER_DISABLE,
+ FLAG_READER_NFC_A,
+ FLAG_READER_NFC_B,
+ FLAG_READER_NFC_F,
+ FLAG_READER_NFC_V,
+ FLAG_READER_NFC_BARCODE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PollTechnology {}
+
/**
* Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
* <p>
@@ -360,6 +373,76 @@
public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence";
/**
+ * Flag for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
+ * <p>
+ * Setting this flag enables listening for Nfc-A technology.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public static final int FLAG_LISTEN_NFC_PASSIVE_A = 0x1;
+
+ /**
+ * Flag for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
+ * <p>
+ * Setting this flag enables listening for Nfc-B technology.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public static final int FLAG_LISTEN_NFC_PASSIVE_B = 1 << 1;
+
+ /**
+ * Flag for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
+ * <p>
+ * Setting this flag enables listening for Nfc-F technology.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public static final int FLAG_LISTEN_NFC_PASSIVE_F = 1 << 2;
+
+ /**
+ * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
+ * <p>
+ * Setting this flag disables listening.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public static final int FLAG_LISTEN_DISABLE = 0x0;
+
+ /**
+ * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
+ * <p>
+ * Setting this flag disables polling.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public static final int FLAG_READER_DISABLE = 0x0;
+
+ /**
+ * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
+ * <p>
+ * Setting this flag makes listening to use current flags.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public static final int FLAG_LISTEN_KEEP = -1;
+
+ /**
+ * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
+ * <p>
+ * Setting this flag makes polling to use current flags.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public static final int FLAG_READER_KEEP = -1;
+
+ /** @hide */
+ public static final int FLAG_USE_ALL_TECH = 0xff;
+
+ /** @hide */
+ @IntDef(flag = true, prefix = {"FLAG_LISTEN_"}, value = {
+ FLAG_LISTEN_KEEP,
+ FLAG_LISTEN_DISABLE,
+ FLAG_LISTEN_NFC_PASSIVE_A,
+ FLAG_LISTEN_NFC_PASSIVE_B,
+ FLAG_LISTEN_NFC_PASSIVE_F
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ListenTechnology {}
+
+ /**
* @hide
* @removed
*/
@@ -437,12 +520,14 @@
@Retention(RetentionPolicy.SOURCE)
public @interface TagIntentAppPreferenceResult {}
- // Guarded by NfcAdapter.class
+ // Guarded by sLock
static boolean sIsInitialized = false;
static boolean sHasNfcFeature;
static boolean sHasCeFeature;
static boolean sHasNfcWlcFeature;
+ static Object sLock = new Object();
+
// Final after first constructor, except for
// attemptDeadServiceRecovery() when NFC crashes - we accept a best effort
// recovery
@@ -1235,7 +1320,7 @@
@java.lang.Deprecated
@UnsupportedAppUsage
public void setBeamPushUris(Uri[] uris, Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1305,7 +1390,7 @@
@java.lang.Deprecated
@UnsupportedAppUsage
public void setBeamPushUrisCallback(CreateBeamUrisCallback callback, Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1390,7 +1475,7 @@
@UnsupportedAppUsage
public void setNdefPushMessage(NdefMessage message, Activity activity,
Activity ... activities) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1404,7 +1489,7 @@
@SystemApi
@UnsupportedAppUsage
public void setNdefPushMessage(NdefMessage message, Activity activity, int flags) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1483,7 +1568,7 @@
@UnsupportedAppUsage
public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity,
Activity ... activities) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1534,7 +1619,7 @@
@UnsupportedAppUsage
public void setOnNdefPushCompleteCallback(OnNdefPushCompleteCallback callback,
Activity activity, Activity ... activities) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1577,7 +1662,7 @@
*/
public void enableForegroundDispatch(Activity activity, PendingIntent intent,
IntentFilter[] filters, String[][] techLists) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1612,7 +1697,7 @@
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
*/
public void disableForegroundDispatch(Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1648,7 +1733,7 @@
*/
public void enableReaderMode(Activity activity, ReaderCallback callback, int flags,
Bundle extras) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1665,7 +1750,7 @@
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
*/
public void disableReaderMode(Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1693,7 +1778,7 @@
@FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
@SuppressLint("VisiblySynchronized")
public void setReaderMode(boolean enablePolling) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1708,6 +1793,80 @@
}
/**
+ * Set the NFC controller to enable specific poll/listen technologies,
+ * as specified in parameters, while this Activity is in the foreground.
+ *
+ * Use {@link #FLAG_READER_KEEP} to keep current polling technology.
+ * Use {@link #FLAG_LISTEN_KEEP} to keep current listenig technology.
+ * Use {@link #FLAG_READER_DISABLE} to disable polling.
+ * Use {@link #FLAG_LISTEN_DISABLE} to disable listening.
+ * Also refer to {@link #resetDiscoveryTechnology(Activity)} to restore these changes.
+ * </p>
+ * The pollTech, listenTech parameters can be one or several of below list.
+ * <pre>
+ * Poll Listen
+ * Passive A 0x01 (NFC_A) 0x01 (NFC_PASSIVE_A)
+ * Passive B 0x02 (NFC_B) 0x02 (NFC_PASSIVE_B)
+ * Passive F 0x04 (NFC_F) 0x04 (NFC_PASSIVE_F)
+ * ISO 15693 0x08 (NFC_V) -
+ * Kovio 0x10 (NFC_BARCODE) -
+ * </pre>
+ * <p>Example usage in an Activity that requires to disable poll,
+ * keep current listen technologies:
+ * <pre>
+ * protected void onResume() {
+ * mNfcAdapter = NfcAdapter.getDefaultAdapter(getApplicationContext());
+ * mNfcAdapter.setDiscoveryTechnology(this,
+ * NfcAdapter.FLAG_READER_DISABLE, NfcAdapter.FLAG_LISTEN_KEEP);
+ * }</pre></p>
+ * @param activity The Activity that requests NFC controller to enable specific technologies.
+ * @param pollTech Flags indicating poll technologies.
+ * @param listenTech Flags indicating listen technologies.
+ * @throws UnsupportedOperationException if FEATURE_NFC,
+ * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF are unavailable.
+ */
+
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public void setDiscoveryTechnology(@NonNull Activity activity,
+ @PollTechnology int pollTech, @ListenTechnology int listenTech) {
+ if (listenTech == FLAG_LISTEN_DISABLE) {
+ synchronized (sLock) {
+ if (!sHasNfcFeature) {
+ throw new UnsupportedOperationException();
+ }
+ }
+ mNfcActivityManager.enableReaderMode(activity, null, pollTech, null);
+ return;
+ }
+ if (pollTech == FLAG_READER_DISABLE) {
+ synchronized (sLock) {
+ if (!sHasCeFeature) {
+ throw new UnsupportedOperationException();
+ }
+ }
+ } else {
+ synchronized (sLock) {
+ if (!sHasNfcFeature || !sHasCeFeature) {
+ throw new UnsupportedOperationException();
+ }
+ }
+ }
+ mNfcActivityManager.setDiscoveryTech(activity, pollTech, listenTech);
+ }
+
+ /**
+ * Restore the poll/listen technologies of NFC controller,
+ * which were changed by {@link #setDiscoveryTechnology(Activity , int , int)}
+ *
+ * @param activity The Activity that requests to changed technologies.
+ */
+
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public void resetDiscoveryTechnology(@NonNull Activity activity) {
+ mNfcActivityManager.resetDiscoveryTech(activity);
+ }
+
+ /**
* Manually invoke Android Beam to share data.
*
* <p>The Android Beam animation is normally only shown when two NFC-capable
@@ -1737,7 +1896,7 @@
@java.lang.Deprecated
@UnsupportedAppUsage
public boolean invokeBeam(Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1775,7 +1934,7 @@
@Deprecated
@UnsupportedAppUsage
public void enableForegroundNdefPush(Activity activity, NdefMessage message) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1805,7 +1964,7 @@
@Deprecated
@UnsupportedAppUsage
public void disableForegroundNdefPush(Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -2085,7 +2244,7 @@
@java.lang.Deprecated
@UnsupportedAppUsage
public boolean isNdefPushEnabled() {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -2199,7 +2358,7 @@
@RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
public boolean addNfcUnlockHandler(final NfcUnlockHandler unlockHandler,
String[] tagTechnologies) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -2248,7 +2407,7 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
public boolean removeNfcUnlockHandler(NfcUnlockHandler unlockHandler) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index 58b6179..ad86d70 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -998,6 +998,87 @@
}
}
+ /**
+ * Setting NFC controller routing table, which includes Protocol Route and Technology Route,
+ * while this Activity is in the foreground.
+ *
+ * The parameter set to null can be used to keep current values for that entry.
+ * <p>
+ * Example usage in an Activity that requires to set proto route to "ESE" and keep tech route:
+ * <pre>
+ * protected void onResume() {
+ * mNfcAdapter.overrideRoutingTable(this , "ESE" , null);
+ * }</pre>
+ * </p>
+ * Also activities must call this method when it goes to the background,
+ * with all parameters set to null.
+ * @param activity The Activity that requests NFC controller routing table to be changed.
+ * @param protocol ISO-DEP route destination, which can be "DH" or "UICC" or "ESE".
+ * @param technology Tech-A, Tech-B route destination, which can be "DH" or "UICC" or "ESE".
+ * @return true if operation is successful and false otherwise
+ *
+ * This is a high risk API and only included to support mainline effort
+ * @hide
+ */
+ public boolean overrideRoutingTable(Activity activity, String protocol, String technology) {
+ if (activity == null) {
+ throw new NullPointerException("activity or service or category is null");
+ }
+ if (!activity.isResumed()) {
+ throw new IllegalArgumentException("Activity must be resumed.");
+ }
+ try {
+ return sService.overrideRoutingTable(UserHandle.myUserId(), protocol, technology);
+ } catch (RemoteException e) {
+ // Try one more time
+ recoverService();
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return false;
+ }
+ try {
+ return sService.overrideRoutingTable(UserHandle.myUserId(), protocol, technology);
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to reach CardEmulationService.");
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Restore the NFC controller routing table,
+ * which was changed by {@link #overrideRoutingTable(Activity, String, String)}
+ *
+ * @param activity The Activity that requested NFC controller routing table to be changed.
+ * @return true if operation is successful and false otherwise
+ *
+ * @hide
+ */
+ public boolean recoverRoutingTable(Activity activity) {
+ if (activity == null) {
+ throw new NullPointerException("activity is null");
+ }
+ if (!activity.isResumed()) {
+ throw new IllegalArgumentException("Activity must be resumed.");
+ }
+ try {
+ return sService.recoverRoutingTable(UserHandle.myUserId());
+ } catch (RemoteException e) {
+ // Try one more time
+ recoverService();
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return false;
+ }
+ try {
+ return sService.recoverRoutingTable(UserHandle.myUserId());
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to reach CardEmulationService.");
+ return false;
+ }
+ }
+ }
+
void recoverService() {
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
sService = adapter.getCardEmulationService();
diff --git a/core/java/android/nfc/flags.aconfig b/core/java/android/nfc/flags.aconfig
index ce4f777..01a4570 100644
--- a/core/java/android/nfc/flags.aconfig
+++ b/core/java/android/nfc/flags.aconfig
@@ -62,3 +62,10 @@
description: "Flag for NFC charging changes"
bug: "292143899"
}
+
+flag {
+ name: "enable_nfc_set_discovery_tech"
+ namespace: "nfc"
+ description: "Flag for NFC set discovery tech API"
+ bug: "300351519"
+}
diff --git a/core/java/android/os/UpdateEngineStable.java b/core/java/android/os/UpdateEngineStable.java
new file mode 100644
index 0000000..9e2593e
--- /dev/null
+++ b/core/java/android/os/UpdateEngineStable.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.annotation.IntDef;
+
+/**
+ * UpdateEngineStable handles calls to the update engine stalbe which takes care of A/B OTA updates.
+ * This interface has lesser functionalities than UpdateEngine and doesn't allow cancel.
+ *
+ * <p>The minimal flow is:
+ *
+ * <ol>
+ * <li>Create a new UpdateEngineStable instance.
+ * <li>Call {@link #bind}, provide callback function.
+ * <li>Call {@link #applyPayloadFd}.
+ * </ol>
+ *
+ * The APIs defined in this class and UpdateEngineStableCallback class must be in sync with the ones
+ * in {@code system/update_engine/stable/android/os/IUpdateEngineStable.aidl} and {@code
+ * ssystem/update_engine/stable/android/os/IUpdateEngineStableCallback.aidl}.
+ *
+ * @hide
+ */
+public class UpdateEngineStable {
+ private static final String TAG = "UpdateEngineStable";
+
+ private static final String UPDATE_ENGINE_STABLE_SERVICE =
+ "android.os.UpdateEngineStableService";
+
+ /**
+ * Error codes from update engine upon finishing a call to {@link applyPayloadFd}. Values will
+ * be passed via the callback function {@link
+ * UpdateEngineStableCallback#onPayloadApplicationComplete}. Values must agree with the ones in
+ * {@code system/update_engine/common/error_code.h}.
+ */
+ /** @hide */
+ @IntDef(
+ value = {
+ UpdateEngine.ErrorCodeConstants.SUCCESS,
+ UpdateEngine.ErrorCodeConstants.ERROR,
+ UpdateEngine.ErrorCodeConstants.FILESYSTEM_COPIER_ERROR,
+ UpdateEngine.ErrorCodeConstants.POST_INSTALL_RUNNER_ERROR,
+ UpdateEngine.ErrorCodeConstants.PAYLOAD_MISMATCHED_TYPE_ERROR,
+ UpdateEngine.ErrorCodeConstants.INSTALL_DEVICE_OPEN_ERROR,
+ UpdateEngine.ErrorCodeConstants.KERNEL_DEVICE_OPEN_ERROR,
+ UpdateEngine.ErrorCodeConstants.DOWNLOAD_TRANSFER_ERROR,
+ UpdateEngine.ErrorCodeConstants.PAYLOAD_HASH_MISMATCH_ERROR,
+ UpdateEngine.ErrorCodeConstants.PAYLOAD_SIZE_MISMATCH_ERROR,
+ UpdateEngine.ErrorCodeConstants.DOWNLOAD_PAYLOAD_VERIFICATION_ERROR,
+ UpdateEngine.ErrorCodeConstants.PAYLOAD_TIMESTAMP_ERROR,
+ UpdateEngine.ErrorCodeConstants.UPDATED_BUT_NOT_ACTIVE,
+ UpdateEngine.ErrorCodeConstants.NOT_ENOUGH_SPACE,
+ UpdateEngine.ErrorCodeConstants.DEVICE_CORRUPTED,
+ })
+ public @interface ErrorCode {}
+
+ private final IUpdateEngineStable mUpdateEngineStable;
+ private IUpdateEngineStableCallback mUpdateEngineStableCallback = null;
+ private final Object mUpdateEngineStableCallbackLock = new Object();
+
+ /**
+ * Creates a new instance.
+ *
+ * @hide
+ */
+ public UpdateEngineStable() {
+ mUpdateEngineStable =
+ IUpdateEngineStable.Stub.asInterface(
+ ServiceManager.getService(UPDATE_ENGINE_STABLE_SERVICE));
+ if (mUpdateEngineStable == null) {
+ throw new IllegalStateException("Failed to find " + UPDATE_ENGINE_STABLE_SERVICE);
+ }
+ }
+
+ /**
+ * Prepares this instance for use. The callback will be notified on any status change, and when
+ * the update completes. A handler can be supplied to control which thread runs the callback, or
+ * null.
+ *
+ * @hide
+ */
+ public boolean bind(final UpdateEngineStableCallback callback, final Handler handler) {
+ synchronized (mUpdateEngineStableCallbackLock) {
+ mUpdateEngineStableCallback =
+ new IUpdateEngineStableCallback.Stub() {
+ @Override
+ public void onStatusUpdate(final int status, final float percent) {
+ if (handler != null) {
+ handler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ callback.onStatusUpdate(status, percent);
+ }
+ });
+ } else {
+ callback.onStatusUpdate(status, percent);
+ }
+ }
+
+ @Override
+ public void onPayloadApplicationComplete(final int errorCode) {
+ if (handler != null) {
+ handler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ callback.onPayloadApplicationComplete(errorCode);
+ }
+ });
+ } else {
+ callback.onPayloadApplicationComplete(errorCode);
+ }
+ }
+
+ @Override
+ public int getInterfaceVersion() {
+ return super.VERSION;
+ }
+
+ @Override
+ public String getInterfaceHash() {
+ return super.HASH;
+ }
+ };
+
+ try {
+ return mUpdateEngineStable.bind(mUpdateEngineStableCallback);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * Equivalent to {@code bind(callback, null)}.
+ *
+ * @hide
+ */
+ public boolean bind(final UpdateEngineStableCallback callback) {
+ return bind(callback, null);
+ }
+
+ /**
+ * Applies payload from given ParcelFileDescriptor. Usage is same as UpdateEngine#applyPayload
+ *
+ * @hide
+ */
+ public void applyPayloadFd(
+ ParcelFileDescriptor fd, long offset, long size, String[] headerKeyValuePairs) {
+ try {
+ mUpdateEngineStable.applyPayloadFd(fd, offset, size, headerKeyValuePairs);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Unbinds the last bound callback function.
+ *
+ * @hide
+ */
+ public boolean unbind() {
+ synchronized (mUpdateEngineStableCallbackLock) {
+ if (mUpdateEngineStableCallback == null) {
+ return true;
+ }
+ try {
+ boolean result = mUpdateEngineStable.unbind(mUpdateEngineStableCallback);
+ mUpdateEngineStableCallback = null;
+ return result;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+}
diff --git a/core/java/android/os/UpdateEngineStableCallback.java b/core/java/android/os/UpdateEngineStableCallback.java
new file mode 100644
index 0000000..4bcfb4b
--- /dev/null
+++ b/core/java/android/os/UpdateEngineStableCallback.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+/**
+ * Callback function for UpdateEngineStable. Used to keep the caller up to date with progress, so
+ * the UI (if any) can be updated.
+ *
+ * <p>The APIs defined in this class and UpdateEngineStable class must be in sync with the ones in
+ * system/update_engine/stable/android/os/IUpdateEngineStable.aidl and
+ * system/update_engine/stable/android/os/IUpdateEngineStableCallback.aidl.
+ *
+ * <p>{@hide}
+ */
+public abstract class UpdateEngineStableCallback {
+
+ /**
+ * Invoked when anything changes. The value of {@code status} will be one of the values from
+ * {@link UpdateEngine.UpdateStatusConstants}, and {@code percent} will be valid
+ *
+ * @hide
+ */
+ public abstract void onStatusUpdate(int status, float percent);
+
+ /**
+ * Invoked when the payload has been applied, whether successfully or unsuccessfully. The value
+ * of {@code errorCode} will be one of the values from {@link UpdateEngine.ErrorCodeConstants}.
+ *
+ * @hide
+ */
+ public abstract void onPayloadApplicationComplete(@UpdateEngineStable.ErrorCode int errorCode);
+}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 54cc5f4..84fddcb 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7428,6 +7428,20 @@
public static final String DEFAULT_INPUT_METHOD = "default_input_method";
/**
+ * Used only by {@link com.android.server.inputmethod.InputMethodManagerService} as a
+ * temporary data store of {@link #DEFAULT_INPUT_METHOD} while a virtual-device-specific
+ * input method is set as default.</p>
+ *
+ * <p>This should be considered to be an implementation detail of
+ * {@link com.android.server.inputmethod.InputMethodManagerService}. Other system
+ * components should never rely on this value.</p>
+ *
+ * @see #DEFAULT_INPUT_METHOD
+ * @hide
+ */
+ public static final String DEFAULT_DEVICE_INPUT_METHOD = "default_device_input_method";
+
+ /**
* Setting to record the input method subtype used by default, holding the ID
* of the desired method.
*/
@@ -14347,6 +14361,19 @@
"mute_alarm_stream_with_ringer_mode";
/**
+ * The user's choice for whether or not Alarm stream should always be muted with Ringer.
+ *
+ * <p>Note that this is different from {@link #MUTE_ALARM_STREAM_WITH_RINGER_MODE}, which
+ * controls the real state of whether or not the Alarm stream and Ringer association occurs.
+ * The two Settings are not necessarily equal, if the final decision for the association
+ * depends on factors beyond the user's preference.
+ *
+ * @hide
+ */
+ public static final String MUTE_ALARM_STREAM_WITH_RINGER_MODE_USER_PREFERENCE =
+ "mute_alarm_stream_with_ringer_mode_user_preference";
+
+ /**
* Overlay display devices setting.
* The associated value is a specially formatted string that describes the
* size and density of simulated secondary display devices.
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index e4af2da..d47ff2e 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -368,11 +368,13 @@
* <p>
* As of Android 11 apps will need specific permission to query other packages. To use
* this method an app must include in their AndroidManifest:
+ * <pre>{@code
* <queries>
* <intent>
* <action android:name="android.provider.Telephony.SMS_DELIVER"/>
* </intent>
* </queries>
+ * }</pre>
* Which will allow them to query packages which declare intent filters that include
* the {@link android.provider.Telephony.Sms.Intents#SMS_DELIVER_ACTION} intent.
* </p>
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 692dad4..1a2be15 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -1439,12 +1439,12 @@
// to make sure the wallpaper is stopped even after the events
// onSurfaceCreated() and onSurfaceChanged().
if (noConsecutiveVisibilityEvents()) {
- if (DEBUG) Log.v(TAG, "toggling doVisibilityChanged");
- Trace.beginSection("WPMS.Engine.doVisibilityChanged-true");
- doVisibilityChanged(true);
+ if (DEBUG) Log.v(TAG, "toggling onVisibilityChanged");
+ Trace.beginSection("WPMS.Engine.onVisibilityChanged-true");
+ onVisibilityChanged(true);
Trace.endSection();
- Trace.beginSection("WPMS.Engine.doVisibilityChanged-false");
- doVisibilityChanged(false);
+ Trace.beginSection("WPMS.Engine.onVisibilityChanged-false");
+ onVisibilityChanged(false);
Trace.endSection();
} else {
if (DEBUG) {
diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig
index 216acdc..3366a7e 100644
--- a/core/java/android/window/flags/windowing_frontend.aconfig
+++ b/core/java/android/window/flags/windowing_frontend.aconfig
@@ -38,6 +38,14 @@
}
flag {
+ name: "draw_magnifier_border_outside_wmlock"
+ namespace: "windowing_frontend"
+ description: "Avoid holding WM locks for a long time when executing lockCanvas"
+ bug: "316075123"
+ is_fixed_read_only: true
+}
+
+flag {
name: "introduce_smoother_dimmer"
namespace: "windowing_frontend"
description: "Refactor dim to fix flickers"
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 65597de..066f38b 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -819,14 +819,20 @@
Log.e(TAG, "onTaskFragmentParentInfoChanged on empty Task id=" + taskId);
return;
}
+ // Checks if container should be updated before apply new parentInfo.
+ final boolean shouldUpdateContainer = taskContainer.shouldUpdateContainer(parentInfo);
taskContainer.updateTaskFragmentParentInfo(parentInfo);
if (!taskContainer.isVisible()) {
// Don't update containers if the task is not visible. We only update containers when
// parentInfo#isVisibleRequested is true.
return;
}
- if (isInPictureInPicture(parentInfo.getConfiguration())) {
- // No need to update presentation in PIP until the Task exit PIP.
+
+ // If the last direct activity of the host task is dismissed and the overlay container is
+ // the only taskFragment, the overlay container should also be dismissed.
+ dismissOverlayContainerIfNeeded(wct, taskContainer);
+
+ if (!shouldUpdateContainer) {
return;
}
updateContainersInTask(wct, taskContainer);
@@ -1947,11 +1953,8 @@
void updateOverlayContainer(@NonNull WindowContainerTransaction wct,
@NonNull TaskFragmentContainer container) {
final TaskContainer taskContainer = container.getTaskContainer();
- // Dismiss the overlay container if it's the only container in the task and there's no
- // direct activity in the parent task.
- if (taskContainer.getTaskFragmentContainers().size() == 1
- && !taskContainer.hasDirectActivity()) {
- container.finish(false /* shouldFinishDependent */, mPresenter, wct, this);
+
+ if (dismissOverlayContainerIfNeeded(wct, taskContainer)) {
return;
}
@@ -1968,6 +1971,24 @@
}
}
+ /** Dismisses the overlay container in the {@code taskContainer} if needed. */
+ @GuardedBy("mLock")
+ private boolean dismissOverlayContainerIfNeeded(@NonNull WindowContainerTransaction wct,
+ @NonNull TaskContainer taskContainer) {
+ final TaskFragmentContainer overlayContainer = taskContainer.getOverlayContainer();
+ if (overlayContainer == null) {
+ return false;
+ }
+ // Dismiss the overlay container if it's the only container in the task and there's no
+ // direct activity in the parent task.
+ if (taskContainer.getTaskFragmentContainers().size() == 1
+ && !taskContainer.hasDirectActivity()) {
+ mPresenter.cleanupContainer(wct, overlayContainer, false /* shouldFinishDependant */);
+ return true;
+ }
+ return false;
+ }
+
/**
* Updates {@link SplitContainer} with the given {@link SplitAttributes} if the
* {@link SplitContainer} is the top most and not finished. If passed {@link SplitAttributes}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
index 64ad4fa..71195b6 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -138,6 +138,21 @@
}
/**
+ * Returns {@code true} if the container should be updated with {@code info}.
+ */
+ boolean shouldUpdateContainer(@NonNull TaskFragmentParentInfo info) {
+ final Configuration configuration = info.getConfiguration();
+
+ return info.isVisible()
+ // No need to update presentation in PIP until the Task exit PIP.
+ && !isInPictureInPicture(configuration)
+ // If the task properties equals regardless of starting position, don't need to
+ // update the container.
+ && (mConfiguration.diffPublicOnly(configuration) != 0
+ || mDisplayId != info.getDisplayId());
+ }
+
+ /**
* Returns the windowing mode for the TaskFragments below this Task, which should be split with
* other TaskFragments.
*
@@ -161,7 +176,11 @@
}
boolean isInPictureInPicture() {
- return getWindowingMode() == WINDOWING_MODE_PINNED;
+ return isInPictureInPicture(mConfiguration);
+ }
+
+ private static boolean isInPictureInPicture(@NonNull Configuration configuration) {
+ return configuration.windowConfiguration.getWindowingMode() == WINDOWING_MODE_PINNED;
}
boolean isInMultiWindow() {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
index b52971a..6fe8e50 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
@@ -616,6 +616,9 @@
* Removes all activities that belong to this process and finishes other containers/activities
* configured to finish together.
*/
+ // Suppress GuardedBy warning because lint ask to mark this method as
+ // @GuardedBy(container.mController.mLock), which is mLock itself
+ @SuppressWarnings("GuardedBy")
@GuardedBy("mController.mLock")
void finish(boolean shouldFinishDependent, @NonNull SplitPresenter presenter,
@NonNull WindowContainerTransaction wct, @NonNull SplitController controller) {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TransactionManager.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TransactionManager.java
index 396956e..6624c70 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TransactionManager.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TransactionManager.java
@@ -77,9 +77,11 @@
@NonNull
TransactionRecord startNewTransaction(@Nullable IBinder taskFragmentTransactionToken) {
if (mCurrentTransaction != null) {
+ final TransactionRecord lastTransaction = mCurrentTransaction;
mCurrentTransaction = null;
throw new IllegalStateException(
- "The previous transaction has not been applied or aborted,");
+ "The previous transaction:" + lastTransaction + " has not been applied or "
+ + "aborted.");
}
mCurrentTransaction = new TransactionRecord(taskFragmentTransactionToken);
return mCurrentTransaction;
@@ -199,5 +201,15 @@
? mOriginType
: TASK_FRAGMENT_TRANSIT_CHANGE;
}
+
+ @Override
+ @NonNull
+ public String toString() {
+ return TransactionRecord.class.getSimpleName() + "{"
+ + "token=" + mTaskFragmentTransactionToken
+ + ", type=" + getTransactionTransitionType()
+ + ", transaction=" + mTransaction
+ + "}";
+ }
}
}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
index 5ef6a52..bc92101 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
@@ -472,6 +472,29 @@
verify(mSplitPresenter).applyActivityStackAttributes(any(), eq(container), eq(attrs));
}
+ @Test
+ public void testOnTaskFragmentParentInfoChanged_positionOnlyChange_earlyReturn() {
+ final TaskFragmentContainer overlayContainer = createTestOverlayContainer(TASK_ID, "test");
+
+ final TaskContainer taskContainer = overlayContainer.getTaskContainer();
+ spyOn(taskContainer);
+ final TaskContainer.TaskProperties taskProperties = taskContainer.getTaskProperties();
+ final TaskFragmentParentInfo parentInfo = new TaskFragmentParentInfo(
+ new Configuration(taskProperties.getConfiguration()), taskProperties.getDisplayId(),
+ true /* visible */, false /* hasDirectActivity */, null /* decorSurface */);
+ parentInfo.getConfiguration().windowConfiguration.getBounds().offset(10, 10);
+
+ mSplitController.onTaskFragmentParentInfoChanged(mTransaction, TASK_ID, parentInfo);
+
+ // The parent info must be applied to the task container
+ verify(taskContainer).updateTaskFragmentParentInfo(parentInfo);
+ verify(mSplitController, never()).updateContainer(any(), any());
+
+ assertWithMessage("The overlay container must still be dismissed even if "
+ + "#updateContainer is not called")
+ .that(taskContainer.getOverlayContainer()).isNull();
+ }
+
/**
* A simplified version of {@link SplitController.ActivityStartMonitor
* #createOrUpdateOverlayTaskFragmentIfNeeded}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java
index 6213f62..8f04f12 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java
@@ -63,6 +63,10 @@
if ((touchX < mStartThresholdX && mSwipeEdge == BackEvent.EDGE_LEFT)
|| (touchX > mStartThresholdX && mSwipeEdge == BackEvent.EDGE_RIGHT)) {
mStartThresholdX = touchX;
+ if ((mSwipeEdge == BackEvent.EDGE_LEFT && mStartThresholdX < mInitTouchX)
+ || (mSwipeEdge == BackEvent.EDGE_RIGHT && mStartThresholdX > mInitTouchX)) {
+ mInitTouchX = mStartThresholdX;
+ }
}
mLatestTouchX = touchX;
mLatestTouchY = touchY;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/TouchTrackerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/TouchTrackerTest.kt
index bf07dcc..6dbb1e2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/TouchTrackerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/TouchTrackerTest.kt
@@ -170,6 +170,71 @@
nonLinearTracker.assertProgress((touchX - INITIAL_X_LEFT_EDGE) / nonLinearTarget)
}
+ @Test
+ fun restartingGesture_resetsInitialTouchX_leftEdge() {
+ val linearTracker = linearTouchTracker()
+ linearTracker.setGestureStartLocation(INITIAL_X_LEFT_EDGE, 0f, BackEvent.EDGE_LEFT)
+ var touchX = 100f
+ val velocityX = 0f
+ val velocityY = 0f
+
+ // assert that progress is increased when increasing touchX
+ linearTracker.update(touchX, 0f, velocityX, velocityY)
+ linearTracker.assertProgress((touchX - INITIAL_X_LEFT_EDGE) / MAX_DISTANCE)
+
+ // assert that progress is reset to 0 when start location is updated
+ linearTracker.updateStartLocation()
+ linearTracker.assertProgress(0f)
+
+ // assert that progress remains 0 when touchX is decreased
+ touchX -= 50
+ linearTracker.update(touchX, 0f, velocityX, velocityY)
+ linearTracker.assertProgress(0f)
+
+ // assert that progress uses new minimal touchX for progress calculation
+ val newInitialTouchX = touchX
+ touchX += 100
+ linearTracker.update(touchX, 0f, velocityX, velocityY)
+ linearTracker.assertProgress((touchX - newInitialTouchX) / MAX_DISTANCE)
+
+ // assert the same for triggerBack==true
+ linearTracker.triggerBack = true
+ linearTracker.assertProgress((touchX - newInitialTouchX) / MAX_DISTANCE)
+ }
+
+ @Test
+ fun restartingGesture_resetsInitialTouchX_rightEdge() {
+ val linearTracker = linearTouchTracker()
+ linearTracker.setGestureStartLocation(INITIAL_X_RIGHT_EDGE, 0f, BackEvent.EDGE_RIGHT)
+
+ var touchX = INITIAL_X_RIGHT_EDGE - 100f
+ val velocityX = 0f
+ val velocityY = 0f
+
+ // assert that progress is increased when decreasing touchX
+ linearTracker.update(touchX, 0f, velocityX, velocityY)
+ linearTracker.assertProgress((INITIAL_X_RIGHT_EDGE - touchX) / MAX_DISTANCE)
+
+ // assert that progress is reset to 0 when start location is updated
+ linearTracker.updateStartLocation()
+ linearTracker.assertProgress(0f)
+
+ // assert that progress remains 0 when touchX is increased
+ touchX += 50
+ linearTracker.update(touchX, 0f, velocityX, velocityY)
+ linearTracker.assertProgress(0f)
+
+ // assert that progress uses new maximal touchX for progress calculation
+ val newInitialTouchX = touchX
+ touchX -= 100
+ linearTracker.update(touchX, 0f, velocityX, velocityY)
+ linearTracker.assertProgress((newInitialTouchX - touchX) / MAX_DISTANCE)
+
+ // assert the same for triggerBack==true
+ linearTracker.triggerBack = true
+ linearTracker.assertProgress((newInitialTouchX - touchX) / MAX_DISTANCE)
+ }
+
companion object {
private const val MAX_DISTANCE = 500f
private const val LINEAR_DISTANCE = 400f
diff --git a/media/java/android/media/LoudnessCodecConfigurator.java b/media/java/android/media/LoudnessCodecConfigurator.java
index de9d87c0..aadd783 100644
--- a/media/java/android/media/LoudnessCodecConfigurator.java
+++ b/media/java/android/media/LoudnessCodecConfigurator.java
@@ -234,19 +234,21 @@
* @param mediaCodec the codec to start receiving asynchronous loudness
* updates. The codec has to be in a configured or started
* state in order to add it for loudness updates.
- * @throws IllegalArgumentException if the {@code mediaCodec} was not configured,
- * does not contain loudness metadata or if it
- * was already added before
+ * @throws IllegalArgumentException if the same {@code mediaCodec} was already
+ * added before.
+ * @return {@code false} if the {@code mediaCodec} was not configured or does
+ * not contain loudness metadata, {@code true} otherwise.
*/
@FlaggedApi(FLAG_LOUDNESS_CONFIGURATOR_API)
- public void addMediaCodec(@NonNull MediaCodec mediaCodec) {
+ public boolean addMediaCodec(@NonNull MediaCodec mediaCodec) {
final MediaCodec mc = Objects.requireNonNull(mediaCodec,
"MediaCodec for addMediaCodec cannot be null");
int piid = PLAYER_PIID_INVALID;
final LoudnessCodecInfo mcInfo = getCodecInfo(mc);
if (mcInfo == null) {
- throw new IllegalArgumentException("Could not extract codec loudness information");
+ Log.v(TAG, "Could not extract codec loudness information");
+ return false;
}
synchronized (mConfiguratorLock) {
final AtomicBoolean containsCodec = new AtomicBoolean(false);
@@ -271,6 +273,8 @@
if (piid != PLAYER_PIID_INVALID) {
mLcDispatcher.addLoudnessCodecInfo(piid, mediaCodec.hashCode(), mcInfo);
}
+
+ return true;
}
/**
diff --git a/media/tests/LoudnessCodecApiTest/src/com/android/loudnesscodecapitest/LoudnessCodecConfiguratorTest.java b/media/tests/LoudnessCodecApiTest/src/com/android/loudnesscodecapitest/LoudnessCodecConfiguratorTest.java
index ce1004c..74e5612 100644
--- a/media/tests/LoudnessCodecApiTest/src/com/android/loudnesscodecapitest/LoudnessCodecConfiguratorTest.java
+++ b/media/tests/LoudnessCodecApiTest/src/com/android/loudnesscodecapitest/LoudnessCodecConfiguratorTest.java
@@ -19,6 +19,7 @@
import static android.media.audio.Flags.FLAG_LOUDNESS_CONFIGURATOR_API;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -191,6 +192,18 @@
@Test
@RequiresFlagsEnabled(FLAG_LOUDNESS_CONFIGURATOR_API)
+ public void addUnconfiguredMediaCodec_returnsFalse() throws Exception {
+ final MediaCodec mediaCodec = MediaCodec.createDecoderByType("audio/mpeg");
+
+ try {
+ assertFalse(mLcc.addMediaCodec(mediaCodec));
+ } finally {
+ mediaCodec.release();
+ }
+ }
+
+ @Test
+ @RequiresFlagsEnabled(FLAG_LOUDNESS_CONFIGURATOR_API)
public void setClearTrack_removeAllAudioServicePiidCodecs() throws Exception {
final ArgumentCaptor<List> argument = ArgumentCaptor.forClass(List.class);
final AudioTrack track = createAudioTrack();
diff --git a/packages/CredentialManager/res/drawable/more_horiz_24px.xml b/packages/CredentialManager/res/drawable/more_horiz_24px.xml
new file mode 100644
index 0000000..7b235f8
--- /dev/null
+++ b/packages/CredentialManager/res/drawable/more_horiz_24px.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="960"
+ android:viewportHeight="960"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M240,560Q207,560 183.5,536.5Q160,513 160,480Q160,447 183.5,423.5Q207,400 240,400Q273,400 296.5,423.5Q320,447 320,480Q320,513 296.5,536.5Q273,560 240,560ZM480,560Q447,560 423.5,536.5Q400,513 400,480Q400,447 423.5,423.5Q447,400 480,400Q513,400 536.5,423.5Q560,447 560,480Q560,513 536.5,536.5Q513,560 480,560ZM720,560Q687,560 663.5,536.5Q640,513 640,480Q640,447 663.5,423.5Q687,400 720,400Q753,400 776.5,423.5Q800,447 800,480Q800,513 776.5,536.5Q753,560 720,560Z"/>
+</vector>
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt b/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
index dfa5735..34f2509 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
@@ -398,7 +398,7 @@
val sliceBuilder = InlineSuggestionUi
.newContentBuilder(bottomSheetPendingIntent)
.setStartIcon(Icon.createWithResource(this,
- com.android.credentialmanager.R.drawable.ic_other_sign_in_24))
+ com.android.credentialmanager.R.drawable.more_horiz_24px))
val presentationBuilder = Presentations.Builder()
.setInlinePresentation(InlinePresentation(
sliceBuilder.build().slice, spec, /* pinned= */ true))
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveActivity.java
index 754437e..b5af845 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveActivity.java
@@ -76,7 +76,7 @@
boolean hasRequestInstallPermission = Arrays.asList(getRequestedPermissions(callingPackage))
.contains(permission.REQUEST_INSTALL_PACKAGES);
boolean hasInstallPermission = getBaseContext().checkPermission(permission.INSTALL_PACKAGES,
- 0 /* random value for pid */, callingUid) != PackageManager.PERMISSION_GRANTED;
+ 0 /* random value for pid */, callingUid) == PackageManager.PERMISSION_GRANTED;
if (!hasRequestInstallPermission && !hasInstallPermission) {
Log.e(TAG, "Uid " + callingUid + " does not have "
+ permission.REQUEST_INSTALL_PACKAGES + " or "
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveFragment.java
index 6ccbc4c..42dd382 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveFragment.java
@@ -28,12 +28,13 @@
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
String appTitle = getArguments().getString(UnarchiveActivity.APP_TITLE);
+ String installerTitle = getArguments().getString(UnarchiveActivity.INSTALLER_TITLE);
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getActivity());
dialogBuilder.setTitle(
String.format(getContext().getString(R.string.unarchive_application_title),
- appTitle));
+ appTitle, installerTitle));
dialogBuilder.setMessage(R.string.unarchive_body_text);
dialogBuilder.setPositiveButton(R.string.restore, this);
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt
index f4edb36..460a6f7 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt
@@ -24,7 +24,8 @@
import com.android.settingslib.spa.gallery.button.ActionButtonPageProvider
import com.android.settingslib.spa.gallery.card.CardPageProvider
import com.android.settingslib.spa.gallery.chart.ChartPageProvider
-import com.android.settingslib.spa.gallery.dialog.AlertDialogPageProvider
+import com.android.settingslib.spa.gallery.dialog.DialogMainPageProvider
+import com.android.settingslib.spa.gallery.dialog.NavDialogProvider
import com.android.settingslib.spa.gallery.editor.EditorMainPageProvider
import com.android.settingslib.spa.gallery.editor.SettingsExposedDropdownMenuBoxPageProvider
import com.android.settingslib.spa.gallery.editor.SettingsExposedDropdownMenuCheckBoxProvider
@@ -91,7 +92,8 @@
ProgressBarPageProvider,
LoadingBarPageProvider,
ChartPageProvider,
- AlertDialogPageProvider,
+ DialogMainPageProvider,
+ NavDialogProvider,
ItemListPageProvider,
ItemOperatePageProvider,
OperateListPageProvider,
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/dialog/AlertDialogPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/dialog/DialogMainPageProvider.kt
similarity index 84%
rename from packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/dialog/AlertDialogPage.kt
rename to packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/dialog/DialogMainPageProvider.kt
index 1545a3e..4e3fcee 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/dialog/AlertDialogPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/dialog/DialogMainPageProvider.kt
@@ -28,10 +28,10 @@
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
-private const val TITLE = "AlertDialogPage"
+private const val TITLE = "Category: Dialog"
-object AlertDialogPageProvider : SettingsPageProvider {
- override val name = "AlertDialogPage"
+object DialogMainPageProvider : SettingsPageProvider {
+ override val name = "DialogMain"
private val owner = createSettingsPage()
override fun buildEntry(arguments: Bundle?): List<SettingsEntry> = listOf(
@@ -47,6 +47,12 @@
override val onClick = alertDialogPresenter::open
})
}.build(),
+ SettingsEntryBuilder.create("NavDialog", owner).setUiLayoutFn {
+ Preference(object : PreferenceModel {
+ override val title = "Navigate to Dialog"
+ override val onClick = navigator(route = NavDialogProvider.name)
+ })
+ }.build(),
)
fun buildInjectEntry() = SettingsEntryBuilder.createInject(owner)
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/dialog/NavDialogProvider.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/dialog/NavDialogProvider.kt
new file mode 100644
index 0000000..6f79911
--- /dev/null
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/dialog/NavDialogProvider.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spa.gallery.dialog
+
+import android.os.Bundle
+import androidx.compose.runtime.Composable
+import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.widget.dialog.SettingsDialogCard
+
+object NavDialogProvider : SettingsPageProvider {
+ override val name = "NavDialog"
+ override val navType = SettingsPageProvider.NavType.Dialog
+
+ @Composable
+ override fun Page(arguments: Bundle?) {
+ SettingsDialogCard("Example Nav Dialog") {}
+ }
+}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePageProvider.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePageProvider.kt
index 6a2e598..1f028d5 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePageProvider.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePageProvider.kt
@@ -30,7 +30,7 @@
import com.android.settingslib.spa.gallery.button.ActionButtonPageProvider
import com.android.settingslib.spa.gallery.card.CardPageProvider
import com.android.settingslib.spa.gallery.chart.ChartPageProvider
-import com.android.settingslib.spa.gallery.dialog.AlertDialogPageProvider
+import com.android.settingslib.spa.gallery.dialog.DialogMainPageProvider
import com.android.settingslib.spa.gallery.editor.EditorMainPageProvider
import com.android.settingslib.spa.gallery.itemList.OperateListPageProvider
import com.android.settingslib.spa.gallery.page.ArgumentPageModel
@@ -71,7 +71,7 @@
ProgressBarPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
LoadingBarPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
ChartPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
- AlertDialogPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
+ DialogMainPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
EditorMainPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
CardPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
CopyablePageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt
index 9f8c868..5605485 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt
@@ -22,7 +22,6 @@
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.annotation.VisibleForTesting
-import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
@@ -30,15 +29,19 @@
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.core.view.WindowCompat
+import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavGraph.Companion.findStartDestination
+import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
+import androidx.navigation.compose.dialog
import androidx.navigation.compose.rememberNavController
import com.android.settingslib.spa.R
import com.android.settingslib.spa.framework.common.LogCategory
import com.android.settingslib.spa.framework.common.NullPageProvider
import com.android.settingslib.spa.framework.common.SettingsPage
import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.common.SettingsPageProvider.NavType
import com.android.settingslib.spa.framework.common.SettingsPageProviderRepository
import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
import com.android.settingslib.spa.framework.common.createSettingsPage
@@ -127,27 +130,31 @@
allProvider: Collection<SettingsPageProvider>,
content: @Composable (SettingsPage) -> Unit,
) {
- // TODO(b/298520326): Remove Box after the issue is fixed.
- // Wrap the top level node into a Box to workaround an issue of Compose 1.6.0-alpha03.
- Box {
- NavHost(
- navController = navController,
- startDestination = NullPageProvider.name,
- ) {
- composable(NullPageProvider.name) {}
- for (spp in allProvider) {
- animatedComposable(
- route = spp.name + spp.parameter.navRoute(),
- arguments = spp.parameter,
- ) { navBackStackEntry ->
- val page = remember { spp.createSettingsPage(navBackStackEntry.arguments) }
- content(page)
- }
+ NavHost(
+ navController = navController,
+ startDestination = NullPageProvider.name,
+ ) {
+ composable(NullPageProvider.name) {}
+ for (spp in allProvider) {
+ destination(spp) { navBackStackEntry ->
+ val page = remember { spp.createSettingsPage(navBackStackEntry.arguments) }
+ content(page)
}
}
}
}
+private fun NavGraphBuilder.destination(
+ spp: SettingsPageProvider,
+ content: @Composable (NavBackStackEntry) -> Unit,
+) {
+ val route = spp.name + spp.parameter.navRoute()
+ when (spp.navType) {
+ NavType.Page -> animatedComposable(route, spp.parameter) { content(it) }
+ NavType.Dialog -> dialog(route, spp.parameter) { content(it) }
+ }
+}
+
@Composable
private fun NavControllerWrapperImpl.InitialDestination(
initialIntent: Intent?,
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPageProvider.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPageProvider.kt
index 18f964e..81bee5e 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPageProvider.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPageProvider.kt
@@ -34,6 +34,14 @@
/** The page provider name, needs to be *unique* and *stable*. */
val name: String
+ enum class NavType {
+ Page,
+ Dialog,
+ }
+
+ val navType: NavType
+ get() = NavType.Page
+
/** The display name of this page provider, for better readability. */
val displayName: String
get() = name
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/dialog/SettingsDialog.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/dialog/SettingsDialog.kt
index 8b172da..f08e740 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/dialog/SettingsDialog.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/dialog/SettingsDialog.kt
@@ -19,10 +19,13 @@
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.AlertDialogDefaults
import androidx.compose.material3.Card
+import androidx.compose.material3.CardDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.window.Dialog
+import androidx.navigation.compose.NavHost
import com.android.settingslib.spa.framework.theme.SettingsDimension
import com.android.settingslib.spa.framework.theme.SettingsShape
import com.android.settingslib.spa.widget.ui.SettingsTitle
@@ -34,13 +37,27 @@
content: @Composable () -> Unit,
) {
Dialog(onDismissRequest = onDismissRequest) {
- Card(shape = SettingsShape.CornerExtraLarge) {
- Column(modifier = Modifier.padding(vertical = SettingsDimension.itemPaddingAround)) {
- Box(modifier = Modifier.padding(SettingsDimension.dialogItemPadding)) {
- SettingsTitle(title = title, useMediumWeight = true)
- }
- content()
+ SettingsDialogCard(title, content)
+ }
+}
+
+/**
+ * Card for dialog, suitable for independent dialog in the [NavHost].
+ */
+@Composable
+fun SettingsDialogCard(
+ title: String,
+ content: @Composable () -> Unit,
+) {
+ Card(
+ shape = SettingsShape.CornerExtraLarge,
+ colors = CardDefaults.cardColors(containerColor = AlertDialogDefaults.containerColor),
+ ) {
+ Column(modifier = Modifier.padding(vertical = SettingsDimension.itemPaddingAround)) {
+ Box(modifier = Modifier.padding(SettingsDimension.dialogItemPadding)) {
+ SettingsTitle(title = title, useMediumWeight = true)
}
+ content()
}
}
}
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/BrowseActivityTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/BrowseActivityTest.kt
index 92d3411..8cbd964 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/BrowseActivityTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/BrowseActivityTest.kt
@@ -18,6 +18,7 @@
import android.content.Context
import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onAllNodesWithText
import androidx.compose.ui.test.onNodeWithText
@@ -29,12 +30,14 @@
import com.android.settingslib.spa.framework.common.SettingsPage
import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
import com.android.settingslib.spa.framework.common.createSettingsPage
+import com.android.settingslib.spa.tests.testutils.SppDialog
import com.android.settingslib.spa.tests.testutils.SpaEnvironmentForTest
import com.android.settingslib.spa.tests.testutils.SpaLoggerForTest
import com.android.settingslib.spa.tests.testutils.SppDisabled
import com.android.settingslib.spa.tests.testutils.SppHome
import com.android.settingslib.spa.testutils.waitUntil
-import com.google.common.truth.Truth
+import com.android.settingslib.spa.testutils.waitUntilExists
+import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -106,11 +109,31 @@
composeTestRule.onNodeWithText(sppDisabled.getTitle(null)).assertDoesNotExist()
spaLogger.verifyPageEvent(pageDisabled.id, 0, 0)
}
+
+ @Test
+ fun browseContent_dialog() {
+ val spaEnvironment = SpaEnvironmentForTest(
+ context = context,
+ rootPages = listOf(SppHome.createSettingsPage()),
+ logger = spaLogger,
+ )
+ SpaEnvironmentFactory.reset(spaEnvironment)
+ val sppRepository by spaEnvironment.pageProviderRepository
+
+ composeTestRule.setContent {
+ BrowseContent(
+ sppRepository = sppRepository,
+ isPageEnabled = SettingsPage::isEnabled,
+ initialIntent = null,
+ )
+ }
+ composeTestRule.onNodeWithText(SppDialog.name).performClick()
+
+ composeTestRule.waitUntilExists(hasText(SppDialog.CONTENT))
+ }
}
private fun SpaLoggerForTest.verifyPageEvent(id: String, entryCount: Int, leaveCount: Int) {
- Truth.assertThat(getEventCount(id, LogEvent.PAGE_ENTER, LogCategory.FRAMEWORK))
- .isEqualTo(entryCount)
- Truth.assertThat(getEventCount(id, LogEvent.PAGE_LEAVE, LogCategory.FRAMEWORK))
- .isEqualTo(leaveCount)
+ assertThat(getEventCount(id, LogEvent.PAGE_ENTER, LogCategory.FRAMEWORK)).isEqualTo(entryCount)
+ assertThat(getEventCount(id, LogEvent.PAGE_LEAVE, LogCategory.FRAMEWORK)).isEqualTo(leaveCount)
}
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsEntryRepositoryTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsEntryRepositoryTest.kt
index b139f28..0a1c05f 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsEntryRepositoryTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsEntryRepositoryTest.kt
@@ -22,6 +22,7 @@
import com.android.settingslib.spa.framework.util.genEntryId
import com.android.settingslib.spa.framework.util.genPageId
import com.android.settingslib.spa.tests.testutils.SpaEnvironmentForTest
+import com.android.settingslib.spa.tests.testutils.SppDialog
import com.android.settingslib.spa.tests.testutils.SppHome
import com.android.settingslib.spa.tests.testutils.SppLayer1
import com.android.settingslib.spa.tests.testutils.SppLayer2
@@ -39,26 +40,21 @@
@Test
fun testGetPageWithEntry() {
val pageWithEntry = entryRepository.getAllPageWithEntry()
- assertThat(pageWithEntry.size).isEqualTo(3)
- assertThat(
- entryRepository.getPageWithEntry(genPageId("SppHome"))
- ?.entries?.size
- ).isEqualTo(1)
- assertThat(
- entryRepository.getPageWithEntry(genPageId("SppLayer1"))
- ?.entries?.size
- ).isEqualTo(3)
- assertThat(
- entryRepository.getPageWithEntry(genPageId("SppLayer2"))
- ?.entries?.size
- ).isEqualTo(2)
+
+ assertThat(pageWithEntry).hasSize(4)
+ assertThat(entryRepository.getPageWithEntry(genPageId("SppHome"))?.entries)
+ .hasSize(2)
+ assertThat(entryRepository.getPageWithEntry(genPageId("SppLayer1"))?.entries)
+ .hasSize(3)
+ assertThat(entryRepository.getPageWithEntry(genPageId("SppLayer2"))?.entries)
+ .hasSize(2)
assertThat(entryRepository.getPageWithEntry(genPageId("SppWithParam"))).isNull()
}
@Test
fun testGetEntry() {
val entry = entryRepository.getAllEntries()
- assertThat(entry.size).isEqualTo(7)
+ assertThat(entry).hasSize(8)
assertThat(
entryRepository.getEntry(
genEntryId(
@@ -91,6 +87,16 @@
).isNotNull()
assertThat(
entryRepository.getEntry(
+ genEntryId(
+ "INJECT",
+ SppDialog.createSettingsPage(),
+ SppHome.createSettingsPage(),
+ SppDialog.createSettingsPage(),
+ )
+ )
+ ).isNotNull()
+ assertThat(
+ entryRepository.getEntry(
genEntryId("Layer1Entry1", SppLayer1.createSettingsPage())
)
).isNotNull()
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsPageProviderRepositoryTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsPageProviderRepositoryTest.kt
index 8576573..169c541 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsPageProviderRepositoryTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsPageProviderRepositoryTest.kt
@@ -25,39 +25,55 @@
@RunWith(AndroidJUnit4::class)
class SettingsPageProviderRepositoryTest {
@Test
- fun getStartPageTest() {
- val sppRepoEmpty = SettingsPageProviderRepository(emptyList(), emptyList())
+ fun rootPages_empty() {
+ val sppRepoEmpty = SettingsPageProviderRepository(emptyList())
+
assertThat(sppRepoEmpty.getDefaultStartPage()).isEqualTo("")
assertThat(sppRepoEmpty.getAllRootPages()).isEmpty()
-
- val nullPage = NullPageProvider.createSettingsPage()
- val sppRepoNull =
- SettingsPageProviderRepository(emptyList(), listOf(nullPage))
- assertThat(sppRepoNull.getDefaultStartPage()).isEqualTo("NULL")
- assertThat(sppRepoNull.getAllRootPages()).contains(nullPage)
-
- val rootPage1 = createSettingsPage(sppName = "Spp1", displayName = "Spp1")
- val rootPage2 = createSettingsPage(sppName = "Spp2", displayName = "Spp2")
- val sppRepo = SettingsPageProviderRepository(emptyList(), listOf(rootPage1, rootPage2))
- val allRoots = sppRepo.getAllRootPages()
- assertThat(sppRepo.getDefaultStartPage()).isEqualTo("Spp1")
- assertThat(allRoots.size).isEqualTo(2)
- assertThat(allRoots).contains(rootPage1)
- assertThat(allRoots).contains(rootPage2)
}
@Test
- fun getProviderTest() {
- val sppRepoEmpty = SettingsPageProviderRepository(emptyList(), emptyList())
+ fun rootPages_single() {
+ val nullPage = NullPageProvider.createSettingsPage()
+
+ val sppRepoNull = SettingsPageProviderRepository(
+ allPageProviders = emptyList(),
+ rootPages = listOf(nullPage),
+ )
+
+ assertThat(sppRepoNull.getDefaultStartPage()).isEqualTo("NULL")
+ assertThat(sppRepoNull.getAllRootPages()).containsExactly(nullPage)
+ }
+
+ @Test
+ fun rootPages_twoPages() {
+ val rootPage1 = createSettingsPage(sppName = "Spp1", displayName = "Spp1")
+ val rootPage2 = createSettingsPage(sppName = "Spp2", displayName = "Spp2")
+
+ val sppRepo = SettingsPageProviderRepository(
+ allPageProviders = emptyList(),
+ rootPages = listOf(rootPage1, rootPage2),
+ )
+
+ assertThat(sppRepo.getDefaultStartPage()).isEqualTo("Spp1")
+ assertThat(sppRepo.getAllRootPages()).containsExactly(rootPage1, rootPage2)
+ }
+
+ @Test
+ fun getProviderOrNull_empty() {
+ val sppRepoEmpty = SettingsPageProviderRepository(emptyList())
assertThat(sppRepoEmpty.getAllProviders()).isEmpty()
assertThat(sppRepoEmpty.getProviderOrNull("Spp")).isNull()
+ }
+ @Test
+ fun getProviderOrNull_single() {
val sppRepo = SettingsPageProviderRepository(listOf(
object : SettingsPageProvider {
override val name = "Spp"
}
- ), emptyList())
- assertThat(sppRepo.getAllProviders().size).isEqualTo(1)
+ ))
+ assertThat(sppRepo.getAllProviders()).hasSize(1)
assertThat(sppRepo.getProviderOrNull("Spp")).isNotNull()
assertThat(sppRepo.getProviderOrNull("SppUnknown")).isNull()
}
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/tests/testutils/SpaEnvironmentForTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/tests/testutils/SpaEnvironmentForTest.kt
index 2755b4e..22a5ca3 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/tests/testutils/SpaEnvironmentForTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/tests/testutils/SpaEnvironmentForTest.kt
@@ -21,6 +21,8 @@
import android.content.Context
import android.content.Intent
import android.os.Bundle
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
import androidx.navigation.NavType
import androidx.navigation.navArgument
import com.android.settingslib.spa.framework.BrowseActivity
@@ -88,6 +90,7 @@
val owner = this.createSettingsPage()
return listOf(
SppLayer1.buildInject().setLink(fromPage = owner).build(),
+ SppDialog.buildInject().setLink(fromPage = owner).build(),
)
}
}
@@ -160,6 +163,21 @@
}
}
+object SppDialog : SettingsPageProvider {
+ override val name = "SppDialog"
+ override val navType = SettingsPageProvider.NavType.Dialog
+
+ const val CONTENT = "SppDialog Content"
+
+ @Composable
+ override fun Page(arguments: Bundle?) {
+ Text(CONTENT)
+ }
+
+ fun buildInject() = SettingsEntryBuilder.createInject(this.createSettingsPage())
+ .setMacro { SimplePreferenceMacro(title = name, clickRoute = name) }
+}
+
object SppForSearch : SettingsPageProvider {
override val name = "SppForSearch"
@@ -223,6 +241,7 @@
navArgument("rt_param") { type = NavType.StringType },
)
},
+ SppDialog,
),
rootPages
)
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
index 9560b8d..cdb8740 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
@@ -19,6 +19,7 @@
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHearingAid;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
@@ -42,18 +43,16 @@
BluetoothMediaDevice(
Context context,
CachedBluetoothDevice device,
- MediaRoute2Info info,
- String packageName) {
- this(context, device, info, packageName, null);
+ MediaRoute2Info info) {
+ this(context, device, info, null);
}
BluetoothMediaDevice(
Context context,
CachedBluetoothDevice device,
MediaRoute2Info info,
- String packageName,
RouteListingPreference.Item item) {
- super(context, info, packageName, item);
+ super(context, info, item);
mCachedDevice = device;
mAudioManager = context.getSystemService(AudioManager.class);
initDeviceRecord();
@@ -100,7 +99,12 @@
@Override
public String getId() {
- return MediaDeviceUtils.getId(mCachedDevice);
+ if (mCachedDevice.isHearingAidDevice()) {
+ if (mCachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
+ return Long.toString(mCachedDevice.getHiSyncId());
+ }
+ }
+ return mCachedDevice.getAddress();
}
/**
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/ComplexMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/ComplexMediaDevice.java
index 4e0ebd1..338fb87 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/ComplexMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/ComplexMediaDevice.java
@@ -34,9 +34,8 @@
ComplexMediaDevice(
Context context,
MediaRoute2Info info,
- String packageName,
RouteListingPreference.Item item) {
- super(context, info, packageName, item);
+ super(context, info, item);
}
// MediaRoute2Info.getName was made public on API 34, but exists since API 30.
@@ -63,7 +62,7 @@
@Override
public String getId() {
- return MediaDeviceUtils.getId(mRouteInfo);
+ return mRouteInfo.getId();
}
public boolean isConnected() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
index 012cbc0..1347dd1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
@@ -45,14 +45,13 @@
InfoMediaDevice(
Context context,
MediaRoute2Info info,
- String packageName,
RouteListingPreference.Item item) {
- super(context, info, packageName, item);
+ super(context, info, item);
initDeviceRecord();
}
- InfoMediaDevice(Context context, MediaRoute2Info info, String packageName) {
- this(context, info, packageName, null);
+ InfoMediaDevice(Context context, MediaRoute2Info info) {
+ this(context, info, null);
}
@Override
@@ -118,7 +117,7 @@
@Override
public String getId() {
- return MediaDeviceUtils.getId(mRouteInfo);
+ return mRouteInfo.getId();
}
public boolean isConnected() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
index e5fce5b..581c7de 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
@@ -383,7 +383,7 @@
for (MediaRoute2Info route : getSelectableRoutes(info)) {
deviceList.add(
new InfoMediaDevice(
- mContext, route, mPackageName, mPreferenceItemMap.get(route.getId())));
+ mContext, route, mPreferenceItemMap.get(route.getId())));
}
return deviceList;
}
@@ -410,7 +410,7 @@
for (MediaRoute2Info route : getDeselectableRoutes(info)) {
deviceList.add(
new InfoMediaDevice(
- mContext, route, mPackageName, mPreferenceItemMap.get(route.getId())));
+ mContext, route, mPreferenceItemMap.get(route.getId())));
Log.d(TAG, route.getName() + " is deselectable for " + mPackageName);
}
return deviceList;
@@ -434,7 +434,7 @@
for (MediaRoute2Info route : getSelectedRoutes(info)) {
deviceList.add(
new InfoMediaDevice(
- mContext, route, mPackageName, mPreferenceItemMap.get(route.getId())));
+ mContext, route, mPreferenceItemMap.get(route.getId())));
}
return deviceList;
}
@@ -633,7 +633,6 @@
new InfoMediaDevice(
mContext,
route,
- mPackageName,
mPreferenceItemMap.get(route.getId()));
break;
case TYPE_BUILTIN_SPEAKER:
@@ -650,7 +649,6 @@
new PhoneMediaDevice(
mContext,
route,
- mPackageName,
mPreferenceItemMap.getOrDefault(route.getId(), null));
break;
case TYPE_HEARING_AID:
@@ -666,7 +664,6 @@
mContext,
cachedDevice,
route,
- mPackageName,
mPreferenceItemMap.getOrDefault(route.getId(), null));
}
break;
@@ -675,7 +672,6 @@
new ComplexMediaDevice(
mContext,
route,
- mPackageName,
mPreferenceItemMap.get(route.getId()));
break;
default:
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index dbc3bf7..ebcca42 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -567,7 +567,7 @@
final CachedBluetoothDevice cachedDevice =
cachedDeviceManager.findDevice(device);
if (isBondedMediaDevice(cachedDevice) && isMutingExpectedDevice(cachedDevice)) {
- return new BluetoothMediaDevice(mContext, cachedDevice, null, mPackageName);
+ return new BluetoothMediaDevice(mContext, cachedDevice, null);
}
}
return null;
@@ -614,7 +614,7 @@
mDisconnectedMediaDevices.clear();
for (CachedBluetoothDevice cachedDevice : cachedBluetoothDeviceList) {
final MediaDevice mediaDevice =
- new BluetoothMediaDevice(mContext, cachedDevice, null, mPackageName);
+ new BluetoothMediaDevice(mContext, cachedDevice, null);
if (!mMediaDevices.contains(mediaDevice)) {
cachedDevice.registerCallback(mDeviceAttributeChangeCallback);
mDisconnectedMediaDevices.add(mediaDevice);
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
index c8e4c0c..f2d9d14 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
@@ -121,16 +121,13 @@
protected final Context mContext;
protected final MediaRoute2Info mRouteInfo;
protected final RouteListingPreference.Item mItem;
- protected final String mPackageName;
MediaDevice(
Context context,
MediaRoute2Info info,
- String packageName,
RouteListingPreference.Item item) {
mContext = context;
mRouteInfo = info;
- mPackageName = packageName;
mItem = item;
setType(info);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java
deleted file mode 100644
index b3a52b9..0000000
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.settingslib.media;
-
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHearingAid;
-import android.media.MediaRoute2Info;
-
-import com.android.settingslib.bluetooth.CachedBluetoothDevice;
-
-/**
- * MediaDeviceUtils provides utility function for MediaDevice
- */
-public class MediaDeviceUtils {
- /**
- * Use CachedBluetoothDevice address to represent unique id
- *
- * @param cachedDevice the CachedBluetoothDevice
- * @return CachedBluetoothDevice address
- */
- public static String getId(CachedBluetoothDevice cachedDevice) {
- if (cachedDevice.isHearingAidDevice()) {
- if (cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
- return Long.toString(cachedDevice.getHiSyncId());
- }
- }
- return cachedDevice.getAddress();
- }
-
- /**
- * Use BluetoothDevice address to represent unique id
- *
- * @param bluetoothDevice the BluetoothDevice
- * @return BluetoothDevice address
- */
- public static String getId(BluetoothDevice bluetoothDevice) {
- return bluetoothDevice.getAddress();
- }
-
- /**
- * Use MediaRoute2Info id to represent unique id
- *
- * @param route the MediaRoute2Info
- * @return MediaRoute2Info id
- */
- public static String getId(MediaRoute2Info route) {
- return route.getId();
- }
-}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
index 0676ce5..d6f1eab 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
@@ -117,16 +117,15 @@
return name.toString();
}
- PhoneMediaDevice(Context context, MediaRoute2Info info, String packageName) {
- this(context, info, packageName, null);
+ PhoneMediaDevice(Context context, MediaRoute2Info info) {
+ this(context, info, null);
}
PhoneMediaDevice(
Context context,
MediaRoute2Info info,
- String packageName,
RouteListingPreference.Item item) {
- super(context, info, packageName, item);
+ super(context, info, item);
mDeviceIconUtil = new DeviceIconUtil(mContext);
initDeviceRecord();
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaDeviceTest.java
index f50802a..7061742 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaDeviceTest.java
@@ -39,6 +39,8 @@
@RunWith(RobolectricTestRunner.class)
public class BluetoothMediaDeviceTest {
+ private static final String TEST_ADDRESS = "11:22:33:44:55:66";
+
@Mock
private CachedBluetoothDevice mDevice;
@@ -54,7 +56,7 @@
when(mDevice.isActiveDevice(BluetoothProfile.HEARING_AID)).thenReturn(true);
when(mDevice.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(true);
- mBluetoothMediaDevice = new BluetoothMediaDevice(mContext, mDevice, null, null, null);
+ mBluetoothMediaDevice = new BluetoothMediaDevice(mContext, mDevice, null, null);
}
@Test
@@ -111,4 +113,10 @@
assertThat(mBluetoothMediaDevice.getIcon() instanceof BitmapDrawable).isFalse();
}
+
+ @Test
+ public void getId_returnsCachedBluetoothDeviceAddress() {
+ when(mDevice.getAddress()).thenReturn(TEST_ADDRESS);
+ assertThat(mBluetoothMediaDevice.getId()).isEqualTo(TEST_ADDRESS);
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaDeviceTest.java
index a072c17..0665308 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaDeviceTest.java
@@ -65,7 +65,7 @@
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
- mInfoMediaDevice = new InfoMediaDevice(mContext, mRouteInfo, TEST_PACKAGE_NAME);
+ mInfoMediaDevice = new InfoMediaDevice(mContext, mRouteInfo);
}
@Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
index 2252b69..f0330c4 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
@@ -547,7 +547,7 @@
@Test
public void connectDeviceWithoutPackageName_noSession_returnFalse() {
final MediaRoute2Info info = mock(MediaRoute2Info.class);
- final MediaDevice device = new InfoMediaDevice(mContext, info, TEST_PACKAGE_NAME);
+ final MediaDevice device = new InfoMediaDevice(mContext, info);
final List<RoutingSessionInfo> infos = new ArrayList<>();
@@ -623,7 +623,7 @@
routingSessionInfos.add(info);
final MediaRoute2Info route2Info = mock(MediaRoute2Info.class);
- final MediaDevice device = new InfoMediaDevice(mContext, route2Info, TEST_PACKAGE_NAME);
+ final MediaDevice device = new InfoMediaDevice(mContext, route2Info);
final List<String> list = new ArrayList<>();
list.add(TEST_ID);
@@ -644,7 +644,7 @@
routingSessionInfos.add(info);
final MediaRoute2Info route2Info = mock(MediaRoute2Info.class);
- final MediaDevice device = new InfoMediaDevice(mContext, route2Info, TEST_PACKAGE_NAME);
+ final MediaDevice device = new InfoMediaDevice(mContext, route2Info);
final List<String> list = new ArrayList<>();
list.add("fake_id");
@@ -674,7 +674,7 @@
routingSessionInfos.add(info);
final MediaRoute2Info route2Info = mock(MediaRoute2Info.class);
- final MediaDevice device = new InfoMediaDevice(mContext, route2Info, TEST_PACKAGE_NAME);
+ final MediaDevice device = new InfoMediaDevice(mContext, route2Info);
final List<String> list = new ArrayList<>();
list.add(TEST_ID);
@@ -695,7 +695,7 @@
routingSessionInfos.add(info);
final MediaRoute2Info route2Info = mock(MediaRoute2Info.class);
- final MediaDevice device = new InfoMediaDevice(mContext, route2Info, TEST_PACKAGE_NAME);
+ final MediaDevice device = new InfoMediaDevice(mContext, route2Info);
final List<String> list = new ArrayList<>();
list.add("fake_id");
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
index 926b41a..999e8d5 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
@@ -116,8 +116,8 @@
when(mLocalProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
when(mLocalProfileManager.getHearingAidProfile()).thenReturn(mHapProfile);
- mInfoMediaDevice1 = spy(new InfoMediaDevice(mContext, mRouteInfo1, TEST_PACKAGE_NAME));
- mInfoMediaDevice2 = new InfoMediaDevice(mContext, mRouteInfo2, TEST_PACKAGE_NAME);
+ mInfoMediaDevice1 = spy(new InfoMediaDevice(mContext, mRouteInfo1));
+ mInfoMediaDevice2 = new InfoMediaDevice(mContext, mRouteInfo2);
mLocalMediaManager = new LocalMediaManager(mContext, mLocalBluetoothManager,
mInfoMediaManager, "com.test.packagename");
mLocalMediaManager.mAudioManager = mAudioManager;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
index 18055d9..098ab16 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
@@ -171,17 +171,17 @@
mBluetoothMediaDevice1 =
new BluetoothMediaDevice(
- mContext, mCachedDevice1, mBluetoothRouteInfo1, TEST_PACKAGE_NAME);
+ mContext, mCachedDevice1, mBluetoothRouteInfo1);
mBluetoothMediaDevice2 =
new BluetoothMediaDevice(
- mContext, mCachedDevice2, mBluetoothRouteInfo2, TEST_PACKAGE_NAME);
+ mContext, mCachedDevice2, mBluetoothRouteInfo2);
mBluetoothMediaDevice3 =
new BluetoothMediaDevice(
- mContext, mCachedDevice3, mBluetoothRouteInfo3, TEST_PACKAGE_NAME);
- mInfoMediaDevice1 = new InfoMediaDevice(mContext, mRouteInfo1, TEST_PACKAGE_NAME);
- mInfoMediaDevice2 = new InfoMediaDevice(mContext, mRouteInfo2, TEST_PACKAGE_NAME);
- mInfoMediaDevice3 = new InfoMediaDevice(mContext, mRouteInfo3, TEST_PACKAGE_NAME);
- mPhoneMediaDevice = new PhoneMediaDevice(mContext, mPhoneRouteInfo, TEST_PACKAGE_NAME);
+ mContext, mCachedDevice3, mBluetoothRouteInfo3);
+ mInfoMediaDevice1 = new InfoMediaDevice(mContext, mRouteInfo1);
+ mInfoMediaDevice2 = new InfoMediaDevice(mContext, mRouteInfo2);
+ mInfoMediaDevice3 = new InfoMediaDevice(mContext, mRouteInfo3);
+ mPhoneMediaDevice = new PhoneMediaDevice(mContext, mPhoneRouteInfo);
}
@Test
@@ -316,7 +316,7 @@
when(phoneRouteInfo.getType()).thenReturn(TYPE_WIRED_HEADPHONES);
final PhoneMediaDevice phoneMediaDevice =
- new PhoneMediaDevice(mContext, phoneRouteInfo, TEST_PACKAGE_NAME);
+ new PhoneMediaDevice(mContext, phoneRouteInfo);
mMediaDevices.add(mBluetoothMediaDevice1);
mMediaDevices.add(phoneMediaDevice);
@@ -332,7 +332,7 @@
when(phoneRouteInfo.getType()).thenReturn(TYPE_WIRED_HEADPHONES);
final PhoneMediaDevice phoneMediaDevice =
- new PhoneMediaDevice(mContext, phoneRouteInfo, TEST_PACKAGE_NAME);
+ new PhoneMediaDevice(mContext, phoneRouteInfo);
mMediaDevices.add(mInfoMediaDevice1);
mMediaDevices.add(phoneMediaDevice);
@@ -483,7 +483,7 @@
public void getFeatures_noRouteInfo_returnEmptyList() {
mBluetoothMediaDevice1 =
new BluetoothMediaDevice(
- mContext, mCachedDevice1, null /* MediaRoute2Info */, TEST_PACKAGE_NAME);
+ mContext, mCachedDevice1, /* MediaRoute2Info */ null);
assertThat(mBluetoothMediaDevice1.getFeatures().size()).isEqualTo(0);
}
@@ -498,10 +498,9 @@
mContext,
mCachedDevice1,
null /* MediaRoute2Info */,
- TEST_PACKAGE_NAME,
mItem);
mPhoneMediaDevice =
- new PhoneMediaDevice(mContext, mPhoneRouteInfo, TEST_PACKAGE_NAME, mItem);
+ new PhoneMediaDevice(mContext, mPhoneRouteInfo, mItem);
assertThat(mBluetoothMediaDevice1.getSelectionBehavior()).isEqualTo(
SELECTION_BEHAVIOR_TRANSFER);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceUtilsTest.java
deleted file mode 100644
index 30a6ad2..0000000
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceUtilsTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2019 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.settingslib.media;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.when;
-
-import android.bluetooth.BluetoothDevice;
-import android.media.MediaRoute2Info;
-
-import com.android.settingslib.bluetooth.CachedBluetoothDevice;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-
-@RunWith(RobolectricTestRunner.class)
-public class MediaDeviceUtilsTest {
-
- private static final String TEST_ADDRESS = "11:22:33:44:55:66";
- private static final String TEST_ROUTE_ID = "test_route_id";
-
- @Mock
- private CachedBluetoothDevice mCachedDevice;
- @Mock
- private BluetoothDevice mBluetoothDevice;
- @Mock
- private MediaRoute2Info mRouteInfo;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- }
-
- @Test
- public void getId_returnCachedBluetoothDeviceAddress() {
- when(mCachedDevice.getAddress()).thenReturn(TEST_ADDRESS);
-
- final String id = MediaDeviceUtils.getId(mCachedDevice);
-
- assertThat(id).isEqualTo(TEST_ADDRESS);
- }
-
- @Test
- public void getId_returnBluetoothDeviceAddress() {
- when(mBluetoothDevice.getAddress()).thenReturn(TEST_ADDRESS);
-
- final String id = MediaDeviceUtils.getId(mBluetoothDevice);
-
- assertThat(id).isEqualTo(TEST_ADDRESS);
- }
-
- @Test
- public void getId_returnRouteInfoId() {
- when(mRouteInfo.getId()).thenReturn(TEST_ROUTE_ID);
-
- final String id = MediaDeviceUtils.getId(mRouteInfo);
-
- assertThat(id).isEqualTo(TEST_ROUTE_ID);
- }
-}
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
index d6e8d26..2e39adc 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
@@ -69,6 +69,7 @@
Settings.Global.PRIVATE_DNS_SPECIFIER,
Settings.Global.SOFT_AP_TIMEOUT_ENABLED,
Settings.Global.ZEN_DURATION,
+ Settings.Global.MUTE_ALARM_STREAM_WITH_RINGER_MODE_USER_PREFERENCE,
Settings.Global.REVERSE_CHARGING_AUTO_ON,
Settings.Global.CHARGING_VIBRATION_ENABLED,
Settings.Global.AWARE_ALLOWED,
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
index 59c3cd3..e7d7bb0 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
@@ -19,93 +19,105 @@
import android.compat.annotation.UnsupportedAppUsage;
import android.provider.Settings;
+import com.android.server.display.feature.flags.Flags;
+
+import java.util.ArrayList;
+import java.util.List;
+
/** Information about the system settings to back up */
public class SystemSettings {
/**
- * Settings to backup.
+ * Settings to back up.
*
* NOTE: Settings are backed up and restored in the order they appear
* in this array. If you have one setting depending on another,
* make sure that they are ordered appropriately.
*/
@UnsupportedAppUsage
- public static final String[] SETTINGS_TO_BACKUP = {
- Settings.System.STAY_ON_WHILE_PLUGGED_IN, // moved to global
- Settings.System.WIFI_USE_STATIC_IP,
- Settings.System.WIFI_STATIC_IP,
- Settings.System.WIFI_STATIC_GATEWAY,
- Settings.System.WIFI_STATIC_NETMASK,
- Settings.System.WIFI_STATIC_DNS1,
- Settings.System.WIFI_STATIC_DNS2,
- Settings.System.BLUETOOTH_DISCOVERABILITY,
- Settings.System.BLUETOOTH_DISCOVERABILITY_TIMEOUT,
- Settings.System.FONT_SCALE,
- Settings.System.DIM_SCREEN,
- Settings.System.SCREEN_OFF_TIMEOUT,
- Settings.System.SCREEN_BRIGHTNESS_MODE,
- Settings.System.ADAPTIVE_SLEEP, // moved to secure
- Settings.System.APPLY_RAMPING_RINGER,
- Settings.System.VIBRATE_INPUT_DEVICES,
- Settings.System.MODE_RINGER_STREAMS_AFFECTED,
- Settings.System.TEXT_AUTO_REPLACE,
- Settings.System.TEXT_AUTO_CAPS,
- Settings.System.TEXT_AUTO_PUNCTUATE,
- Settings.System.TEXT_SHOW_PASSWORD,
- Settings.System.AUTO_TIME, // moved to global
- Settings.System.AUTO_TIME_ZONE, // moved to global
- Settings.System.TIME_12_24,
- Settings.System.DTMF_TONE_WHEN_DIALING,
- Settings.System.DTMF_TONE_TYPE_WHEN_DIALING,
- Settings.System.HEARING_AID,
- Settings.System.TTY_MODE,
- Settings.System.MASTER_MONO,
- Settings.System.MASTER_BALANCE,
- Settings.System.FOLD_LOCK_BEHAVIOR,
- Settings.System.SOUND_EFFECTS_ENABLED,
- Settings.System.HAPTIC_FEEDBACK_ENABLED,
- Settings.System.POWER_SOUNDS_ENABLED, // moved to global
- Settings.System.DOCK_SOUNDS_ENABLED, // moved to global
- Settings.System.LOCKSCREEN_SOUNDS_ENABLED,
- Settings.System.SHOW_WEB_SUGGESTIONS,
- Settings.System.SIP_CALL_OPTIONS,
- Settings.System.SIP_RECEIVE_CALLS,
- Settings.System.POINTER_SPEED,
- Settings.System.VIBRATE_ON,
- Settings.System.VIBRATE_WHEN_RINGING,
- Settings.System.RINGTONE,
- Settings.System.LOCK_TO_APP_ENABLED,
- Settings.System.NOTIFICATION_SOUND,
- Settings.System.ACCELEROMETER_ROTATION,
- Settings.System.SHOW_BATTERY_PERCENT,
- Settings.System.ALARM_VIBRATION_INTENSITY,
- Settings.System.MEDIA_VIBRATION_INTENSITY,
- Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
- Settings.System.RING_VIBRATION_INTENSITY,
- Settings.System.HAPTIC_FEEDBACK_INTENSITY,
- Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY,
- Settings.System.KEYBOARD_VIBRATION_ENABLED,
- Settings.System.HAPTIC_FEEDBACK_ENABLED,
- Settings.System.DISPLAY_COLOR_MODE_VENDOR_HINT, // must precede DISPLAY_COLOR_MODE
- Settings.System.DISPLAY_COLOR_MODE,
- Settings.System.ALARM_ALERT,
- Settings.System.NOTIFICATION_LIGHT_PULSE,
- Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED,
- Settings.System.CLOCKWORK_BLUETOOTH_SETTINGS_PREF,
- Settings.System.UNREAD_NOTIFICATION_DOT_INDICATOR,
- Settings.System.AUTO_LAUNCH_MEDIA_CONTROLS,
- Settings.System.LOCALE_PREFERENCES,
- Settings.System.TOUCHPAD_POINTER_SPEED,
- Settings.System.TOUCHPAD_NATURAL_SCROLLING,
- Settings.System.TOUCHPAD_TAP_TO_CLICK,
- Settings.System.TOUCHPAD_RIGHT_CLICK_ZONE,
- Settings.System.CAMERA_FLASH_NOTIFICATION,
- Settings.System.SCREEN_FLASH_NOTIFICATION,
- Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR,
- Settings.System.PEAK_REFRESH_RATE,
- Settings.System.MIN_REFRESH_RATE,
- Settings.System.NOTIFICATION_COOLDOWN_ENABLED,
- Settings.System.NOTIFICATION_COOLDOWN_ALL,
- Settings.System.NOTIFICATION_COOLDOWN_VIBRATE_UNLOCKED,
- };
+ public static final String[] SETTINGS_TO_BACKUP = getSettingsToBackUp();
+
+ private static String[] getSettingsToBackUp() {
+ List<String> settings = new ArrayList<>(List.of(
+ Settings.System.STAY_ON_WHILE_PLUGGED_IN, // moved to global
+ Settings.System.WIFI_USE_STATIC_IP,
+ Settings.System.WIFI_STATIC_IP,
+ Settings.System.WIFI_STATIC_GATEWAY,
+ Settings.System.WIFI_STATIC_NETMASK,
+ Settings.System.WIFI_STATIC_DNS1,
+ Settings.System.WIFI_STATIC_DNS2,
+ Settings.System.BLUETOOTH_DISCOVERABILITY,
+ Settings.System.BLUETOOTH_DISCOVERABILITY_TIMEOUT,
+ Settings.System.FONT_SCALE,
+ Settings.System.DIM_SCREEN,
+ Settings.System.SCREEN_OFF_TIMEOUT,
+ Settings.System.SCREEN_BRIGHTNESS_MODE,
+ Settings.System.ADAPTIVE_SLEEP, // moved to secure
+ Settings.System.APPLY_RAMPING_RINGER,
+ Settings.System.VIBRATE_INPUT_DEVICES,
+ Settings.System.MODE_RINGER_STREAMS_AFFECTED,
+ Settings.System.TEXT_AUTO_REPLACE,
+ Settings.System.TEXT_AUTO_CAPS,
+ Settings.System.TEXT_AUTO_PUNCTUATE,
+ Settings.System.TEXT_SHOW_PASSWORD,
+ Settings.System.AUTO_TIME, // moved to global
+ Settings.System.AUTO_TIME_ZONE, // moved to global
+ Settings.System.TIME_12_24,
+ Settings.System.DTMF_TONE_WHEN_DIALING,
+ Settings.System.DTMF_TONE_TYPE_WHEN_DIALING,
+ Settings.System.HEARING_AID,
+ Settings.System.TTY_MODE,
+ Settings.System.MASTER_MONO,
+ Settings.System.MASTER_BALANCE,
+ Settings.System.FOLD_LOCK_BEHAVIOR,
+ Settings.System.SOUND_EFFECTS_ENABLED,
+ Settings.System.HAPTIC_FEEDBACK_ENABLED,
+ Settings.System.POWER_SOUNDS_ENABLED, // moved to global
+ Settings.System.DOCK_SOUNDS_ENABLED, // moved to global
+ Settings.System.LOCKSCREEN_SOUNDS_ENABLED,
+ Settings.System.SHOW_WEB_SUGGESTIONS,
+ Settings.System.SIP_CALL_OPTIONS,
+ Settings.System.SIP_RECEIVE_CALLS,
+ Settings.System.POINTER_SPEED,
+ Settings.System.VIBRATE_ON,
+ Settings.System.VIBRATE_WHEN_RINGING,
+ Settings.System.RINGTONE,
+ Settings.System.LOCK_TO_APP_ENABLED,
+ Settings.System.NOTIFICATION_SOUND,
+ Settings.System.ACCELEROMETER_ROTATION,
+ Settings.System.SHOW_BATTERY_PERCENT,
+ Settings.System.ALARM_VIBRATION_INTENSITY,
+ Settings.System.MEDIA_VIBRATION_INTENSITY,
+ Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
+ Settings.System.RING_VIBRATION_INTENSITY,
+ Settings.System.HAPTIC_FEEDBACK_INTENSITY,
+ Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY,
+ Settings.System.KEYBOARD_VIBRATION_ENABLED,
+ Settings.System.HAPTIC_FEEDBACK_ENABLED,
+ Settings.System.DISPLAY_COLOR_MODE_VENDOR_HINT, // must precede DISPLAY_COLOR_MODE
+ Settings.System.DISPLAY_COLOR_MODE,
+ Settings.System.ALARM_ALERT,
+ Settings.System.NOTIFICATION_LIGHT_PULSE,
+ Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED,
+ Settings.System.CLOCKWORK_BLUETOOTH_SETTINGS_PREF,
+ Settings.System.UNREAD_NOTIFICATION_DOT_INDICATOR,
+ Settings.System.AUTO_LAUNCH_MEDIA_CONTROLS,
+ Settings.System.LOCALE_PREFERENCES,
+ Settings.System.TOUCHPAD_POINTER_SPEED,
+ Settings.System.TOUCHPAD_NATURAL_SCROLLING,
+ Settings.System.TOUCHPAD_TAP_TO_CLICK,
+ Settings.System.TOUCHPAD_RIGHT_CLICK_ZONE,
+ Settings.System.CAMERA_FLASH_NOTIFICATION,
+ Settings.System.SCREEN_FLASH_NOTIFICATION,
+ Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR,
+ Settings.System.NOTIFICATION_COOLDOWN_ENABLED,
+ Settings.System.NOTIFICATION_COOLDOWN_ALL,
+ Settings.System.NOTIFICATION_COOLDOWN_VIBRATE_UNLOCKED
+ ));
+ if (Flags.backUpSmoothDisplayAndForcePeakRefreshRate()) {
+ settings.add(Settings.System.PEAK_REFRESH_RATE);
+ settings.add(Settings.System.MIN_REFRESH_RATE);
+ }
+ return settings.toArray(new String[0]);
+ }
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index f8bdcf6..5022395 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -210,6 +210,8 @@
VALIDATORS.put(Global.POWER_BUTTON_LONG_PRESS_DURATION_MS, NONE_NEGATIVE_LONG_VALIDATOR);
VALIDATORS.put(Global.STYLUS_EVER_USED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Global.MUTE_ALARM_STREAM_WITH_RINGER_MODE, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(
+ Global.MUTE_ALARM_STREAM_WITH_RINGER_MODE_USER_PREFERENCE, BOOLEAN_VALIDATOR);
VALIDATORS.put(Global.Wearable.HAS_PAY_TOKENS, BOOLEAN_VALIDATOR);
VALIDATORS.put(Global.Wearable.GMS_CHECKIN_TIMEOUT_MIN, ANY_INTEGER_VALIDATOR);
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 6ad10cc..1481d97 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -33,6 +33,8 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.server.display.feature.flags.Flags;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -53,59 +55,6 @@
public static final String HYBRID_SYSUI_BATTERY_WARNING_FLAGS =
"hybrid_sysui_battery_warning_flags";
- /**
- * The following denylists contain settings that should *not* be backed up and restored to
- * another device. As a general rule, anything that is not user configurable should be
- * denied (and conversely, things that *are* user configurable *should* be backed up)
- */
- private static final Set<String> BACKUP_DENY_LIST_SYSTEM_SETTINGS =
- newHashSet(
- Settings.System.ADVANCED_SETTINGS, // candidate for backup?
- Settings.System.ALARM_ALERT_CACHE, // internal cache
- Settings.System.APPEND_FOR_LAST_AUDIBLE, // suffix deprecated since API 2
- Settings.System.EGG_MODE, // I am the lolrus
- Settings.System.END_BUTTON_BEHAVIOR, // bug?
- Settings.System
- .HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, // candidate for backup?
- Settings.System.LOCKSCREEN_DISABLED, // ?
- Settings.System.MEDIA_BUTTON_RECEIVER, // candidate for backup?
- Settings.System.MUTE_STREAMS_AFFECTED, // candidate for backup?
- Settings.System.NOTIFICATION_SOUND_CACHE, // internal cache
- Settings.System.POINTER_LOCATION, // backup candidate?
- Settings.System.DEBUG_ENABLE_ENHANCED_CALL_BLOCKING, // used for testing only
- Settings.System.RINGTONE_CACHE, // internal cache
- Settings.System.SCREEN_BRIGHTNESS, // removed in P
- Settings.System.SETUP_WIZARD_HAS_RUN, // Only used by SuW
- Settings.System.SHOW_GTALK_SERVICE_STATUS, // candidate for backup?
- Settings.System.SHOW_TOUCHES,
- Settings.System.SHOW_KEY_PRESSES,
- Settings.System.SHOW_ROTARY_INPUT,
- Settings.System.SIP_ADDRESS_ONLY, // value, not a setting
- Settings.System.SIP_ALWAYS, // value, not a setting
- Settings.System.SYSTEM_LOCALES, // bug?
- Settings.System.USER_ROTATION, // backup candidate?
- Settings.System.VIBRATE_IN_SILENT, // deprecated?
- Settings.System.VOLUME_ACCESSIBILITY, // used internally, changing value will
- // not change volume
- Settings.System.VOLUME_ALARM, // deprecated since API 2?
- Settings.System.VOLUME_ASSISTANT, // candidate for backup?
- Settings.System.VOLUME_BLUETOOTH_SCO, // deprecated since API 2?
- Settings.System.VOLUME_MASTER, // candidate for backup?
- Settings.System.VOLUME_MUSIC, // deprecated since API 2?
- Settings.System.VOLUME_NOTIFICATION, // deprecated since API 2?
- Settings.System.VOLUME_RING, // deprecated since API 2?
- Settings.System.VOLUME_SYSTEM, // deprecated since API 2?
- Settings.System.VOLUME_VOICE, // deprecated since API 2?
- Settings.System.WHEN_TO_MAKE_WIFI_CALLS, // bug?
- Settings.System.WINDOW_ORIENTATION_LISTENER_LOG, // used for debugging only
- Settings.System.SCREEN_BRIGHTNESS_FLOAT,
- Settings.System.SCREEN_BRIGHTNESS_FOR_ALS,
- Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE,
- Settings.System.WEAR_TTS_PREWARM_ENABLED,
- Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ,
- Settings.System.MULTI_AUDIO_FOCUS_ENABLED // form-factor/OEM specific
- );
-
private static final Set<String> BACKUP_DENY_LIST_GLOBAL_SETTINGS =
newHashSet(
Settings.Global.ACTIVITY_MANAGER_CONSTANTS,
@@ -737,6 +686,7 @@
Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS,
Settings.Secure.CONTENT_CAPTURE_ENABLED,
Settings.Secure.DEFAULT_INPUT_METHOD,
+ Settings.Secure.DEFAULT_DEVICE_INPUT_METHOD,
Settings.Secure.DEVICE_PAIRED,
Settings.Secure.DIALER_DEFAULT_APPLICATION,
Settings.Secure.DISABLED_PRINT_SERVICES,
@@ -862,7 +812,7 @@
checkSettingsBackedUpOrDenied(
getCandidateSettings(Settings.System.class),
newHashSet(SystemSettings.SETTINGS_TO_BACKUP),
- BACKUP_DENY_LIST_SYSTEM_SETTINGS);
+ getBackUpDenyListSystemSettings());
}
@Test
@@ -937,6 +887,69 @@
checkSettingsBackedUpOrDenied(allSettings, keys, BACKUP_DENY_LIST_SECURE_SETTINGS);
}
+ /**
+ * The following denylists contain settings that should *not* be backed up and restored to
+ * another device. As a general rule, anything that is not user configurable should be
+ * denied (and conversely, things that *are* user configurable *should* be backed up)
+ */
+ private static Set<String> getBackUpDenyListSystemSettings() {
+ Set<String> settings =
+ newHashSet(
+ Settings.System.ADVANCED_SETTINGS, // candidate for backup?
+ Settings.System.ALARM_ALERT_CACHE, // internal cache
+ Settings.System.APPEND_FOR_LAST_AUDIBLE, // suffix deprecated since API 2
+ Settings.System.EGG_MODE, // I am the lolrus
+ Settings.System.END_BUTTON_BEHAVIOR, // bug?
+ Settings.System
+ .HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY,
+ // candidate for backup?
+ Settings.System.LOCKSCREEN_DISABLED, // ?
+ Settings.System.MEDIA_BUTTON_RECEIVER, // candidate for backup?
+ Settings.System.MUTE_STREAMS_AFFECTED, // candidate for backup?
+ Settings.System.NOTIFICATION_SOUND_CACHE, // internal cache
+ Settings.System.POINTER_LOCATION, // backup candidate?
+ Settings.System.DEBUG_ENABLE_ENHANCED_CALL_BLOCKING,
+ // used for testing only
+ Settings.System.RINGTONE_CACHE, // internal cache
+ Settings.System.SCREEN_BRIGHTNESS, // removed in P
+ Settings.System.SETUP_WIZARD_HAS_RUN, // Only used by SuW
+ Settings.System.SHOW_GTALK_SERVICE_STATUS, // candidate for backup?
+ Settings.System.SHOW_TOUCHES,
+ Settings.System.SHOW_KEY_PRESSES,
+ Settings.System.SHOW_ROTARY_INPUT,
+ Settings.System.SIP_ADDRESS_ONLY, // value, not a setting
+ Settings.System.SIP_ALWAYS, // value, not a setting
+ Settings.System.SYSTEM_LOCALES, // bug?
+ Settings.System.USER_ROTATION, // backup candidate?
+ Settings.System.VIBRATE_IN_SILENT, // deprecated?
+ Settings.System.VOLUME_ACCESSIBILITY,
+ // used internally, changing value will
+ // not change volume
+ Settings.System.VOLUME_ALARM, // deprecated since API 2?
+ Settings.System.VOLUME_ASSISTANT, // candidate for backup?
+ Settings.System.VOLUME_BLUETOOTH_SCO, // deprecated since API 2?
+ Settings.System.VOLUME_MASTER, // candidate for backup?
+ Settings.System.VOLUME_MUSIC, // deprecated since API 2?
+ Settings.System.VOLUME_NOTIFICATION, // deprecated since API 2?
+ Settings.System.VOLUME_RING, // deprecated since API 2?
+ Settings.System.VOLUME_SYSTEM, // deprecated since API 2?
+ Settings.System.VOLUME_VOICE, // deprecated since API 2?
+ Settings.System.WHEN_TO_MAKE_WIFI_CALLS, // bug?
+ Settings.System.WINDOW_ORIENTATION_LISTENER_LOG, // used for debugging only
+ Settings.System.SCREEN_BRIGHTNESS_FLOAT,
+ Settings.System.SCREEN_BRIGHTNESS_FOR_ALS,
+ Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE,
+ Settings.System.WEAR_TTS_PREWARM_ENABLED,
+ Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ,
+ Settings.System.MULTI_AUDIO_FOCUS_ENABLED // form-factor/OEM specific
+ );
+ if (!Flags.backUpSmoothDisplayAndForcePeakRefreshRate()) {
+ settings.add(Settings.System.MIN_REFRESH_RATE);
+ settings.add(Settings.System.PEAK_REFRESH_RATE);
+ }
+ return settings;
+ }
+
private static void checkSettingsBackedUpOrDenied(
Set<String> settings, Set<String> settingsToBackup, Set<String> denylist) {
Set<String> settingsNotBackedUp = difference(settings, settingsToBackup);
diff --git a/packages/SystemUI/aconfig/predictive_back.aconfig b/packages/SystemUI/aconfig/predictive_back.aconfig
new file mode 100644
index 0000000..1ad1666
--- /dev/null
+++ b/packages/SystemUI/aconfig/predictive_back.aconfig
@@ -0,0 +1,22 @@
+package: "com.android.systemui"
+
+flag {
+ name: "predictive_back_sysui"
+ namespace: "systemui"
+ description: "Predictive Back Dispatching for SysUI"
+ bug: "309545085"
+}
+
+flag {
+ name: "predictive_back_animate_shade"
+ namespace: "systemui"
+ description: "Enable Shade Animations"
+ bug: "309545085"
+}
+
+flag {
+ name: "predictive_back_animate_bouncer"
+ namespace: "systemui"
+ description: "Enable Predictive Back Animation in Bouncer"
+ bug: "309545085"
+}
\ No newline at end of file
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index aa0903c..5b21854 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -165,7 +165,7 @@
name: "qs_new_tiles"
namespace: "systemui"
description: "Use the new tiles in the Quick Settings. Should have no behavior changes."
- bug: "241772429"
+ bug: "311147395"
}
flag {
@@ -308,6 +308,13 @@
}
flag {
+ name: "run_fingerprint_detect_on_dismissible_keyguard"
+ namespace: "systemui"
+ description: "Run fingerprint detect instead of authenticate if the keyguard is dismissible."
+ bug: "311145851"
+}
+
+flag {
name: "bluetooth_qs_tile_dialog_auto_on_toggle"
namespace: "systemui"
description: "Displays the auto on toggle in the bluetooth QS tile dialog"
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/ShaderUtilLibrary.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/ShaderUtilLibrary.kt
index 23fcb69..867bbb7d 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/ShaderUtilLibrary.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/ShaderUtilLibrary.kt
@@ -65,12 +65,33 @@
return dest;
}
- // Return range [-1, 1].
+ // Integer mod. GLSL es 1.0 doesn't have integer mod :(
+ int imod(int a, int b) {
+ return a - (b * (a / b));
+ }
+
+ ivec3 imod(ivec3 a, int b) {
+ return ivec3(imod(a.x, b), imod(a.y, b), imod(a.z, b));
+ }
+
+ // Integer based hash function with the return range of [-1, 1].
vec3 hash(vec3 p) {
- p = fract(p * vec3(.3456, .1234, .9876));
- p += dot(p, p.yxz + 43.21);
- p = (p.xxy + p.yxx) * p.zyx;
- return (fract(sin(p) * 4567.1234567) - .5) * 2.;
+ ivec3 v = ivec3(p);
+ v = v * 1671731 + 10139267;
+
+ v.x += v.y * v.z;
+ v.y += v.z * v.x;
+ v.z += v.x * v.y;
+
+ ivec3 v2 = v / 65536; // v >> 16
+ v = imod((10 - imod((v + v2), 10)), 10); // v ^ v2
+
+ v.x += v.y * v.z;
+ v.y += v.z * v.x;
+ v.z += v.x * v.y;
+
+ // Use sin and cos to map the range to [-1, 1].
+ return vec3(sin(float(v.x)), cos(float(v.y)), sin(float(v.z)));
}
// Skew factors (non-uniform).
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
index 1fc2843..c8461d2 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
@@ -45,10 +45,10 @@
import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants
import com.android.systemui.classifier.FalsingA11yDelegate
import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
import com.android.systemui.log.SessionTracker
@@ -140,7 +140,7 @@
@Mock private lateinit var viewMediatorCallback: ViewMediatorCallback
@Mock private lateinit var audioManager: AudioManager
@Mock private lateinit var mSelectedUserInteractor: SelectedUserInteractor
- @Mock private lateinit var faceAuthInteractor: KeyguardFaceAuthInteractor
+ @Mock private lateinit var faceAuthInteractor: DeviceEntryFaceAuthInteractor
@Mock private lateinit var faceAuthAccessibilityDelegate: FaceAuthAccessibilityDelegate
@Mock private lateinit var deviceProvisionedController: DeviceProvisionedController
@Mock private lateinit var postureController: DevicePostureController
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index e5da1f8..36aa441 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -85,10 +85,10 @@
import com.android.systemui.biometrics.ui.viewmodel.DeviceEntryUdfpsTouchOverlayViewModel;
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.keyguard.ScreenLifecycle;
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.log.SessionTracker;
import com.android.systemui.plugins.FalsingManager;
@@ -336,7 +336,7 @@
mSessionTracker,
mAlternateBouncerInteractor,
mInputManager,
- mock(KeyguardFaceAuthInteractor.class),
+ mock(DeviceEntryFaceAuthInteractor.class),
mUdfpsKeyguardAccessibilityDelegate,
mSelectedUserInteractor,
mFpsUnlockTracker,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt
index 1f8854f..335ac9d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt
@@ -32,11 +32,11 @@
import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants
import com.android.systemui.bouncer.ui.BouncerView
import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.FakeTrustRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
@@ -111,7 +111,7 @@
FakeTrustRepository(),
testScope.backgroundScope,
mSelectedUserInteractor,
- mock(KeyguardFaceAuthInteractor::class.java),
+ mock(DeviceEntryFaceAuthInteractor::class.java),
)
mAlternateBouncerInteractor =
AlternateBouncerInteractor(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
index 99c1874..93ba6a4 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
@@ -25,7 +25,7 @@
import com.android.systemui.authentication.shared.model.AuthenticationPatternCoordinate
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
import com.android.systemui.res.R
import com.android.systemui.scene.SceneTestUtils
import com.google.common.truth.Truth.assertThat
@@ -46,7 +46,7 @@
@RunWith(AndroidJUnit4::class)
class BouncerInteractorTest : SysuiTestCase() {
- @Mock private lateinit var keyguardFaceAuthInteractor: KeyguardFaceAuthInteractor
+ @Mock private lateinit var mDeviceEntryFaceAuthInteractor: DeviceEntryFaceAuthInteractor
private val utils = SceneTestUtils(this)
private val testScope = utils.testScope
@@ -67,7 +67,7 @@
underTest =
utils.bouncerInteractor(
authenticationInteractor = authenticationInteractor,
- keyguardFaceAuthInteractor = keyguardFaceAuthInteractor,
+ deviceEntryFaceAuthInteractor = mDeviceEntryFaceAuthInteractor,
)
}
@@ -306,7 +306,7 @@
fun intentionalUserInputEvent_notifiesFaceAuthInteractor() =
testScope.runTest {
underTest.onIntentionalUserInput()
- verify(keyguardFaceAuthInteractor).onPrimaryBouncerUserInput()
+ verify(mDeviceEntryFaceAuthInteractor).onPrimaryBouncerUserInput()
}
companion object {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
index bdf5041..c8560c3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
@@ -26,9 +26,9 @@
import com.android.systemui.bouncer.ui.BouncerView
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.repository.TrustRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import com.android.systemui.utils.os.FakeHandler
@@ -54,7 +54,7 @@
@Mock private lateinit var dismissCallbackRegistry: DismissCallbackRegistry
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
@Mock private lateinit var mSelectedUserInteractor: SelectedUserInteractor
- @Mock private lateinit var faceAuthInteractor: KeyguardFaceAuthInteractor
+ @Mock private lateinit var faceAuthInteractor: DeviceEntryFaceAuthInteractor
private val mainHandler = FakeHandler(Looper.getMainLooper())
private lateinit var underTest: PrimaryBouncerInteractor
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt
index a3bf3f4..a0c2acc 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt
@@ -30,9 +30,9 @@
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.repository.TrustRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
@@ -63,7 +63,7 @@
@Mock private lateinit var dismissCallbackRegistry: DismissCallbackRegistry
@Mock private lateinit var mSelectedUserInteractor: SelectedUserInteractor
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
- @Mock private lateinit var faceAuthInteractor: KeyguardFaceAuthInteractor
+ @Mock private lateinit var faceAuthInteractor: DeviceEntryFaceAuthInteractor
lateinit var bouncerInteractor: PrimaryBouncerInteractor
private val mainHandler = FakeHandler(Looper.getMainLooper())
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
similarity index 96%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
index 941d67f..6a14220 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.keyguard.data.repository
+package com.android.systemui.deviceentry.data.repository
import android.app.StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP
import android.app.StatusBarManager.SESSION_KEYGUARD
@@ -37,10 +37,6 @@
import androidx.test.filters.SmallTest
import com.android.internal.logging.InstanceId.fakeInstanceId
import com.android.internal.logging.UiEventLogger
-import com.android.keyguard.FaceAuthUiEvent
-import com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_TRIGGERED_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN
-import com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_TRIGGERED_NOTIFICATION_PANEL_CLICKED
-import com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository
@@ -53,21 +49,32 @@
import com.android.systemui.coroutines.FlowValue
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
+import com.android.systemui.deviceentry.shared.FaceAuthUiEvent
+import com.android.systemui.deviceentry.shared.FaceAuthUiEvent.FACE_AUTH_TRIGGERED_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN
+import com.android.systemui.deviceentry.shared.FaceAuthUiEvent.FACE_AUTH_TRIGGERED_NOTIFICATION_PANEL_CLICKED
+import com.android.systemui.deviceentry.shared.FaceAuthUiEvent.FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER
+import com.android.systemui.deviceentry.shared.model.ErrorFaceAuthenticationStatus
+import com.android.systemui.deviceentry.shared.model.FaceAuthenticationStatus
+import com.android.systemui.deviceentry.shared.model.FaceDetectionStatus
+import com.android.systemui.deviceentry.shared.model.HelpFaceAuthenticationStatus
+import com.android.systemui.deviceentry.shared.model.SuccessFaceAuthenticationStatus
import com.android.systemui.display.data.repository.FakeDisplayRepository
import com.android.systemui.display.data.repository.display
import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags.KEYGUARD_WM_STATE_REFACTOR
+import com.android.systemui.keyguard.data.repository.BiometricType
+import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
+import com.android.systemui.keyguard.data.repository.FakeCommandQueue
+import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.data.repository.FakeTrustRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
-import com.android.systemui.keyguard.shared.model.ErrorFaceAuthenticationStatus
-import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus
-import com.android.systemui.keyguard.shared.model.FaceDetectionStatus
-import com.android.systemui.keyguard.shared.model.HelpFaceAuthenticationStatus
import com.android.systemui.keyguard.shared.model.KeyguardState
-import com.android.systemui.keyguard.shared.model.SuccessFaceAuthenticationStatus
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.log.FaceAuthenticationLogger
diff --git a/packages/SystemUI/shared/Android.bp b/packages/SystemUI/shared/Android.bp
index 2b41178..3a26ebf 100644
--- a/packages/SystemUI/shared/Android.bp
+++ b/packages/SystemUI/shared/Android.bp
@@ -66,6 +66,7 @@
"kotlinx_coroutines",
"dagger2",
"jsr330",
+ "com_android_systemui_shared_flags_lib",
],
resource_dirs: [
"res",
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
index 131eb6b..c08b083 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
@@ -20,10 +20,11 @@
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
+import static com.android.systemui.shared.Flags.shadeAllowBackGesture;
+
import android.annotation.IntDef;
import android.content.Context;
import android.content.res.Resources;
-import android.os.SystemProperties;
import android.view.ViewConfiguration;
import android.view.WindowManagerPolicyConstants;
@@ -132,8 +133,7 @@
SYSUI_STATE_WAKEFULNESS_TRANSITION | SYSUI_STATE_AWAKE;
// Whether the back gesture is allowed (or ignored) by the Shade
- public static final boolean ALLOW_BACK_GESTURE_IN_SHADE = SystemProperties.getBoolean(
- "persist.wm.debug.shade_allow_back_gesture", false);
+ public static final boolean ALLOW_BACK_GESTURE_IN_SHADE = shadeAllowBackGesture();
@Retention(RetentionPolicy.SOURCE)
@IntDef({SYSUI_STATE_SCREEN_PINNING,
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 5e35e77..b6b8c2a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -78,10 +78,10 @@
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.classifier.FalsingA11yDelegate;
import com.android.systemui.classifier.FalsingCollector;
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor;
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.log.SessionTracker;
import com.android.systemui.plugins.ActivityStarter;
@@ -135,7 +135,7 @@
private final SessionTracker mSessionTracker;
private final Optional<SideFpsController> mSideFpsController;
private final FalsingA11yDelegate mFalsingA11yDelegate;
- private final KeyguardFaceAuthInteractor mKeyguardFaceAuthInteractor;
+ private final DeviceEntryFaceAuthInteractor mDeviceEntryFaceAuthInteractor;
private final BouncerMessageInteractor mBouncerMessageInteractor;
private int mTranslationY;
private final KeyguardTransitionInteractor mKeyguardTransitionInteractor;
@@ -216,7 +216,7 @@
@Override
public void onUserInput() {
mBouncerMessageInteractor.onPrimaryBouncerUserInput();
- mKeyguardFaceAuthInteractor.onPrimaryBouncerUserInput();
+ mDeviceEntryFaceAuthInteractor.onPrimaryBouncerUserInput();
}
@Override
@@ -347,11 +347,11 @@
private final SwipeListener mSwipeListener = new SwipeListener() {
@Override
public void onSwipeUp() {
- if (mKeyguardFaceAuthInteractor.canFaceAuthRun()) {
+ if (mDeviceEntryFaceAuthInteractor.canFaceAuthRun()) {
mKeyguardSecurityCallback.userActivity();
}
- mKeyguardFaceAuthInteractor.onSwipeUpOnBouncer();
- if (mKeyguardFaceAuthInteractor.isFaceAuthEnabledAndEnrolled()) {
+ mDeviceEntryFaceAuthInteractor.onSwipeUpOnBouncer();
+ if (mDeviceEntryFaceAuthInteractor.isFaceAuthEnabledAndEnrolled()) {
mUpdateMonitor.requestActiveUnlock(
ActiveUnlockConfig.ActiveUnlockRequestOrigin.UNLOCK_INTENT,
"swipeUpOnBouncer");
@@ -456,7 +456,7 @@
TelephonyManager telephonyManager,
ViewMediatorCallback viewMediatorCallback,
AudioManager audioManager,
- KeyguardFaceAuthInteractor keyguardFaceAuthInteractor,
+ DeviceEntryFaceAuthInteractor deviceEntryFaceAuthInteractor,
BouncerMessageInteractor bouncerMessageInteractor,
Provider<JavaAdapter> javaAdapter,
SelectedUserInteractor selectedUserInteractor,
@@ -495,7 +495,7 @@
mTelephonyManager = telephonyManager;
mViewMediatorCallback = viewMediatorCallback;
mAudioManager = audioManager;
- mKeyguardFaceAuthInteractor = keyguardFaceAuthInteractor;
+ mDeviceEntryFaceAuthInteractor = deviceEntryFaceAuthInteractor;
mBouncerMessageInteractor = bouncerMessageInteractor;
mSelectedUserInteractor = selectedUserInteractor;
mDeviceEntryInteractor = deviceEntryInteractor;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 4d84d0b..e59868e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -113,24 +113,26 @@
import com.android.settingslib.fuelgauge.BatteryStatus;
import com.android.systemui.CoreStartable;
import com.android.systemui.Dumpable;
+import com.android.systemui.Flags;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.biometrics.FingerprintInteractiveToAuthProvider;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.deviceentry.data.repository.FaceWakeUpTriggersConfig;
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor;
+import com.android.systemui.deviceentry.domain.interactor.FaceAuthenticationListener;
+import com.android.systemui.deviceentry.shared.model.AcquiredFaceAuthenticationStatus;
+import com.android.systemui.deviceentry.shared.model.ErrorFaceAuthenticationStatus;
+import com.android.systemui.deviceentry.shared.model.FaceAuthenticationStatus;
+import com.android.systemui.deviceentry.shared.model.FaceDetectionStatus;
+import com.android.systemui.deviceentry.shared.model.FailedFaceAuthenticationStatus;
+import com.android.systemui.deviceentry.shared.model.HelpFaceAuthenticationStatus;
+import com.android.systemui.deviceentry.shared.model.SuccessFaceAuthenticationStatus;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.dump.DumpsysTableLogger;
-import com.android.systemui.keyguard.domain.interactor.FaceAuthenticationListener;
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
import com.android.systemui.keyguard.shared.constants.TrustAgentUiEvent;
-import com.android.systemui.keyguard.shared.model.AcquiredFaceAuthenticationStatus;
-import com.android.systemui.keyguard.shared.model.ErrorFaceAuthenticationStatus;
-import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus;
-import com.android.systemui.keyguard.shared.model.FaceDetectionStatus;
-import com.android.systemui.keyguard.shared.model.FailedFaceAuthenticationStatus;
-import com.android.systemui.keyguard.shared.model.HelpFaceAuthenticationStatus;
-import com.android.systemui.keyguard.shared.model.SuccessFaceAuthenticationStatus;
import com.android.systemui.log.SessionTracker;
import com.android.systemui.plugins.clocks.WeatherData;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -359,7 +361,7 @@
@Nullable
private final BiometricManager mBiometricManager;
@Nullable
- private KeyguardFaceAuthInteractor mFaceAuthInteractor;
+ private DeviceEntryFaceAuthInteractor mFaceAuthInteractor;
private final DevicePostureController mDevicePostureController;
private final TaskStackChangeListeners mTaskStackChangeListeners;
private final IActivityTaskManager mActivityTaskManager;
@@ -373,6 +375,7 @@
private List<SubscriptionInfo> mSubscriptionInfo;
@VisibleForTesting
protected int mFingerprintRunningState = BIOMETRIC_STATE_STOPPED;
+ private boolean mFingerprintDetectRunning;
private boolean mIsDreaming;
private boolean mLogoutEnabled;
private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -986,6 +989,7 @@
final boolean wasCancellingRestarting = mFingerprintRunningState
== BIOMETRIC_STATE_CANCELLING_RESTARTING;
mFingerprintRunningState = BIOMETRIC_STATE_STOPPED;
+ mFingerprintDetectRunning = false;
if (wasCancellingRestarting) {
KeyguardUpdateMonitor.this.updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
} else {
@@ -1094,6 +1098,9 @@
boolean wasRunning = mFingerprintRunningState == BIOMETRIC_STATE_RUNNING;
boolean isRunning = fingerprintRunningState == BIOMETRIC_STATE_RUNNING;
mFingerprintRunningState = fingerprintRunningState;
+ if (mFingerprintRunningState == BIOMETRIC_STATE_STOPPED) {
+ mFingerprintDetectRunning = false;
+ }
mLogger.logFingerprintRunningState(mFingerprintRunningState);
// Clients of KeyguardUpdateMonitor don't care about the internal state about the
// asynchronousness of the cancel cycle. So only notify them if the actually running state
@@ -1266,14 +1273,14 @@
return getFaceAuthInteractor() != null && getFaceAuthInteractor().isRunning();
}
- private @Nullable KeyguardFaceAuthInteractor getFaceAuthInteractor() {
+ private @Nullable DeviceEntryFaceAuthInteractor getFaceAuthInteractor() {
return mFaceAuthInteractor;
}
/**
* Set the face auth interactor that should be used for initiating face authentication.
*/
- public void setFaceAuthInteractor(KeyguardFaceAuthInteractor faceAuthInteractor) {
+ public void setFaceAuthInteractor(DeviceEntryFaceAuthInteractor faceAuthInteractor) {
if (mFaceAuthInteractor != null) {
mFaceAuthInteractor.unregisterListener(mFaceAuthenticationListener);
}
@@ -1356,7 +1363,7 @@
* @return whether the current user has been authenticated with face. This may be true
* on the lockscreen if the user doesn't have bypass enabled.
*
- * @deprecated Use {@link KeyguardFaceAuthInteractor#isAuthenticated()}
+ * @deprecated Use {@link DeviceEntryFaceAuthInteractor#isAuthenticated()}
*/
@Deprecated
public boolean getIsFaceAuthenticated() {
@@ -1387,7 +1394,7 @@
/**
* Returns whether the user is unlocked with face.
- * @deprecated Use {@link KeyguardFaceAuthInteractor#isAuthenticated()} instead
+ * @deprecated Use {@link DeviceEntryFaceAuthInteractor#isAuthenticated()} instead
*/
@Deprecated
public boolean isCurrentUserUnlockedWithFace() {
@@ -2066,6 +2073,7 @@
@VisibleForTesting
void resetBiometricListeningState() {
mFingerprintRunningState = BIOMETRIC_STATE_STOPPED;
+ mFingerprintDetectRunning = false;
}
@VisibleForTesting
@@ -2457,7 +2465,7 @@
/**
* @return true if there's at least one face enrolled
- * @deprecated Use {@link KeyguardFaceAuthInteractor#isFaceAuthEnabledAndEnrolled()}
+ * @deprecated Use {@link DeviceEntryFaceAuthInteractor#isFaceAuthEnabledAndEnrolled()}
*/
@Deprecated
public boolean isFaceEnabledAndEnrolled() {
@@ -2504,8 +2512,10 @@
return;
}
final boolean shouldListenForFingerprint = shouldListenForFingerprint(isUdfpsSupported());
- final boolean runningOrRestarting = mFingerprintRunningState == BIOMETRIC_STATE_RUNNING
+ final boolean running = mFingerprintRunningState == BIOMETRIC_STATE_RUNNING;
+ final boolean runningOrRestarting = running
|| mFingerprintRunningState == BIOMETRIC_STATE_CANCELLING_RESTARTING;
+ final boolean runDetect = shouldRunFingerprintDetect();
if (runningOrRestarting && !shouldListenForFingerprint) {
if (action == BIOMETRIC_ACTION_START) {
mLogger.v("Ignoring stopListeningForFingerprint()");
@@ -2517,10 +2527,24 @@
mLogger.v("Ignoring startListeningForFingerprint()");
return;
}
- startListeningForFingerprint();
+ startListeningForFingerprint(runDetect);
+ } else if (running && runDetect && !mFingerprintDetectRunning) {
+ if (action == BIOMETRIC_ACTION_STOP) {
+ mLogger.v("Ignoring startListeningForFingerprint(detect)");
+ return;
+ }
+ // stop running authentication and start running fingerprint detection
+ stopListeningForFingerprint();
+ startListeningForFingerprint(true);
}
}
+ private boolean shouldRunFingerprintDetect() {
+ return !isUnlockingWithFingerprintAllowed()
+ || (Flags.runFingerprintDetectOnDismissibleKeyguard()
+ && getUserCanSkipBouncer(mSelectedUserInteractor.getSelectedUserId()));
+ }
+
/**
* If a user is encrypted or not.
* This is NOT related to the lock screen being visible or not.
@@ -2776,7 +2800,6 @@
&& biometricEnabledForUser
&& !isUserInLockdown(user);
final boolean strongerAuthRequired = !isUnlockingWithFingerprintAllowed();
- final boolean isSideFps = isSfpsSupported() && isSfpsEnrolled();
final boolean shouldListenBouncerState =
!strongerAuthRequired || !mPrimaryBouncerIsOrWillBeShowing;
@@ -2822,7 +2845,7 @@
/**
* If face auth is allows to scan on this exact moment.
*
- * @deprecated Use {@link KeyguardFaceAuthInteractor#canFaceAuthRun()}
+ * @deprecated Use {@link DeviceEntryFaceAuthInteractor#canFaceAuthRun()}
*/
@Deprecated
public boolean shouldListenForFace() {
@@ -2839,7 +2862,7 @@
}
}
- private void startListeningForFingerprint() {
+ private void startListeningForFingerprint(boolean runDetect) {
final int userId = mSelectedUserInteractor.getSelectedUserId();
final boolean unlockPossible = isUnlockWithFingerprintPossible(userId);
if (mFingerprintCancelSignal != null) {
@@ -2869,18 +2892,20 @@
mFingerprintInteractiveToAuthProvider.getVendorExtension(userId));
}
- if (!isUnlockingWithFingerprintAllowed()) {
+ if (runDetect) {
mLogger.v("startListeningForFingerprint - detect");
mFpm.detectFingerprint(
mFingerprintCancelSignal,
mFingerprintDetectionCallback,
fingerprintAuthenticateOptions);
+ mFingerprintDetectRunning = true;
} else {
mLogger.v("startListeningForFingerprint");
mFpm.authenticate(null /* crypto */, mFingerprintCancelSignal,
mFingerprintAuthenticationCallback,
null /* handler */,
fingerprintAuthenticateOptions);
+ mFingerprintDetectRunning = false;
}
setFingerprintRunningState(BIOMETRIC_STATE_RUNNING);
}
@@ -2891,7 +2916,7 @@
}
/**
- * @deprecated Use {@link KeyguardFaceAuthInteractor#isLockedOut()}
+ * @deprecated Use {@link DeviceEntryFaceAuthInteractor#isLockedOut()}
*/
@Deprecated
public boolean isFaceLockedOut() {
@@ -2932,7 +2957,7 @@
}
/**
- * @deprecated Use {@link KeyguardFaceAuthInteractor#isFaceAuthEnabledAndEnrolled()}
+ * @deprecated Use {@link DeviceEntryFaceAuthInteractor#isFaceAuthEnabledAndEnrolled()}
*/
@VisibleForTesting
@Deprecated
@@ -3876,6 +3901,7 @@
mSelectedUserInteractor.getSelectedUserId()));
pw.println(" getUserUnlockedWithBiometric()="
+ getUserUnlockedWithBiometric(mSelectedUserInteractor.getSelectedUserId()));
+ pw.println(" mFingerprintDetectRunning=" + mFingerprintDetectRunning);
pw.println(" SIM States:");
for (SimData data : mSimDatas.values()) {
pw.println(" " + data.toString());
diff --git a/packages/SystemUI/src/com/android/systemui/back/domain/interactor/BackActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/back/domain/interactor/BackActionInteractor.kt
index 066cba23..6076f32 100644
--- a/packages/SystemUI/src/com/android/systemui/back/domain/interactor/BackActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/back/domain/interactor/BackActionInteractor.kt
@@ -22,10 +22,9 @@
import android.window.OnBackInvokedDispatcher
import android.window.WindowOnBackInvokedDispatcher
import com.android.systemui.CoreStartable
+import com.android.systemui.Flags.predictiveBackAnimateShade
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor
import com.android.systemui.shade.QuickSettingsController
@@ -48,14 +47,13 @@
private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager,
private val shadeController: ShadeController,
private val notificationShadeWindowController: NotificationShadeWindowController,
- private val windowRootViewVisibilityInteractor: WindowRootViewVisibilityInteractor,
- featureFlags: FeatureFlags,
+ private val windowRootViewVisibilityInteractor: WindowRootViewVisibilityInteractor
) : CoreStartable {
private var isCallbackRegistered = false
private val callback =
- if (featureFlags.isEnabled(Flags.WM_SHADE_ANIMATE_BACK_GESTURE)) {
+ if (predictiveBackAnimateShade()) {
/**
* New callback that handles back gesture invoked, cancel, progress and provides
* feedback via Shade animation.
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
index 6345312..45967c6 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
@@ -32,13 +32,13 @@
import com.android.settingslib.Utils
import com.android.systemui.CoreStartable
import com.android.systemui.Flags.lightRevealMigration
-import com.android.systemui.res.R
import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.log.core.LogLevel
import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.res.R
import com.android.systemui.statusbar.CircleReveal
import com.android.systemui.statusbar.LiftReveal
import com.android.systemui.statusbar.LightRevealEffect
@@ -50,6 +50,7 @@
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.ViewController
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import java.io.PrintWriter
import javax.inject.Inject
import javax.inject.Provider
@@ -62,6 +63,7 @@
*
* The ripple uses the accent color of the current theme.
*/
+@ExperimentalCoroutinesApi
@SysUISingleton
class AuthRippleController @Inject constructor(
private val sysuiContext: Context,
@@ -75,7 +77,6 @@
private val udfpsControllerProvider: Provider<UdfpsController>,
private val statusBarStateController: StatusBarStateController,
private val displayMetrics: DisplayMetrics,
- private val featureFlags: FeatureFlags,
private val logger: KeyguardLogger,
private val biometricUnlockController: BiometricUnlockController,
private val lightRevealScrim: LightRevealScrim,
@@ -313,6 +314,18 @@
mView.fadeDwellRipple()
}
}
+
+ override fun onBiometricDetected(
+ userId: Int,
+ biometricSourceType: BiometricSourceType,
+ isStrongBiometric: Boolean
+ ) {
+ // TODO (b/309804148): add support detect auth ripple for deviceEntryUdfpsRefactor
+ if (!DeviceEntryUdfpsRefactor.isEnabled &&
+ keyguardUpdateMonitor.getUserCanSkipBouncer(userId)) {
+ showUnlockRipple(biometricSourceType)
+ }
+ }
}
private val configurationChangedListener =
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FaceAuthAccessibilityDelegate.kt b/packages/SystemUI/src/com/android/systemui/biometrics/FaceAuthAccessibilityDelegate.kt
index cb75049..3ea1632 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/FaceAuthAccessibilityDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/FaceAuthAccessibilityDelegate.kt
@@ -22,7 +22,7 @@
import android.view.accessibility.AccessibilityNodeInfo
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
import com.android.systemui.res.R
import javax.inject.Inject
@@ -35,7 +35,7 @@
@Inject
constructor(
@Main private val resources: Resources,
- private val faceAuthInteractor: KeyguardFaceAuthInteractor,
+ private val faceAuthInteractor: DeviceEntryFaceAuthInteractor,
) : View.AccessibilityDelegate() {
override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfo) {
super.onInitializeAccessibilityNodeInfo(host, info)
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 2fd13b3..d664637 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -80,11 +80,11 @@
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor;
import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor;
import com.android.systemui.doze.DozeReceiver;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.ScreenLifecycle;
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.log.SessionTracker;
import com.android.systemui.plugins.FalsingManager;
@@ -149,7 +149,7 @@
@NonNull private final DumpManager mDumpManager;
@NonNull private final SystemUIDialogManager mDialogManager;
@NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
- @NonNull private final KeyguardFaceAuthInteractor mKeyguardFaceAuthInteractor;
+ @NonNull private final DeviceEntryFaceAuthInteractor mDeviceEntryFaceAuthInteractor;
@NonNull private final VibratorHelper mVibrator;
@NonNull private final FalsingManager mFalsingManager;
@NonNull private final PowerManager mPowerManager;
@@ -664,7 +664,7 @@
@NonNull SessionTracker sessionTracker,
@NonNull AlternateBouncerInteractor alternateBouncerInteractor,
@NonNull InputManager inputManager,
- @NonNull KeyguardFaceAuthInteractor keyguardFaceAuthInteractor,
+ @NonNull DeviceEntryFaceAuthInteractor deviceEntryFaceAuthInteractor,
@NonNull UdfpsKeyguardAccessibilityDelegate udfpsKeyguardAccessibilityDelegate,
@NonNull SelectedUserInteractor selectedUserInteractor,
@NonNull FpsUnlockTracker fpsUnlockTracker,
@@ -736,7 +736,7 @@
}
return Unit.INSTANCE;
});
- mKeyguardFaceAuthInteractor = keyguardFaceAuthInteractor;
+ mDeviceEntryFaceAuthInteractor = deviceEntryFaceAuthInteractor;
final UdfpsOverlayController mUdfpsOverlayController = new UdfpsOverlayController();
mFingerprintManager.setUdfpsOverlayController(mUdfpsOverlayController);
@@ -1027,7 +1027,7 @@
if (!mOnFingerDown) {
playStartHaptic();
- mKeyguardFaceAuthInteractor.onUdfpsSensorTouched();
+ mDeviceEntryFaceAuthInteractor.onUdfpsSensorTouched();
}
mOnFingerDown = true;
mFingerprintManager.onPointerDown(requestId, mSensorProps.sensorId, pointerId, x, y,
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
index 81d822f..c8ce245 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
@@ -29,7 +29,7 @@
import com.android.systemui.classifier.domain.interactor.FalsingInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.res.R
import javax.inject.Inject
@@ -52,7 +52,7 @@
@Application private val applicationContext: Context,
private val repository: BouncerRepository,
private val authenticationInteractor: AuthenticationInteractor,
- private val keyguardFaceAuthInteractor: KeyguardFaceAuthInteractor,
+ private val deviceEntryFaceAuthInteractor: DeviceEntryFaceAuthInteractor,
private val falsingInteractor: FalsingInteractor,
private val powerInteractor: PowerInteractor,
private val simBouncerInteractor: SimBouncerInteractor,
@@ -100,7 +100,7 @@
* user's pocket or by the user's face while holding their device up to their ear.
*/
fun onIntentionalUserInput() {
- keyguardFaceAuthInteractor.onPrimaryBouncerUserInput()
+ deviceEntryFaceAuthInteractor.onPrimaryBouncerUserInput()
powerInteractor.onUserTouch()
falsingInteractor.updateFalseConfidence(FalsingClassifier.Result.passed(0.6))
}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt
index b587ed8..ef4554c 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt
@@ -30,9 +30,9 @@
import com.android.systemui.bouncer.shared.model.Message
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.deviceentry.data.repository.DeviceEntryFaceAuthRepository
import com.android.systemui.flags.SystemPropertiesHelper
import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
-import com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository
import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.TrustRepository
import com.android.systemui.res.R.string.bouncer_face_not_recognized
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt
index 621ca5d..654fa22 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt
@@ -38,9 +38,9 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.repository.TrustRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.res.R
import com.android.systemui.shared.system.SysUiStatsLog
@@ -77,7 +77,7 @@
private val trustRepository: TrustRepository,
@Application private val applicationScope: CoroutineScope,
private val selectedUserInteractor: SelectedUserInteractor,
- private val keyguardFaceAuthInteractor: KeyguardFaceAuthInteractor,
+ private val deviceEntryFaceAuthInteractor: DeviceEntryFaceAuthInteractor,
) {
private val passiveAuthBouncerDelay =
context.resources.getInteger(R.integer.primary_bouncer_passive_auth_delay).toLong()
@@ -429,7 +429,7 @@
keyguardUpdateMonitor.canTriggerActiveUnlockBasedOnDeviceState()
return !needsFullscreenBouncer() &&
- (keyguardFaceAuthInteractor.canFaceAuthRun() || canRunActiveUnlock)
+ (deviceEntryFaceAuthInteractor.canFaceAuthRun() || canRunActiveUnlock)
}
companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/DeviceEntryModule.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/DeviceEntryModule.kt
index b915418..71b5ab2 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/DeviceEntryModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/DeviceEntryModule.kt
@@ -1,6 +1,7 @@
package com.android.systemui.deviceentry
import com.android.systemui.deviceentry.data.repository.DeviceEntryRepositoryModule
+import com.android.systemui.deviceentry.data.repository.FaceWakeUpTriggersConfigModule
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import dagger.Module
import dagger.multibindings.Multibinds
@@ -9,6 +10,7 @@
includes =
[
DeviceEntryRepositoryModule::class,
+ FaceWakeUpTriggersConfigModule::class,
],
)
abstract class DeviceEntryModule {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt
similarity index 95%
rename from packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt
rename to packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt
index 17d7836..7a70c4a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.keyguard.data.repository
+package com.android.systemui.deviceentry.data.repository
import android.app.StatusBarManager
import android.content.Context
@@ -22,7 +22,6 @@
import android.os.CancellationSignal
import com.android.internal.logging.InstanceId
import com.android.internal.logging.UiEventLogger
-import com.android.keyguard.FaceAuthUiEvent
import com.android.systemui.Dumpable
import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
@@ -32,19 +31,27 @@
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.deviceentry.shared.FaceAuthUiEvent
+import com.android.systemui.deviceentry.shared.model.AcquiredFaceAuthenticationStatus
+import com.android.systemui.deviceentry.shared.model.ErrorFaceAuthenticationStatus
+import com.android.systemui.deviceentry.shared.model.FaceAuthenticationStatus
+import com.android.systemui.deviceentry.shared.model.FaceDetectionStatus
+import com.android.systemui.deviceentry.shared.model.FailedFaceAuthenticationStatus
+import com.android.systemui.deviceentry.shared.model.HelpFaceAuthenticationStatus
+import com.android.systemui.deviceentry.shared.model.SuccessFaceAuthenticationStatus
import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
+import com.android.systemui.keyguard.data.repository.BiometricType
+import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
+import com.android.systemui.keyguard.data.repository.FaceAuthTableLog
+import com.android.systemui.keyguard.data.repository.FaceDetectTableLog
+import com.android.systemui.keyguard.data.repository.KeyguardRepository
+import com.android.systemui.keyguard.data.repository.TrustRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
-import com.android.systemui.keyguard.shared.model.AcquiredFaceAuthenticationStatus
-import com.android.systemui.keyguard.shared.model.ErrorFaceAuthenticationStatus
-import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus
-import com.android.systemui.keyguard.shared.model.FaceDetectionStatus
-import com.android.systemui.keyguard.shared.model.FailedFaceAuthenticationStatus
-import com.android.systemui.keyguard.shared.model.HelpFaceAuthenticationStatus
import com.android.systemui.keyguard.shared.model.KeyguardState
-import com.android.systemui.keyguard.shared.model.SuccessFaceAuthenticationStatus
import com.android.systemui.keyguard.shared.model.SysUiFaceAuthenticateOptions
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.log.FaceAuthenticationLogger
diff --git a/packages/SystemUI/src/com/android/keyguard/FaceWakeUpTriggersConfig.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/FaceWakeUpTriggersConfig.kt
similarity index 83%
rename from packages/SystemUI/src/com/android/keyguard/FaceWakeUpTriggersConfig.kt
rename to packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/FaceWakeUpTriggersConfig.kt
index 84a6b09..9d6718b 100644
--- a/packages/SystemUI/src/com/android/keyguard/FaceWakeUpTriggersConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/FaceWakeUpTriggersConfig.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,28 +14,35 @@
* limitations under the License.
*/
-package com.android.keyguard
+package com.android.systemui.deviceentry.data.repository
import android.content.res.Resources
import android.os.Build
import android.os.PowerManager
import com.android.systemui.Dumpable
-import com.android.systemui.res.R
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
import com.android.systemui.power.shared.model.WakeSleepReason
+import com.android.systemui.res.R
import com.android.systemui.util.settings.GlobalSettings
+import dagger.Binds
+import dagger.Module
import java.io.PrintWriter
import java.util.stream.Collectors
import javax.inject.Inject
/** Determines which device wake-ups should trigger passive authentication. */
+interface FaceWakeUpTriggersConfig {
+ fun shouldTriggerFaceAuthOnWakeUpFrom(@PowerManager.WakeReason pmWakeReason: Int): Boolean
+ fun shouldTriggerFaceAuthOnWakeUpFrom(wakeReason: WakeSleepReason): Boolean
+}
+
@SysUISingleton
-class FaceWakeUpTriggersConfig
+class FaceWakeUpTriggersConfigImpl
@Inject
constructor(@Main resources: Resources, globalSettings: GlobalSettings, dumpManager: DumpManager) :
- Dumpable {
+ Dumpable, FaceWakeUpTriggersConfig {
private val defaultTriggerFaceAuthOnWakeUpFrom: Set<Int> =
resources.getIntArray(R.array.config_face_auth_wake_up_triggers).toSet()
private val triggerFaceAuthOnWakeUpFrom: Set<Int>
@@ -65,11 +72,13 @@
dumpManager.registerDumpable(this)
}
- fun shouldTriggerFaceAuthOnWakeUpFrom(@PowerManager.WakeReason pmWakeReason: Int): Boolean {
+ override fun shouldTriggerFaceAuthOnWakeUpFrom(
+ @PowerManager.WakeReason pmWakeReason: Int
+ ): Boolean {
return triggerFaceAuthOnWakeUpFrom.contains(pmWakeReason)
}
- fun shouldTriggerFaceAuthOnWakeUpFrom(wakeReason: WakeSleepReason): Boolean =
+ override fun shouldTriggerFaceAuthOnWakeUpFrom(wakeReason: WakeSleepReason): Boolean =
wakeSleepReasonsToTriggerFaceAuth.contains(wakeReason)
override fun dump(pw: PrintWriter, args: Array<out String>) {
@@ -87,3 +96,8 @@
?: default
}
}
+
+@Module
+interface FaceWakeUpTriggersConfigModule {
+ @Binds fun repository(impl: FaceWakeUpTriggersConfigImpl): FaceWakeUpTriggersConfig
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/NoopDeviceEntryFaceAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/NoopDeviceEntryFaceAuthRepository.kt
similarity index 68%
rename from packages/SystemUI/src/com/android/systemui/keyguard/data/repository/NoopDeviceEntryFaceAuthRepository.kt
rename to packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/NoopDeviceEntryFaceAuthRepository.kt
index f4a74f0..6695b182 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/NoopDeviceEntryFaceAuthRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/NoopDeviceEntryFaceAuthRepository.kt
@@ -1,25 +1,25 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * 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
+ * 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.
+ * 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.keyguard.data.repository
+package com.android.systemui.deviceentry.data.repository
-import com.android.keyguard.FaceAuthUiEvent
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus
-import com.android.systemui.keyguard.shared.model.FaceDetectionStatus
+import com.android.systemui.deviceentry.shared.FaceAuthUiEvent
+import com.android.systemui.deviceentry.shared.model.FaceAuthenticationStatus
+import com.android.systemui.deviceentry.shared.model.FaceDetectionStatus
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricAuthInteractor.kt
index 1a6bd04..5699176 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricAuthInteractor.kt
@@ -18,13 +18,14 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.deviceentry.shared.DeviceEntryBiometricMode
+import com.android.systemui.deviceentry.shared.model.FailedFaceAuthenticationStatus
import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
-import com.android.systemui.keyguard.shared.model.FailedFaceAuthenticationStatus
import javax.inject.Inject
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
@@ -62,7 +63,9 @@
val faceOnlyFaceFailure: Flow<FailedFaceAuthenticationStatus> =
faceOnly.flatMapLatest { faceOnly ->
if (faceOnly) {
- deviceEntryFaceAuthInteractor.faceFailure
+ deviceEntryFaceAuthInteractor.authenticationStatus.filterIsInstance<
+ FailedFaceAuthenticationStatus
+ >()
} else {
emptyFlow()
}
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractor.kt
index 70716c6..99bd25b 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractor.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,19 +16,80 @@
package com.android.systemui.deviceentry.domain.interactor
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository
-import com.android.systemui.keyguard.shared.model.FailedFaceAuthenticationStatus
-import javax.inject.Inject
+import com.android.systemui.deviceentry.shared.model.FaceAuthenticationStatus
+import com.android.systemui.deviceentry.shared.model.FaceDetectionStatus
import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.filterIsInstance
-@SysUISingleton
-class DeviceEntryFaceAuthInteractor
-@Inject
-constructor(
- repository: DeviceEntryFaceAuthRepository,
-) {
- val faceFailure: Flow<FailedFaceAuthenticationStatus> =
- repository.authenticationStatus.filterIsInstance<FailedFaceAuthenticationStatus>()
+/**
+ * Interactor that exposes API to get the face authentication status and handle any events that can
+ * cause face authentication to run for device entry.
+ */
+interface DeviceEntryFaceAuthInteractor {
+
+ /** Current authentication status */
+ val authenticationStatus: Flow<FaceAuthenticationStatus>
+
+ /** Current detection status */
+ val detectionStatus: Flow<FaceDetectionStatus>
+
+ /** Can face auth be run right now */
+ fun canFaceAuthRun(): Boolean
+
+ /** Whether face auth is currently running or not. */
+ fun isRunning(): Boolean
+
+ /** Whether face auth is in lock out state. */
+ fun isLockedOut(): Boolean
+
+ /** Whether face auth is enrolled and enabled for the current user */
+ fun isFaceAuthEnabledAndEnrolled(): Boolean
+
+ /** Whether the current user is authenticated successfully with face auth */
+ fun isAuthenticated(): Boolean
+ /**
+ * Register listener for use from code that cannot use [authenticationStatus] or
+ * [detectionStatus]
+ */
+ fun registerListener(listener: FaceAuthenticationListener)
+
+ /** Unregister previously registered listener */
+ fun unregisterListener(listener: FaceAuthenticationListener)
+
+ fun onUdfpsSensorTouched()
+ fun onAssistantTriggeredOnLockScreen()
+ fun onDeviceLifted()
+ fun onQsExpansionStared()
+ fun onNotificationPanelClicked()
+ fun onSwipeUpOnBouncer()
+ fun onPrimaryBouncerUserInput()
+ fun onAccessibilityAction()
+ fun onWalletLaunched()
+
+ /** Whether face auth is considered class 3 */
+ fun isFaceAuthStrong(): Boolean
+}
+
+/**
+ * Listener that can be registered with the [DeviceEntryFaceAuthInteractor] to receive updates about
+ * face authentication & detection updates.
+ *
+ * This is present to make it easier for use the new face auth API for code that cannot use
+ * [DeviceEntryFaceAuthInteractor.authenticationStatus] or
+ * [DeviceEntryFaceAuthInteractor.detectionStatus] flows.
+ */
+interface FaceAuthenticationListener {
+ /** Receive face isAuthenticated updates */
+ fun onAuthenticatedChanged(isAuthenticated: Boolean)
+
+ /** Receive face authentication status updates */
+ fun onAuthenticationStatusChanged(status: FaceAuthenticationStatus)
+
+ /** Receive status updates whenever face detection runs */
+ fun onDetectionStatusChanged(status: FaceDetectionStatus)
+
+ fun onLockoutStateChanged(isLockedOut: Boolean)
+
+ fun onRunningStateChanged(isRunning: Boolean)
+
+ fun onAuthEnrollmentStateChanged(enrolled: Boolean)
}
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
index f6a9570..2680328 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
@@ -20,8 +20,8 @@
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.deviceentry.data.repository.DeviceEntryFaceAuthRepository
import com.android.systemui.deviceentry.data.repository.DeviceEntryRepository
-import com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository
import com.android.systemui.keyguard.data.repository.TrustRepository
import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
import com.android.systemui.scene.domain.interactor.SceneInteractor
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/NoopDeviceEntryFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/NoopDeviceEntryFaceAuthInteractor.kt
new file mode 100644
index 0000000..3b94166
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/NoopDeviceEntryFaceAuthInteractor.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.deviceentry.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.deviceentry.shared.model.FaceAuthenticationStatus
+import com.android.systemui.deviceentry.shared.model.FaceDetectionStatus
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.emptyFlow
+
+/**
+ * Implementation of the interactor that noops all face auth operations.
+ *
+ * This is required for SystemUI variants that do not support face authentication but still inject
+ * other SysUI components that depend on [DeviceEntryFaceAuthInteractor]
+ */
+@SysUISingleton
+class NoopDeviceEntryFaceAuthInteractor @Inject constructor() : DeviceEntryFaceAuthInteractor {
+ override val authenticationStatus: Flow<FaceAuthenticationStatus>
+ get() = emptyFlow()
+ override val detectionStatus: Flow<FaceDetectionStatus>
+ get() = emptyFlow()
+
+ override fun canFaceAuthRun(): Boolean = false
+
+ override fun isRunning(): Boolean = false
+
+ override fun isLockedOut(): Boolean = false
+
+ override fun isFaceAuthEnabledAndEnrolled(): Boolean = false
+
+ override fun isFaceAuthStrong(): Boolean = false
+
+ override fun isAuthenticated(): Boolean = false
+
+ override fun registerListener(listener: FaceAuthenticationListener) {}
+
+ override fun unregisterListener(listener: FaceAuthenticationListener) {}
+
+ override fun onUdfpsSensorTouched() {}
+
+ override fun onAssistantTriggeredOnLockScreen() {}
+
+ override fun onDeviceLifted() {}
+
+ override fun onQsExpansionStared() {}
+
+ override fun onNotificationPanelClicked() {}
+
+ override fun onSwipeUpOnBouncer() {}
+ override fun onPrimaryBouncerUserInput() {}
+ override fun onAccessibilityAction() {}
+ override fun onWalletLaunched() = Unit
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt
similarity index 94%
rename from packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt
rename to packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt
index e3f4739..98130eb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt
@@ -14,14 +14,12 @@
* limitations under the License.
*/
-package com.android.systemui.keyguard.domain.interactor
+package com.android.systemui.deviceentry.domain.interactor
import android.app.trust.TrustManager
import android.content.Context
import android.hardware.biometrics.BiometricFaceConstants
import android.hardware.biometrics.BiometricSourceType
-import com.android.keyguard.FaceAuthUiEvent
-import com.android.keyguard.FaceWakeUpTriggersConfig
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.CoreStartable
import com.android.systemui.biometrics.data.repository.FacePropertyRepository
@@ -32,11 +30,14 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.deviceentry.data.repository.DeviceEntryFaceAuthRepository
+import com.android.systemui.deviceentry.data.repository.FaceWakeUpTriggersConfig
+import com.android.systemui.deviceentry.shared.FaceAuthUiEvent
+import com.android.systemui.deviceentry.shared.model.ErrorFaceAuthenticationStatus
+import com.android.systemui.deviceentry.shared.model.FaceAuthenticationStatus
import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
-import com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository
import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
-import com.android.systemui.keyguard.shared.model.ErrorFaceAuthenticationStatus
-import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.log.FaceAuthenticationLogger
import com.android.systemui.power.domain.interactor.PowerInteractor
@@ -65,7 +66,7 @@
* SystemUI Keyguard.
*/
@SysUISingleton
-class SystemUIKeyguardFaceAuthInteractor
+class SystemUIDeviceEntryFaceAuthInteractor
@Inject
constructor(
private val context: Context,
@@ -84,7 +85,7 @@
private val powerInteractor: PowerInteractor,
private val biometricSettingsRepository: BiometricSettingsRepository,
private val trustManager: TrustManager,
-) : CoreStartable, KeyguardFaceAuthInteractor {
+) : CoreStartable, DeviceEntryFaceAuthInteractor {
private val listeners: MutableList<FaceAuthenticationListener> = mutableListOf()
@@ -310,7 +311,7 @@
}
companion object {
- const val TAG = "KeyguardFaceAuthInteractor"
+ const val TAG = "DeviceEntryFaceAuthInteractor"
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/shared/FaceAuthReason.kt
similarity index 73%
rename from packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
rename to packages/SystemUI/src/com/android/systemui/deviceentry/shared/FaceAuthReason.kt
index 2abb7a4..ee220d5 100644
--- a/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/shared/FaceAuthReason.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,58 +14,55 @@
* limitations under the License.
*/
-package com.android.keyguard
+package com.android.systemui.deviceentry.shared
import android.annotation.StringDef
import android.os.PowerManager
import com.android.internal.logging.UiEvent
import com.android.internal.logging.UiEventLogger
-import com.android.keyguard.FaceAuthApiRequestReason.Companion.ACCESSIBILITY_ACTION
-import com.android.keyguard.FaceAuthApiRequestReason.Companion.NOTIFICATION_PANEL_CLICKED
-import com.android.keyguard.FaceAuthApiRequestReason.Companion.PICK_UP_GESTURE_TRIGGERED
-import com.android.keyguard.FaceAuthApiRequestReason.Companion.QS_EXPANDED
-import com.android.keyguard.FaceAuthApiRequestReason.Companion.SWIPE_UP_ON_BOUNCER
-import com.android.keyguard.FaceAuthApiRequestReason.Companion.UDFPS_POINTER_DOWN
-import com.android.keyguard.InternalFaceAuthReasons.ALL_AUTHENTICATORS_REGISTERED
-import com.android.keyguard.InternalFaceAuthReasons.ALTERNATE_BIOMETRIC_BOUNCER_SHOWN
-import com.android.keyguard.InternalFaceAuthReasons.ASSISTANT_VISIBILITY_CHANGED
-import com.android.keyguard.InternalFaceAuthReasons.AUTH_REQUEST_DURING_CANCELLATION
-import com.android.keyguard.InternalFaceAuthReasons.BIOMETRIC_ENABLED
-import com.android.keyguard.InternalFaceAuthReasons.CAMERA_LAUNCHED
-import com.android.keyguard.InternalFaceAuthReasons.DEVICE_WOKEN_UP_ON_REACH_GESTURE
-import com.android.keyguard.InternalFaceAuthReasons.DISPLAY_OFF
-import com.android.keyguard.InternalFaceAuthReasons.DREAM_STARTED
-import com.android.keyguard.InternalFaceAuthReasons.DREAM_STOPPED
-import com.android.keyguard.InternalFaceAuthReasons.ENROLLMENTS_CHANGED
-import com.android.keyguard.InternalFaceAuthReasons.FACE_AUTHENTICATED
-import com.android.keyguard.InternalFaceAuthReasons.FACE_AUTH_STOPPED_ON_USER_INPUT
-import com.android.keyguard.InternalFaceAuthReasons.FACE_CANCEL_NOT_RECEIVED
-import com.android.keyguard.InternalFaceAuthReasons.FACE_LOCKOUT_RESET
-import com.android.keyguard.InternalFaceAuthReasons.FINISHED_GOING_TO_SLEEP
-import com.android.keyguard.InternalFaceAuthReasons.FP_AUTHENTICATED
-import com.android.keyguard.InternalFaceAuthReasons.FP_LOCKED_OUT
-import com.android.keyguard.InternalFaceAuthReasons.GOING_TO_SLEEP
-import com.android.keyguard.InternalFaceAuthReasons.KEYGUARD_GOING_AWAY
-import com.android.keyguard.InternalFaceAuthReasons.KEYGUARD_INIT
-import com.android.keyguard.InternalFaceAuthReasons.KEYGUARD_OCCLUSION_CHANGED
-import com.android.keyguard.InternalFaceAuthReasons.KEYGUARD_RESET
-import com.android.keyguard.InternalFaceAuthReasons.KEYGUARD_VISIBILITY_CHANGED
-import com.android.keyguard.InternalFaceAuthReasons.NON_STRONG_BIOMETRIC_ALLOWED_CHANGED
-import com.android.keyguard.InternalFaceAuthReasons.OCCLUDING_APP_REQUESTED
-import com.android.keyguard.InternalFaceAuthReasons.POSTURE_CHANGED
-import com.android.keyguard.InternalFaceAuthReasons.PRIMARY_BOUNCER_SHOWN
-import com.android.keyguard.InternalFaceAuthReasons.PRIMARY_BOUNCER_SHOWN_OR_WILL_BE_SHOWN
-import com.android.keyguard.InternalFaceAuthReasons.RETRY_AFTER_HW_UNAVAILABLE
-import com.android.keyguard.InternalFaceAuthReasons.STARTED_WAKING_UP
-import com.android.keyguard.InternalFaceAuthReasons.STRONG_AUTH_ALLOWED_CHANGED
-import com.android.keyguard.InternalFaceAuthReasons.TRUST_DISABLED
-import com.android.keyguard.InternalFaceAuthReasons.TRUST_ENABLED
-import com.android.keyguard.InternalFaceAuthReasons.USER_SWITCHING
+import com.android.systemui.deviceentry.shared.FaceAuthApiRequestReason.Companion.ACCESSIBILITY_ACTION
+import com.android.systemui.deviceentry.shared.FaceAuthApiRequestReason.Companion.NOTIFICATION_PANEL_CLICKED
+import com.android.systemui.deviceentry.shared.FaceAuthApiRequestReason.Companion.PICK_UP_GESTURE_TRIGGERED
+import com.android.systemui.deviceentry.shared.FaceAuthApiRequestReason.Companion.QS_EXPANDED
+import com.android.systemui.deviceentry.shared.FaceAuthApiRequestReason.Companion.SWIPE_UP_ON_BOUNCER
+import com.android.systemui.deviceentry.shared.FaceAuthApiRequestReason.Companion.UDFPS_POINTER_DOWN
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.ALL_AUTHENTICATORS_REGISTERED
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.ALTERNATE_BIOMETRIC_BOUNCER_SHOWN
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.ASSISTANT_VISIBILITY_CHANGED
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.AUTH_REQUEST_DURING_CANCELLATION
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.BIOMETRIC_ENABLED
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.CAMERA_LAUNCHED
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.DEVICE_WOKEN_UP_ON_REACH_GESTURE
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.DISPLAY_OFF
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.DREAM_STARTED
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.DREAM_STOPPED
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.ENROLLMENTS_CHANGED
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.FACE_AUTHENTICATED
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.FACE_AUTH_STOPPED_ON_USER_INPUT
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.FACE_CANCEL_NOT_RECEIVED
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.FACE_LOCKOUT_RESET
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.FINISHED_GOING_TO_SLEEP
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.FP_AUTHENTICATED
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.FP_LOCKED_OUT
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.GOING_TO_SLEEP
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.KEYGUARD_GOING_AWAY
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.KEYGUARD_INIT
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.KEYGUARD_OCCLUSION_CHANGED
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.KEYGUARD_RESET
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.KEYGUARD_VISIBILITY_CHANGED
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.NON_STRONG_BIOMETRIC_ALLOWED_CHANGED
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.OCCLUDING_APP_REQUESTED
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.POSTURE_CHANGED
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.PRIMARY_BOUNCER_SHOWN
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.PRIMARY_BOUNCER_SHOWN_OR_WILL_BE_SHOWN
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.RETRY_AFTER_HW_UNAVAILABLE
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.STARTED_WAKING_UP
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.STRONG_AUTH_ALLOWED_CHANGED
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.TRUST_DISABLED
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.TRUST_ENABLED
+import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.USER_SWITCHING
-/**
- * List of reasons why face auth is requested by clients through
- * [KeyguardUpdateMonitor.requestFaceAuth].
- */
+/** List of reasons why face auth is requested by clients. */
@Retention(AnnotationRetention.SOURCE)
@StringDef(
SWIPE_UP_ON_BOUNCER,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/FaceAuthenticationModels.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/shared/model/FaceAuthenticationModels.kt
similarity index 95%
rename from packages/SystemUI/src/com/android/systemui/keyguard/shared/model/FaceAuthenticationModels.kt
rename to packages/SystemUI/src/com/android/systemui/deviceentry/shared/model/FaceAuthenticationModels.kt
index 3de3666..f006b34 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/FaceAuthenticationModels.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/shared/model/FaceAuthenticationModels.kt
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-package com.android.systemui.keyguard.shared.model
+package com.android.systemui.deviceentry.shared.model
import android.hardware.face.FaceManager
import android.os.SystemClock.elapsedRealtime
/**
* Authentication status provided by
- * [com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository]
+ * [com.android.systemui.deviceentry.data.repository.DeviceEntryFaceAuthRepository]
*/
sealed class FaceAuthenticationStatus
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index bb0c273..38c7c6a 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -444,29 +444,10 @@
// TODO(b/254512728): Tracking Bug
@JvmField val NEW_BACK_AFFORDANCE = releasedFlag("new_back_affordance")
- // TODO(b/255854141): Tracking Bug
- @JvmField
- val WM_ENABLE_PREDICTIVE_BACK_SYSUI =
- unreleasedFlag("persist.wm.debug.predictive_back_sysui_enable", teamfood = true)
// TODO(b/270987164): Tracking Bug
@JvmField val TRACKPAD_GESTURE_FEATURES = releasedFlag("trackpad_gesture_features")
- // TODO(b/263826204): Tracking Bug
- @JvmField
- val WM_ENABLE_PREDICTIVE_BACK_BOUNCER_ANIM =
- unreleasedFlag("persist.wm.debug.predictive_back_bouncer_anim", teamfood = true)
-
- // TODO(b/238475428): Tracking Bug
- @JvmField
- val WM_SHADE_ALLOW_BACK_GESTURE =
- sysPropBooleanFlag("persist.wm.debug.shade_allow_back_gesture", default = false)
-
- // TODO(b/238475428): Tracking Bug
- @JvmField
- val WM_SHADE_ANIMATE_BACK_GESTURE =
- unreleasedFlag("persist.wm.debug.shade_animate_back_gesture", teamfood = false)
-
// TODO(b/265639042): Tracking Bug
@JvmField
val WM_ENABLE_PREDICTIVE_BACK_QS_DIALOG_ANIM =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardFaceAuthNotSupportedModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardFaceAuthNotSupportedModule.kt
index d8eb81c..f29b657 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardFaceAuthNotSupportedModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardFaceAuthNotSupportedModule.kt
@@ -16,10 +16,10 @@
package com.android.systemui.keyguard.dagger
-import com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository
-import com.android.systemui.keyguard.data.repository.NoopDeviceEntryFaceAuthRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
-import com.android.systemui.keyguard.domain.interactor.NoopKeyguardFaceAuthInteractor
+import com.android.systemui.deviceentry.data.repository.DeviceEntryFaceAuthRepository
+import com.android.systemui.deviceentry.data.repository.NoopDeviceEntryFaceAuthRepository
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
+import com.android.systemui.deviceentry.domain.interactor.NoopDeviceEntryFaceAuthInteractor
import dagger.Binds
import dagger.Module
@@ -33,7 +33,9 @@
@Module
interface KeyguardFaceAuthNotSupportedModule {
@Binds
- fun keyguardFaceAuthInteractor(impl: NoopKeyguardFaceAuthInteractor): KeyguardFaceAuthInteractor
+ fun keyguardFaceAuthInteractor(
+ impl: NoopDeviceEntryFaceAuthInteractor
+ ): DeviceEntryFaceAuthInteractor
@Binds
fun deviceEntryFaceAuthRepository(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthModule.kt
index ee0eb2d..b373f85 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthModule.kt
@@ -19,8 +19,10 @@
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
-import com.android.systemui.keyguard.domain.interactor.SystemUIKeyguardFaceAuthInteractor
+import com.android.systemui.deviceentry.data.repository.DeviceEntryFaceAuthRepository
+import com.android.systemui.deviceentry.data.repository.DeviceEntryFaceAuthRepositoryImpl
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
+import com.android.systemui.deviceentry.domain.interactor.SystemUIDeviceEntryFaceAuthInteractor
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.TableLogBufferFactory
import dagger.Binds
@@ -38,13 +40,13 @@
@Binds
@IntoMap
- @ClassKey(SystemUIKeyguardFaceAuthInteractor::class)
- fun bind(impl: SystemUIKeyguardFaceAuthInteractor): CoreStartable
+ @ClassKey(SystemUIDeviceEntryFaceAuthInteractor::class)
+ fun bind(impl: SystemUIDeviceEntryFaceAuthInteractor): CoreStartable
@Binds
fun keyguardFaceAuthInteractor(
- impl: SystemUIKeyguardFaceAuthInteractor
- ): KeyguardFaceAuthInteractor
+ impl: SystemUIDeviceEntryFaceAuthInteractor
+ ): DeviceEntryFaceAuthInteractor
companion object {
@Provides
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractor.kt
deleted file mode 100644
index 046916a..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractor.kt
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2023 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.keyguard.domain.interactor
-
-import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus
-import com.android.systemui.keyguard.shared.model.FaceDetectionStatus
-import kotlinx.coroutines.flow.Flow
-
-/**
- * Interactor that exposes API to get the face authentication status and handle any events that can
- * cause face authentication to run.
- */
-interface KeyguardFaceAuthInteractor {
-
- /** Current authentication status */
- val authenticationStatus: Flow<FaceAuthenticationStatus>
-
- /** Current detection status */
- val detectionStatus: Flow<FaceDetectionStatus>
-
- /** Can face auth be run right now */
- fun canFaceAuthRun(): Boolean
-
- /** Whether face auth is currently running or not. */
- fun isRunning(): Boolean
-
- /** Whether face auth is in lock out state. */
- fun isLockedOut(): Boolean
-
- /** Whether face auth is enrolled and enabled for the current user */
- fun isFaceAuthEnabledAndEnrolled(): Boolean
-
- /** Whether the current user is authenticated successfully with face auth */
- fun isAuthenticated(): Boolean
- /**
- * Register listener for use from code that cannot use [authenticationStatus] or
- * [detectionStatus]
- */
- fun registerListener(listener: FaceAuthenticationListener)
-
- /** Unregister previously registered listener */
- fun unregisterListener(listener: FaceAuthenticationListener)
-
- fun onUdfpsSensorTouched()
- fun onAssistantTriggeredOnLockScreen()
- fun onDeviceLifted()
- fun onQsExpansionStared()
- fun onNotificationPanelClicked()
- fun onSwipeUpOnBouncer()
- fun onPrimaryBouncerUserInput()
- fun onAccessibilityAction()
- fun onWalletLaunched()
-
- /** Whether face auth is considered class 3 */
- fun isFaceAuthStrong(): Boolean
-}
-
-/**
- * Listener that can be registered with the [KeyguardFaceAuthInteractor] to receive updates about
- * face authentication & detection updates.
- *
- * This is present to make it easier for use the new face auth API for code that cannot use
- * [KeyguardFaceAuthInteractor.authenticationStatus] or [KeyguardFaceAuthInteractor.detectionStatus]
- * flows.
- */
-interface FaceAuthenticationListener {
- /** Receive face isAuthenticated updates */
- fun onAuthenticatedChanged(isAuthenticated: Boolean)
-
- /** Receive face authentication status updates */
- fun onAuthenticationStatusChanged(status: FaceAuthenticationStatus)
-
- /** Receive status updates whenever face detection runs */
- fun onDetectionStatusChanged(status: FaceDetectionStatus)
-
- fun onLockoutStateChanged(isLockedOut: Boolean)
-
- fun onRunningStateChanged(isRunning: Boolean)
-
- fun onAuthEnrollmentStateChanged(enrolled: Boolean)
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/NoopKeyguardFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/NoopKeyguardFaceAuthInteractor.kt
deleted file mode 100644
index cd6ab31..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/NoopKeyguardFaceAuthInteractor.kt
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2023 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.keyguard.domain.interactor
-
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus
-import com.android.systemui.keyguard.shared.model.FaceDetectionStatus
-import javax.inject.Inject
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.emptyFlow
-
-/**
- * Implementation of the interactor that noops all face auth operations.
- *
- * This is required for SystemUI variants that do not support face authentication but still inject
- * other SysUI components that depend on [KeyguardFaceAuthInteractor]
- */
-@SysUISingleton
-class NoopKeyguardFaceAuthInteractor @Inject constructor() : KeyguardFaceAuthInteractor {
- override val authenticationStatus: Flow<FaceAuthenticationStatus>
- get() = emptyFlow()
- override val detectionStatus: Flow<FaceDetectionStatus>
- get() = emptyFlow()
-
- override fun canFaceAuthRun(): Boolean = false
-
- override fun isRunning(): Boolean = false
-
- override fun isLockedOut(): Boolean = false
-
- override fun isFaceAuthEnabledAndEnrolled(): Boolean = false
-
- override fun isFaceAuthStrong(): Boolean = false
-
- override fun isAuthenticated(): Boolean = false
-
- override fun registerListener(listener: FaceAuthenticationListener) {}
-
- override fun unregisterListener(listener: FaceAuthenticationListener) {}
-
- override fun onUdfpsSensorTouched() {}
-
- override fun onAssistantTriggeredOnLockScreen() {}
-
- override fun onDeviceLifted() {}
-
- override fun onQsExpansionStared() {}
-
- override fun onNotificationPanelClicked() {}
-
- override fun onSwipeUpOnBouncer() {}
- override fun onPrimaryBouncerUserInput() {}
- override fun onAccessibilityAction() {}
- override fun onWalletLaunched() = Unit
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/SysUiFaceAuthenticateOptions.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/SysUiFaceAuthenticateOptions.kt
index 942cd60..b3d0f918 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/SysUiFaceAuthenticateOptions.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/SysUiFaceAuthenticateOptions.kt
@@ -32,7 +32,7 @@
import android.os.PowerManager.WAKE_REASON_UNKNOWN
import android.util.Log
import com.android.internal.logging.UiEventLogger
-import com.android.keyguard.FaceAuthUiEvent
+import com.android.systemui.deviceentry.shared.FaceAuthUiEvent
/**
* Wrapper for [FaceAuthenticateOptions] to convert SystemUI values to their corresponding value in
diff --git a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
index 3c2facb..9e6c552 100644
--- a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
@@ -2,9 +2,9 @@
import android.hardware.face.FaceManager
import android.hardware.face.FaceSensorPropertiesInternal
-import com.android.keyguard.FaceAuthUiEvent
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.shared.model.ErrorFaceAuthenticationStatus
+import com.android.systemui.deviceentry.shared.FaceAuthUiEvent
+import com.android.systemui.deviceentry.shared.model.ErrorFaceAuthenticationStatus
import com.android.systemui.log.core.LogLevel.DEBUG
import com.android.systemui.log.dagger.FaceAuthLog
import com.android.systemui.power.shared.model.WakeSleepReason
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
index 1e67771..24cb8ff 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -20,6 +20,7 @@
import com.android.systemui.common.data.repository.PackageChangeRepository;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.deviceentry.data.repository.DeviceEntryFaceAuthRepositoryImpl;
import com.android.systemui.log.LogBuffer;
import com.android.systemui.log.LogBufferFactory;
import com.android.systemui.log.LogcatEchoTracker;
@@ -462,7 +463,7 @@
/**
* Provides a {@link LogBuffer} for use by
- * {@link com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepositoryImpl}.
+ * {@link DeviceEntryFaceAuthRepositoryImpl}.
*/
@Provides
@SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
index 3e50dd3..ac0bd29 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -49,6 +49,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Collectors;
@@ -231,32 +232,39 @@
if (!collapsedView && mQsTileRevealController != null) {
mQsTileRevealController.updateRevealedTiles(tiles);
}
- boolean shouldChange = false;
+ boolean shouldChangeAll = false;
+ // If the new tiles are a prefix of the old tiles, we delete the extra tiles (from the old).
+ // If not (even if they share a prefix) we remove all and add all the new ones.
if (tiles.size() <= mRecords.size()) {
int i = 0;
+ // Iterate through the requested tiles and check if they are the same as the existing
+ // tiles.
for (QSTile tile : tiles) {
if (tile != mRecords.get(i).tile) {
- shouldChange = true;
+ shouldChangeAll = true;
break;
}
i++;
}
- // If the first tiles are the same as the new ones, remove any extras.
- if (!shouldChange) {
- while (i < mRecords.size()) {
- QSPanelControllerBase.TileRecord record = mRecords.get(i);
+ // If the first tiles are the same as the new ones, we reuse them and remove any extra
+ // tiles.
+ if (!shouldChangeAll && i < mRecords.size()) {
+ List<TileRecord> extraRecords = mRecords.subList(i, mRecords.size());
+ for (QSPanelControllerBase.TileRecord record : extraRecords) {
mView.removeTile(record);
record.tile.removeCallback(record.callback);
- i++;
}
+ extraRecords.clear();
mCachedSpecs = getTilesSpecs();
}
} else {
- shouldChange = true;
+ shouldChangeAll = true;
}
- if (shouldChange) {
+ // If we detected that the existing tiles are different than the requested tiles, clear them
+ // and add the new tiles.
+ if (shouldChangeAll) {
for (QSPanelControllerBase.TileRecord record : mRecords) {
mView.removeTile(record);
record.tile.removeCallback(record.callback);
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index fb6bc38..a5c1cf1 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -26,6 +26,7 @@
import static com.android.keyguard.KeyguardClockSwitch.SMALL;
import static com.android.systemui.Flags.keyguardBottomAreaRefactor;
import static com.android.systemui.Flags.migrateClocksToBlueprint;
+import static com.android.systemui.Flags.predictiveBackAnimateShade;
import static com.android.systemui.classifier.Classifier.BOUNCER_UNLOCK;
import static com.android.systemui.classifier.Classifier.GENERIC;
import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
@@ -121,6 +122,7 @@
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.DisplayId;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.dump.DumpsysTableLogger;
@@ -131,7 +133,6 @@
import com.android.systemui.keyguard.KeyguardViewConfigurator;
import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.keyguard.domain.interactor.NaturalScrollingSettingObserver;
@@ -327,7 +328,7 @@
private final PulseExpansionHandler mPulseExpansionHandler;
private final KeyguardBypassController mKeyguardBypassController;
private final KeyguardUpdateMonitor mUpdateMonitor;
- private final KeyguardFaceAuthInteractor mKeyguardFaceAuthInteractor;
+ private final DeviceEntryFaceAuthInteractor mDeviceEntryFaceAuthInteractor;
private final ConversationNotificationManager mConversationNotificationManager;
private final AuthController mAuthController;
private final MediaHierarchyManager mMediaHierarchyManager;
@@ -779,7 +780,7 @@
ActiveNotificationsInteractor activeNotificationsInteractor,
ShadeAnimationInteractor shadeAnimationInteractor,
KeyguardViewConfigurator keyguardViewConfigurator,
- KeyguardFaceAuthInteractor keyguardFaceAuthInteractor,
+ DeviceEntryFaceAuthInteractor deviceEntryFaceAuthInteractor,
SplitShadeStateController splitShadeStateController,
PowerInteractor powerInteractor,
KeyguardClockPositionAlgorithm keyguardClockPositionAlgorithm,
@@ -891,7 +892,7 @@
mShadeHeaderController = shadeHeaderController;
mLayoutInflater = layoutInflater;
mFeatureFlags = featureFlags;
- mAnimateBack = mFeatureFlags.isEnabled(Flags.WM_SHADE_ANIMATE_BACK_GESTURE);
+ mAnimateBack = predictiveBackAnimateShade();
mTrackpadGestureFeaturesEnabled = mFeatureFlags.isEnabled(Flags.TRACKPAD_GESTURE_FEATURES);
mFalsingCollector = falsingCollector;
mWakeUpCoordinator = coordinator;
@@ -936,7 +937,7 @@
mScreenOffAnimationController = screenOffAnimationController;
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
mLastDownEvents = new NPVCDownEventState.Buffer(MAX_DOWN_EVENT_BUFFER_SIZE);
- mKeyguardFaceAuthInteractor = keyguardFaceAuthInteractor;
+ mDeviceEntryFaceAuthInteractor = deviceEntryFaceAuthInteractor;
int currentMode = navigationModeController.addListener(
mode -> mIsGestureNavigation = QuickStepContract.isGesturalMode(mode));
@@ -2978,9 +2979,9 @@
mShadeLog.v("onMiddleClicked on Keyguard, mDozingOnDown: false");
// Try triggering face auth, this "might" run. Check
// KeyguardUpdateMonitor#shouldListenForFace to see when face auth won't run.
- mKeyguardFaceAuthInteractor.onNotificationPanelClicked();
+ mDeviceEntryFaceAuthInteractor.onNotificationPanelClicked();
- if (mKeyguardFaceAuthInteractor.canFaceAuthRun()) {
+ if (mDeviceEntryFaceAuthInteractor.canFaceAuthRun()) {
mUpdateMonitor.requestActiveUnlock(
ActiveUnlockConfig.ActiveUnlockRequestOrigin.UNLOCK_INTENT,
"lockScreenEmptySpaceTap");
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
index 8397caa..1dff99d 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
@@ -66,9 +66,9 @@
import com.android.systemui.Dumpable;
import com.android.systemui.classifier.Classifier;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.fragments.FragmentHostManager;
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl;
import com.android.systemui.media.controls.pipeline.MediaDataManager;
import com.android.systemui.media.controls.ui.MediaHierarchyManager;
@@ -152,7 +152,7 @@
private final RecordingController mRecordingController;
private final LockscreenGestureLogger mLockscreenGestureLogger;
private final ShadeLogger mShadeLog;
- private final KeyguardFaceAuthInteractor mKeyguardFaceAuthInteractor;
+ private final DeviceEntryFaceAuthInteractor mDeviceEntryFaceAuthInteractor;
private final CastController mCastController;
private final SplitShadeStateController mSplitShadeStateController;
private final InteractionJankMonitor mInteractionJankMonitor;
@@ -338,7 +338,7 @@
InteractionJankMonitor interactionJankMonitor,
ShadeLogger shadeLog,
DumpManager dumpManager,
- KeyguardFaceAuthInteractor keyguardFaceAuthInteractor,
+ DeviceEntryFaceAuthInteractor deviceEntryFaceAuthInteractor,
ShadeRepository shadeRepository,
ShadeInteractor shadeInteractor,
ActiveNotificationsInteractor activeNotificationsInteractor,
@@ -384,7 +384,7 @@
mLockscreenGestureLogger = lockscreenGestureLogger;
mMetricsLogger = metricsLogger;
mShadeLog = shadeLog;
- mKeyguardFaceAuthInteractor = keyguardFaceAuthInteractor;
+ mDeviceEntryFaceAuthInteractor = deviceEntryFaceAuthInteractor;
mCastController = castController;
mInteractionJankMonitor = interactionJankMonitor;
mShadeRepository = shadeRepository;
@@ -972,7 +972,7 @@
// When expanding QS, let's authenticate the user if possible,
// this will speed up notification actions.
if (height == 0 && !mKeyguardStateController.canDismissLockScreen()) {
- mKeyguardFaceAuthInteractor.onQsExpansionStared();
+ mDeviceEntryFaceAuthInteractor.onQsExpansionStared();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/domain/interactor/NotificationShelfInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/domain/interactor/NotificationShelfInteractor.kt
index 4b89615..9fdd0bc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/domain/interactor/NotificationShelfInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/domain/interactor/NotificationShelfInteractor.kt
@@ -18,7 +18,7 @@
import android.os.PowerManager
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository
+import com.android.systemui.deviceentry.data.repository.DeviceEntryFaceAuthRepository
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.statusbar.LockscreenShadeTransitionController
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 57d49b2..6e3aabf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -31,6 +31,7 @@
import static com.android.systemui.charging.WirelessChargingAnimation.UNKNOWN_BATTERY_LEVEL;
import static com.android.systemui.statusbar.NotificationLockscreenUserManager.PERMISSION_SELF;
import static com.android.systemui.statusbar.StatusBarState.SHADE;
+import static com.android.systemui.Flags.predictiveBackSysui;
import android.annotation.Nullable;
import android.app.ActivityOptions;
@@ -836,7 +837,7 @@
mLightRevealScrim = lightRevealScrim;
// Based on teamfood flag, turn predictive back dispatch on at runtime.
- if (mFeatureFlags.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_SYSUI)) {
+ if (predictiveBackSysui()) {
mContext.getApplicationInfo().setEnableOnBackInvokedCallback(true);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
index 32b3ac2..9f08633 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
@@ -28,7 +28,7 @@
import com.android.systemui.Dumpable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dump.DumpManager
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import com.android.systemui.util.Assert
@@ -43,13 +43,13 @@
*/
@SysUISingleton
class KeyguardLiftController @Inject constructor(
- private val context: Context,
- private val statusBarStateController: StatusBarStateController,
- private val asyncSensorManager: AsyncSensorManager,
- private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
- private val keyguardFaceAuthInteractor: KeyguardFaceAuthInteractor,
- private val dumpManager: DumpManager,
- private val selectedUserInteractor: SelectedUserInteractor,
+ private val context: Context,
+ private val statusBarStateController: StatusBarStateController,
+ private val asyncSensorManager: AsyncSensorManager,
+ private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
+ private val deviceEntryFaceAuthInteractor: DeviceEntryFaceAuthInteractor,
+ private val dumpManager: DumpManager,
+ private val selectedUserInteractor: SelectedUserInteractor,
) : Dumpable, CoreStartable {
private val pickupSensor = asyncSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE)
@@ -75,7 +75,7 @@
// Not listening anymore since trigger events unregister themselves
isListening = false
updateListeningState()
- keyguardFaceAuthInteractor.onDeviceLifted()
+ deviceEntryFaceAuthInteractor.onDeviceLifted()
keyguardUpdateMonitor.requestActiveUnlock(
ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE,
"KeyguardLiftController")
@@ -113,7 +113,7 @@
val onKeyguard = keyguardUpdateMonitor.isKeyguardVisible &&
!statusBarStateController.isDozing
- val isFaceEnabled = keyguardFaceAuthInteractor.isFaceAuthEnabledAndEnrolled()
+ val isFaceEnabled = deviceEntryFaceAuthInteractor.isFaceAuthEnabledAndEnrolled()
val shouldListen = (onKeyguard || bouncerVisible) && isFaceEnabled
if (shouldListen != isListening) {
isListening = shouldListen
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 4999123..88347ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -18,6 +18,7 @@
import static android.view.WindowInsets.Type.navigationBars;
+import static com.android.systemui.Flags.predictiveBackAnimateBouncer;
import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN;
import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
@@ -400,8 +401,7 @@
mFoldAodAnimationController = sysUIUnfoldComponent
.map(SysUIUnfoldComponent::getFoldAodAnimationController).orElse(null);
mAlternateBouncerInteractor = alternateBouncerInteractor;
- mIsBackAnimationEnabled =
- featureFlags.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_BOUNCER_ANIM);
+ mIsBackAnimationEnabled = predictiveBackAnimateBouncer();
mUdfpsOverlayInteractor = udfpsOverlayInteractor;
mActivityStarter = activityStarter;
mKeyguardTransitionInteractor = keyguardTransitionInteractor;
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
index 5558aa7..111492c 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
@@ -43,7 +43,7 @@
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.res.R;
@@ -69,7 +69,7 @@
private final Executor mExecutor;
private final Handler mHandler;
private final FalsingManager mFalsingManager;
- private final KeyguardFaceAuthInteractor mKeyguardFaceAuthInteractor;
+ private final DeviceEntryFaceAuthInteractor mDeviceEntryFaceAuthInteractor;
private FalsingCollector mFalsingCollector;
private final UserTracker mUserTracker;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@@ -94,7 +94,7 @@
KeyguardUpdateMonitor keyguardUpdateMonitor,
StatusBarKeyguardViewManager keyguardViewManager,
UiEventLogger uiEventLogger,
- KeyguardFaceAuthInteractor keyguardFaceAuthInteractor) {
+ DeviceEntryFaceAuthInteractor deviceEntryFaceAuthInteractor) {
mKeyguardStateController = keyguardStateController;
mKeyguardDismissUtil = keyguardDismissUtil;
mActivityStarter = activityStarter;
@@ -106,7 +106,7 @@
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mKeyguardViewManager = keyguardViewManager;
mUiEventLogger = uiEventLogger;
- mKeyguardFaceAuthInteractor = keyguardFaceAuthInteractor;
+ mDeviceEntryFaceAuthInteractor = deviceEntryFaceAuthInteractor;
}
@Override
@@ -213,7 +213,7 @@
true,
Utils.getColorAttrDefaultColor(
this, com.android.internal.R.attr.colorAccentPrimary));
- mKeyguardFaceAuthInteractor.onWalletLaunched();
+ mDeviceEntryFaceAuthInteractor.onWalletLaunched();
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index c5ce856..bb98595 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -120,16 +120,19 @@
import com.android.keyguard.KeyguardUpdateMonitor.BiometricAuthenticated;
import com.android.keyguard.logging.KeyguardUpdateMonitorLogger;
import com.android.settingslib.fuelgauge.BatteryStatus;
+import com.android.systemui.Flags;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.biometrics.FingerprintInteractiveToAuthProvider;
import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.deviceentry.data.repository.FaceWakeUpTriggersConfig;
+import com.android.systemui.deviceentry.data.repository.FaceWakeUpTriggersConfigImpl;
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor;
+import com.android.systemui.deviceentry.domain.interactor.FaceAuthenticationListener;
+import com.android.systemui.deviceentry.shared.model.ErrorFaceAuthenticationStatus;
+import com.android.systemui.deviceentry.shared.model.FaceDetectionStatus;
+import com.android.systemui.deviceentry.shared.model.FailedFaceAuthenticationStatus;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.keyguard.domain.interactor.FaceAuthenticationListener;
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
-import com.android.systemui.keyguard.shared.model.ErrorFaceAuthenticationStatus;
-import com.android.systemui.keyguard.shared.model.FaceDetectionStatus;
-import com.android.systemui.keyguard.shared.model.FailedFaceAuthenticationStatus;
import com.android.systemui.log.SessionTracker;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.settings.UserTracker;
@@ -261,7 +264,7 @@
@Mock
private SelectedUserInteractor mSelectedUserInteractor;
@Mock
- private KeyguardFaceAuthInteractor mFaceAuthInteractor;
+ private DeviceEntryFaceAuthInteractor mFaceAuthInteractor;
@Captor
private ArgumentCaptor<FaceAuthenticationListener> mFaceAuthenticationListener;
@@ -315,7 +318,7 @@
mContext.getOrCreateTestableResources().addOverride(
com.android.systemui.res.R.integer.config_face_auth_supported_posture,
DEVICE_POSTURE_UNKNOWN);
- mFaceWakeUpTriggersConfig = new FaceWakeUpTriggersConfig(
+ mFaceWakeUpTriggersConfig = new FaceWakeUpTriggersConfigImpl(
mContext.getResources(),
mGlobalSettings,
mDumpManager
@@ -923,8 +926,7 @@
@Test
public void trustAgentHasTrust() {
// WHEN user has trust
- mKeyguardUpdateMonitor.onTrustChanged(true, true,
- mSelectedUserInteractor.getSelectedUserId(), 0, null);
+ givenSelectedUserCanSkipBouncerFromTrustedState();
// THEN user is considered as "having trust" and bouncer can be skipped
Assert.assertTrue(mKeyguardUpdateMonitor.getUserHasTrust(
@@ -948,8 +950,7 @@
@Test
public void trustAgentHasTrust_fingerprintLockout() {
// GIVEN user has trust
- mKeyguardUpdateMonitor.onTrustChanged(true, true,
- mSelectedUserInteractor.getSelectedUserId(), 0, null);
+ givenSelectedUserCanSkipBouncerFromTrustedState();
Assert.assertTrue(mKeyguardUpdateMonitor.getUserHasTrust(
mSelectedUserInteractor.getSelectedUserId()));
@@ -1992,6 +1993,43 @@
}
@Test
+ public void runFpDetectFlagDisabled_sideFps_keyguardDismissible_fingerprintAuthenticateRuns() {
+ mSetFlagsRule.disableFlags(Flags.FLAG_RUN_FINGERPRINT_DETECT_ON_DISMISSIBLE_KEYGUARD);
+
+ // Clear invocations, since previous setup (e.g. registering BiometricManager callbacks)
+ // will trigger updateBiometricListeningState();
+ clearInvocations(mFingerprintManager);
+ mKeyguardUpdateMonitor.resetBiometricListeningState();
+
+ // GIVEN the user can skip the bouncer
+ givenSelectedUserCanSkipBouncerFromTrustedState();
+ when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
+ mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
+ mTestableLooper.processAllMessages();
+
+ // WHEN verify authenticate runs
+ verifyFingerprintAuthenticateCall();
+ }
+
+ @Test
+ public void sideFps_keyguardDismissible_fingerprintDetectRuns() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_RUN_FINGERPRINT_DETECT_ON_DISMISSIBLE_KEYGUARD);
+ // Clear invocations, since previous setup (e.g. registering BiometricManager callbacks)
+ // will trigger updateBiometricListeningState();
+ clearInvocations(mFingerprintManager);
+ mKeyguardUpdateMonitor.resetBiometricListeningState();
+
+ // GIVEN the user can skip the bouncer
+ givenSelectedUserCanSkipBouncerFromTrustedState();
+ when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
+ mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
+ mTestableLooper.processAllMessages();
+
+ // WHEN verify detect runs
+ verifyFingerprintDetectCall();
+ }
+
+ @Test
public void testFingerprintSensorProperties() throws RemoteException {
mFingerprintAuthenticatorsRegisteredCallback.onAllAuthenticatorsRegistered(
new ArrayList<>());
@@ -2096,6 +2134,11 @@
verify(callback).onBiometricEnrollmentStateChanged(BiometricSourceType.FACE);
}
+ private void givenSelectedUserCanSkipBouncerFromTrustedState() {
+ mKeyguardUpdateMonitor.onTrustChanged(true, true,
+ mSelectedUserInteractor.getSelectedUserId(), 0, null);
+ }
+
private void verifyFingerprintAuthenticateNeverCalled() {
verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), any());
verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/back/domain/interactor/BackActionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/back/domain/interactor/BackActionInteractorTest.kt
index 8693d5c..7c626a1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/back/domain/interactor/BackActionInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/back/domain/interactor/BackActionInteractorTest.kt
@@ -16,6 +16,9 @@
package com.android.systemui.back.domain.interactor
+import android.platform.test.annotations.RequiresFlagsDisabled
+import android.platform.test.annotations.RequiresFlagsEnabled
+import android.platform.test.flag.junit.DeviceFlagsValueProvider
import android.view.ViewRootImpl
import android.window.BackEvent
import android.window.BackEvent.EDGE_LEFT
@@ -26,9 +29,8 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.statusbar.IStatusBarService
+import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
-import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest
@@ -72,7 +74,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
class BackActionInteractorTest : SysuiTestCase() {
private val testScope = TestScope()
- private val featureFlags = FakeFeatureFlags()
private val executor = FakeExecutor(FakeSystemClock())
@JvmField @Rule var mockitoRule = MockitoJUnit.rule()
@@ -107,17 +108,17 @@
statusBarKeyguardViewManager,
shadeController,
notificationShadeWindowController,
- windowRootViewVisibilityInteractor,
- featureFlags,
+ windowRootViewVisibilityInteractor
)
.apply { this.setup(qsController, shadeViewController) }
}
private val powerInteractor = PowerInteractorFactory.create().powerInteractor
+ @get:Rule val checkFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
+
@Before
fun setUp() {
- featureFlags.set(Flags.WM_SHADE_ANIMATE_BACK_GESTURE, false)
whenever(notificationShadeWindowController.windowRootView).thenReturn(windowRootView)
whenever(windowRootView.viewRootImpl).thenReturn(viewRootImpl)
whenever(viewRootImpl.onBackInvokedDispatcher).thenReturn(onBackInvokedDispatcher)
@@ -229,9 +230,9 @@
}
@Test
+ @RequiresFlagsDisabled(Flags.FLAG_PREDICTIVE_BACK_ANIMATE_SHADE)
fun animationFlagOff_onBackInvoked_keyguardNotified() {
backActionInteractor.start()
- featureFlags.set(Flags.WM_SHADE_ANIMATE_BACK_GESTURE, false)
windowRootViewVisibilityInteractor.setIsLockscreenOrShadeVisible(true)
powerInteractor.setAwakeForTest()
val callback = getBackInvokedCallback()
@@ -243,8 +244,8 @@
}
@Test
+ @RequiresFlagsEnabled(Flags.FLAG_PREDICTIVE_BACK_ANIMATE_SHADE)
fun animationFlagOn_onBackInvoked_keyguardNotified() {
- featureFlags.set(Flags.WM_SHADE_ANIMATE_BACK_GESTURE, true)
backActionInteractor.start()
windowRootViewVisibilityInteractor.setIsLockscreenOrShadeVisible(true)
powerInteractor.setAwakeForTest()
@@ -257,8 +258,8 @@
}
@Test
+ @RequiresFlagsEnabled(Flags.FLAG_PREDICTIVE_BACK_ANIMATE_SHADE)
fun animationFlagOn_callbackIsAnimationCallback() {
- featureFlags.set(Flags.WM_SHADE_ANIMATE_BACK_GESTURE, true)
backActionInteractor.start()
windowRootViewVisibilityInteractor.setIsLockscreenOrShadeVisible(true)
powerInteractor.setAwakeForTest()
@@ -269,8 +270,8 @@
}
@Test
+ @RequiresFlagsEnabled(Flags.FLAG_PREDICTIVE_BACK_ANIMATE_SHADE)
fun onBackProgressed_shadeCannotBeCollapsed_shadeViewControllerNotNotified() {
- featureFlags.set(Flags.WM_SHADE_ANIMATE_BACK_GESTURE, true)
backActionInteractor.start()
windowRootViewVisibilityInteractor.setIsLockscreenOrShadeVisible(true)
powerInteractor.setAwakeForTest()
@@ -284,8 +285,8 @@
}
@Test
+ @RequiresFlagsEnabled(Flags.FLAG_PREDICTIVE_BACK_ANIMATE_SHADE)
fun onBackProgressed_shadeCanBeCollapsed_shadeViewControllerNotified() {
- featureFlags.set(Flags.WM_SHADE_ANIMATE_BACK_GESTURE, true)
backActionInteractor.start()
windowRootViewVisibilityInteractor.setIsLockscreenOrShadeVisible(true)
powerInteractor.setAwakeForTest()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
index 1f7dd6d..c143bc0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
@@ -123,7 +123,6 @@
udfpsControllerProvider,
statusBarStateController,
displayMetrics,
- featureFlags,
KeyguardLogger(logcatLogBuffer(AuthRippleController.TAG)),
biometricUnlockController,
lightRevealScrim,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/FaceAuthAccessibilityDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/FaceAuthAccessibilityDelegateTest.kt
index 86b9b84..9b0e58d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/FaceAuthAccessibilityDelegateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/FaceAuthAccessibilityDelegateTest.kt
@@ -22,7 +22,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.whenever
@@ -42,7 +42,7 @@
class FaceAuthAccessibilityDelegateTest : SysuiTestCase() {
@Mock private lateinit var hostView: View
- @Mock private lateinit var faceAuthInteractor: KeyguardFaceAuthInteractor
+ @Mock private lateinit var faceAuthInteractor: DeviceEntryFaceAuthInteractor
private lateinit var underTest: FaceAuthAccessibilityDelegate
@Before
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt
index 755fa02..54dbd04 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt
@@ -57,13 +57,13 @@
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.bouncer.ui.BouncerView
import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
import com.android.systemui.display.data.repository.FakeDisplayRepository
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.FakeTrustRepository
import com.android.systemui.keyguard.domain.interactor.DeviceEntrySideFpsOverlayInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
import com.android.systemui.keyguard.ui.viewmodel.SideFpsProgressBarViewModel
import com.android.systemui.log.SideFpsLogger
import com.android.systemui.log.logcatLogBuffer
@@ -110,7 +110,7 @@
@JvmField @Rule var mockitoRule: MockitoRule = MockitoJUnit.rule()
@Mock private lateinit var activityTaskManager: ActivityTaskManager
@Mock private lateinit var displayManager: DisplayManager
- @Mock private lateinit var faceAuthInteractor: KeyguardFaceAuthInteractor
+ @Mock private lateinit var faceAuthInteractor: DeviceEntryFaceAuthInteractor
@Mock
private lateinit var fingerprintInteractiveToAuthProvider: FingerprintInteractiveToAuthProvider
@Mock private lateinit var fpsUnlockTracker: FpsUnlockTracker
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt
index bdca948..1fa60fc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt
@@ -55,13 +55,13 @@
import com.android.systemui.bouncer.ui.BouncerView
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
import com.android.systemui.display.data.repository.FakeDisplayRepository
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.FakeTrustRepository
import com.android.systemui.keyguard.domain.interactor.DeviceEntrySideFpsOverlayInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
import com.android.systemui.keyguard.ui.viewmodel.SideFpsProgressBarViewModel
import com.android.systemui.log.SideFpsLogger
import com.android.systemui.log.logcatLogBuffer
@@ -101,7 +101,7 @@
@JvmField @Rule var mockitoRule: MockitoRule = MockitoJUnit.rule()
@Mock private lateinit var activityTaskManager: ActivityTaskManager
- @Mock private lateinit var faceAuthInteractor: KeyguardFaceAuthInteractor
+ @Mock private lateinit var faceAuthInteractor: DeviceEntryFaceAuthInteractor
@Mock
private lateinit var fingerprintInteractiveToAuthProvider: FingerprintInteractiveToAuthProvider
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractorTest.kt
index 45a426e..e796303 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractorTest.kt
@@ -36,13 +36,13 @@
import com.android.systemui.bouncer.ui.BouncerView
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
import com.android.systemui.flags.SystemPropertiesHelper
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFaceAuthRepository
import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.FakeTrustRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
import com.android.systemui.keyguard.shared.model.AuthenticationFlags
import com.android.systemui.res.R.string.kg_too_many_failed_attempts_countdown
import com.android.systemui.res.R.string.kg_trust_agent_disabled
@@ -122,7 +122,7 @@
fakeTrustRepository,
testScope.backgroundScope,
mSelectedUserInteractor,
- mock(KeyguardFaceAuthInteractor::class.java),
+ mock(DeviceEntryFaceAuthInteractor::class.java),
)
underTest =
BouncerMessageInteractor(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorTest.kt
index dacf23a..ee46f76 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorTest.kt
@@ -32,9 +32,9 @@
import com.android.systemui.bouncer.ui.BouncerView
import com.android.systemui.bouncer.ui.BouncerViewDelegate
import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.repository.FakeTrustRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.res.R
import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
@@ -73,7 +73,7 @@
@Mock private lateinit var dismissCallbackRegistry: DismissCallbackRegistry
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
@Mock private lateinit var mSelectedUserInteractor: SelectedUserInteractor
- @Mock private lateinit var faceAuthInteractor: KeyguardFaceAuthInteractor
+ @Mock private lateinit var faceAuthInteractor: DeviceEntryFaceAuthInteractor
private lateinit var mainHandler: FakeHandler
private lateinit var underTest: PrimaryBouncerInteractor
private lateinit var resources: TestableResources
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsInteractorTest.kt
index 59bcf01..d5c3641 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsInteractorTest.kt
@@ -24,13 +24,13 @@
import com.android.systemui.biometrics.shared.model.SensorStrength
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.deviceentry.domain.interactor.deviceEntryHapticsInteractor
+import com.android.systemui.deviceentry.shared.model.FailedFaceAuthenticationStatus
import com.android.systemui.keyevent.data.repository.fakeKeyEventRepository
import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
import com.android.systemui.keyguard.data.repository.deviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository
import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
import com.android.systemui.keyguard.shared.model.FailFingerprintAuthenticationStatus
-import com.android.systemui.keyguard.shared.model.FailedFaceAuthenticationStatus
import com.android.systemui.kosmos.testScope
import com.android.systemui.power.data.repository.powerRepository
import com.android.systemui.power.shared.model.WakeSleepReason
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/FaceWakeUpTriggersConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/FaceWakeUpTriggersConfigTest.kt
similarity index 91%
rename from packages/SystemUI/tests/src/com/android/keyguard/FaceWakeUpTriggersConfigTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/FaceWakeUpTriggersConfigTest.kt
index 94c34a5..e9b4bbb 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/FaceWakeUpTriggersConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/FaceWakeUpTriggersConfigTest.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.keyguard
+package com.android.systemui.deviceentry.data.repository
import android.os.PowerManager
import android.testing.AndroidTestingRunner
@@ -71,6 +71,6 @@
wakeUpTriggers
)
- return FaceWakeUpTriggersConfig(mContext.getResources(), globalSettings, dumpManager)
+ return FaceWakeUpTriggersConfigImpl(mContext.resources, globalSettings, dumpManager)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorTest.kt
similarity index 93%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorTest.kt
index 769cf45..368d1d9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorTest.kt
@@ -1,21 +1,20 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * 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
+ * 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.
- *
+ * 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.keyguard.domain.interactor
+package com.android.systemui.deviceentry.domain.interactor
import android.app.trust.TrustManager
import android.content.pm.UserInfo
@@ -25,8 +24,6 @@
import android.os.PowerManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.keyguard.FaceAuthUiEvent
-import com.android.keyguard.FaceWakeUpTriggersConfig
import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.SysuiTestCase
@@ -42,6 +39,9 @@
import com.android.systemui.bouncer.ui.BouncerView
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.deviceentry.data.repository.FaceWakeUpTriggersConfig
+import com.android.systemui.deviceentry.shared.FaceAuthUiEvent
+import com.android.systemui.deviceentry.shared.model.ErrorFaceAuthenticationStatus
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFaceAuthRepository
@@ -49,7 +49,8 @@
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.FakeTrustRepository
-import com.android.systemui.keyguard.shared.model.ErrorFaceAuthenticationStatus
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
@@ -87,9 +88,9 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
-class KeyguardFaceAuthInteractorTest : SysuiTestCase() {
+class DeviceEntryFaceAuthInteractorTest : SysuiTestCase() {
- private lateinit var underTest: SystemUIKeyguardFaceAuthInteractor
+ private lateinit var underTest: SystemUIDeviceEntryFaceAuthInteractor
private lateinit var testScope: TestScope
private lateinit var bouncerRepository: FakeKeyguardBouncerRepository
private lateinit var keyguardTransitionRepository: FakeKeyguardTransitionRepository
@@ -133,7 +134,7 @@
fakeBiometricSettingsRepository = FakeBiometricSettingsRepository()
underTest =
- SystemUIKeyguardFaceAuthInteractor(
+ SystemUIDeviceEntryFaceAuthInteractor(
mContext,
testScope.backgroundScope,
dispatcher,
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/FaceAuthReasonTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/shared/FaceAuthReasonTest.kt
similarity index 92%
rename from packages/SystemUI/tests/src/com/android/keyguard/FaceAuthReasonTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/deviceentry/shared/FaceAuthReasonTest.kt
index 68d0f41..ef89752 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/FaceAuthReasonTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/shared/FaceAuthReasonTest.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.keyguard
+
+package com.android.systemui.deviceentry.shared
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt
index 027dfa1..c4df27c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt
@@ -29,6 +29,7 @@
import com.android.systemui.bouncer.ui.BouncerView
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
@@ -62,7 +63,7 @@
class DeviceEntrySideFpsOverlayInteractorTest : SysuiTestCase() {
@JvmField @Rule var mockitoRule: MockitoRule = MockitoJUnit.rule()
- @Mock private lateinit var faceAuthInteractor: KeyguardFaceAuthInteractor
+ @Mock private lateinit var faceAuthInteractor: DeviceEntryFaceAuthInteractor
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
@Mock private lateinit var mSelectedUserInteractor: SelectedUserInteractor
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt
index 1f245f1..7358b9d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt
@@ -147,7 +147,7 @@
trustRepository,
testScope.backgroundScope,
mSelectedUserInteractor,
- keyguardFaceAuthInteractor = mock(),
+ deviceEntryFaceAuthInteractor = mock(),
),
AlternateBouncerInteractor(
statusBarStateController = mock(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
index 018fa9e..a92111e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
@@ -394,6 +394,7 @@
public void setTiles_differentTiles_extraTileRemoved() {
when(mQSHost.getTiles()).thenReturn(List.of(mQSTile, mOtherTile));
mController.setTiles();
+ assertEquals(2, mController.mRecords.size());
clearInvocations(mQSPanel);
@@ -402,6 +403,7 @@
verify(mQSPanel, times(1)).removeTile(any());
verify(mQSPanel, never()).addTile(any());
+ assertEquals(1, mController.mRecords.size());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
index 2220756..3132767 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -86,6 +86,7 @@
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository;
import com.android.systemui.common.ui.view.LongPressHandlingView;
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor;
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.dump.DumpManager;
@@ -98,7 +99,6 @@
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
@@ -337,7 +337,7 @@
protected ArgumentCaptor<NotificationStackScrollLayout.OnEmptySpaceClickListener>
mEmptySpaceClickListenerCaptor;
@Mock protected ActivityStarter mActivityStarter;
- @Mock protected KeyguardFaceAuthInteractor mKeyguardFaceAuthInteractor;
+ @Mock protected DeviceEntryFaceAuthInteractor mDeviceEntryFaceAuthInteractor;
@Mock private JavaAdapter mJavaAdapter;
@Mock private CastController mCastController;
@Mock private SharedNotificationContainerInteractor mSharedNotificationContainerInteractor;
@@ -382,7 +382,6 @@
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- mFeatureFlags.set(Flags.WM_SHADE_ANIMATE_BACK_GESTURE, false);
mFeatureFlags.set(Flags.TRACKPAD_GESTURE_FEATURES, false);
mFeatureFlags.set(Flags.LOCKSCREEN_ENABLE_LANDSCAPE, false);
mFeatureFlags.set(Flags.QS_USER_DETAIL_SHORTCUT, false);
@@ -730,7 +729,7 @@
mActiveNotificationsInteractor,
mShadeAnimationInteractor,
mKeyguardViewConfigurator,
- mKeyguardFaceAuthInteractor,
+ mDeviceEntryFaceAuthInteractor,
new ResourcesSplitShadeStateController(),
mPowerInteractor,
mKeyguardClockPositionAlgorithm,
@@ -800,7 +799,7 @@
mInteractionJankMonitor,
mShadeLog,
mDumpManager,
- mKeyguardFaceAuthInteractor,
+ mDeviceEntryFaceAuthInteractor,
mShadeRepository,
mShadeInteractor,
mActiveNotificationsInteractor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
index 3cbb9bb..2e8d46a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -1120,7 +1120,7 @@
mTouchHandler.onTouch(mock(View.class), mDownMotionEvent);
mEmptySpaceClickListenerCaptor.getValue().onEmptySpaceClicked(0, 0);
- verify(mKeyguardFaceAuthInteractor).onNotificationPanelClicked();
+ verify(mDeviceEntryFaceAuthInteractor).onNotificationPanelClicked();
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
index c21addc..ee7c6c8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -62,7 +62,7 @@
import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFaceAuthRepository
import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.FakeTrustRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl
import com.android.systemui.keyguard.shared.model.TransitionStep
@@ -257,7 +257,7 @@
FakeTrustRepository(),
testScope.backgroundScope,
mSelectedUserInteractor,
- mock(KeyguardFaceAuthInteractor::class.java)
+ mock(DeviceEntryFaceAuthInteractor::class.java)
),
facePropertyRepository = FakeFacePropertyRepository(),
deviceEntryFingerprintAuthRepository =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java
index eb5633b..727a6c3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java
@@ -42,6 +42,7 @@
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository;
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository;
import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor;
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor;
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FakeFeatureFlagsClassic;
@@ -55,7 +56,6 @@
import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor;
import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor;
import com.android.systemui.keyguard.domain.interactor.InWindowLauncherUnlockAnimationInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.media.controls.pipeline.MediaDataManager;
@@ -378,7 +378,7 @@
mInteractionJankMonitor,
mShadeLogger,
mDumpManager,
- mock(KeyguardFaceAuthInteractor.class),
+ mock(DeviceEntryFaceAuthInteractor.class),
mShadeRepository,
mShadeInteractor,
mActiveNotificationsInteractor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index e339636..316f2b9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -334,15 +334,8 @@
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
- // CentralSurfacesImpl's runtime flag check fails if the flag is absent.
- // This value is unused, because test manifest is opted in.
- mFeatureFlags.set(Flags.WM_ENABLE_PREDICTIVE_BACK_SYSUI, false);
// Set default value to avoid IllegalStateException.
mFeatureFlags.set(Flags.SHORTCUT_LIST_SEARCH_LAYOUT, false);
- // For the Shade to respond to Back gesture, we must enable the event routing
- mFeatureFlags.set(Flags.WM_SHADE_ALLOW_BACK_GESTURE, true);
- // For the Shade to animate during the Back gesture, we must enable the animation flag.
- mFeatureFlags.set(Flags.WM_SHADE_ANIMATE_BACK_GESTURE, true);
mSetFlagsRule.enableFlags(FLAG_LIGHT_REVEAL_MIGRATION);
// Turn AOD on and toggle feature flag for jank fixes
mFeatureFlags.set(Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD, true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 225ddb6..8dde935 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -37,6 +37,9 @@
import static kotlinx.coroutines.test.TestCoroutineDispatchersKt.StandardTestDispatcher;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.service.trust.TrustAgentService;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -98,6 +101,7 @@
import com.google.common.truth.Truth;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -165,6 +169,8 @@
@Captor
private ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallback;
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
@Before
public void setUp() {
@@ -175,7 +181,6 @@
when(mBouncerView.getDelegate()).thenReturn(mBouncerViewDelegate);
when(mBouncerViewDelegate.getBackCallback()).thenReturn(mBouncerViewDelegateBackCallback);
mFeatureFlags = new FakeFeatureFlags();
- mFeatureFlags.set(Flags.WM_ENABLE_PREDICTIVE_BACK_BOUNCER_ANIM, true);
mFeatureFlags.set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false);
mFeatureFlags.set(Flags.KEYGUARD_WM_STATE_REFACTOR, false);
mSetFlagsRule.disableFlags(com.android.systemui.Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR);
@@ -584,6 +589,7 @@
}
@Test
+ @RequiresFlagsEnabled(com.android.systemui.Flags.FLAG_PREDICTIVE_BACK_ANIMATE_BOUNCER)
public void testPredictiveBackCallback_registration() {
/* verify that a predictive back callback is registered when the bouncer becomes visible */
mBouncerExpansionCallback.onVisibilityChanged(true);
@@ -598,6 +604,7 @@
}
@Test
+ @RequiresFlagsEnabled(com.android.systemui.Flags.FLAG_PREDICTIVE_BACK_ANIMATE_BOUNCER)
public void testPredictiveBackCallback_invocationHidesBouncer() {
mBouncerExpansionCallback.onVisibilityChanged(true);
/* capture the predictive back callback during registration */
@@ -615,6 +622,7 @@
}
@Test
+ @RequiresFlagsEnabled(com.android.systemui.Flags.FLAG_PREDICTIVE_BACK_ANIMATE_BOUNCER)
public void testPredictiveBackCallback_noBackAnimationForFullScreenBouncer() {
when(mKeyguardSecurityModel.getSecurityMode(anyInt()))
.thenReturn(KeyguardSecurityModel.SecurityMode.SimPin);
@@ -634,6 +642,7 @@
}
@Test
+ @RequiresFlagsEnabled(com.android.systemui.Flags.FLAG_PREDICTIVE_BACK_ANIMATE_BOUNCER)
public void testPredictiveBackCallback_forwardsBackDispatches() {
mBouncerExpansionCallback.onVisibilityChanged(true);
/* capture the predictive back callback during registration */
diff --git a/packages/SystemUI/tests/utils/src/com/android/keyguard/TrustManagerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/keyguard/TrustManagerKosmos.kt
new file mode 100644
index 0000000..187935b
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/keyguard/TrustManagerKosmos.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.keyguard
+
+import android.app.trust.TrustManager
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
+
+val Kosmos.trustManager by Kosmos.Fixture { mock<TrustManager>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FacePropertyRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FacePropertyRepositoryKosmos.kt
new file mode 100644
index 0000000..6ef7419
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FacePropertyRepositoryKosmos.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics.data.repository
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+
+val Kosmos.facePropertyRepository by Fixture { FakeFacePropertyRepository() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FaceWakeUpTriggersConfigKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FaceWakeUpTriggersConfigKosmos.kt
new file mode 100644
index 0000000..21cff0d
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FaceWakeUpTriggersConfigKosmos.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.deviceentry.data.repository
+
+import com.android.systemui.kosmos.Kosmos
+
+var Kosmos.faceWakeUpTriggersConfig: FaceWakeUpTriggersConfig by
+ Kosmos.Fixture { FakeFaceWakeUpTriggersConfig() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeFaceWakeUpTriggersConfig.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeFaceWakeUpTriggersConfig.kt
new file mode 100644
index 0000000..af617b7
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeFaceWakeUpTriggersConfig.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.deviceentry.data.repository
+
+import com.android.systemui.power.shared.model.WakeSleepReason
+
+class FakeFaceWakeUpTriggersConfig : FaceWakeUpTriggersConfig {
+ private val triggerFaceAuthOnWakeUpFrom: MutableSet<Int> = mutableSetOf()
+ private val wakeSleepReasonsToTriggerFaceAuth: MutableSet<WakeSleepReason> = mutableSetOf()
+ override fun shouldTriggerFaceAuthOnWakeUpFrom(pmWakeReason: Int): Boolean {
+ return triggerFaceAuthOnWakeUpFrom.contains(pmWakeReason)
+ }
+
+ override fun shouldTriggerFaceAuthOnWakeUpFrom(wakeReason: WakeSleepReason): Boolean {
+ return wakeSleepReasonsToTriggerFaceAuth.contains(wakeReason)
+ }
+
+ fun setTriggerFaceAuthOnWakeUpFrom(pmWakeReasons: Set<Int>) {
+ triggerFaceAuthOnWakeUpFrom.clear()
+ triggerFaceAuthOnWakeUpFrom.addAll(pmWakeReasons)
+
+ wakeSleepReasonsToTriggerFaceAuth.clear()
+ wakeSleepReasonsToTriggerFaceAuth.addAll(
+ pmWakeReasons.map { WakeSleepReason.fromPowerManagerWakeReason(it) }
+ )
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorKosmos.kt
index d2dff78..0b1fb40 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorKosmos.kt
@@ -18,13 +18,45 @@
package com.android.systemui.deviceentry.domain.interactor
+import android.content.applicationContext
+import com.android.keyguard.keyguardUpdateMonitor
+import com.android.keyguard.trustManager
+import com.android.systemui.biometrics.data.repository.facePropertyRepository
+import com.android.systemui.bouncer.domain.interactor.alternateBouncerInteractor
+import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor
+import com.android.systemui.deviceentry.data.repository.faceWakeUpTriggersConfig
+import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
import com.android.systemui.keyguard.data.repository.deviceEntryFaceAuthRepository
+import com.android.systemui.keyguard.data.repository.deviceEntryFingerprintAuthRepository
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.log.FaceAuthenticationLogger
+import com.android.systemui.power.domain.interactor.powerInteractor
+import com.android.systemui.user.data.repository.userRepository
+import com.android.systemui.util.mockito.mock
import kotlinx.coroutines.ExperimentalCoroutinesApi
+val Kosmos.faceAuthLogger by Kosmos.Fixture { mock<FaceAuthenticationLogger>() }
val Kosmos.deviceEntryFaceAuthInteractor by
Kosmos.Fixture {
- DeviceEntryFaceAuthInteractor(
+ SystemUIDeviceEntryFaceAuthInteractor(
+ context = applicationContext,
+ applicationScope = applicationCoroutineScope,
+ mainDispatcher = testDispatcher,
repository = deviceEntryFaceAuthRepository,
+ primaryBouncerInteractor = { primaryBouncerInteractor },
+ alternateBouncerInteractor = alternateBouncerInteractor,
+ keyguardTransitionInteractor = keyguardTransitionInteractor,
+ faceAuthenticationLogger = faceAuthLogger,
+ keyguardUpdateMonitor = keyguardUpdateMonitor,
+ deviceEntryFingerprintAuthRepository = deviceEntryFingerprintAuthRepository,
+ userRepository = userRepository,
+ facePropertyRepository = facePropertyRepository,
+ faceWakeUpTriggersConfig = faceWakeUpTriggersConfig,
+ powerInteractor = powerInteractor,
+ biometricSettingsRepository = biometricSettingsRepository,
+ trustManager = trustManager,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryKosmos.kt
index 3d72967..599b5142 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryKosmos.kt
@@ -16,6 +16,7 @@
package com.android.systemui.keyguard.data.repository
+import com.android.systemui.deviceentry.data.repository.DeviceEntryFaceAuthRepository
import com.android.systemui.kosmos.Kosmos
var Kosmos.deviceEntryFaceAuthRepository: DeviceEntryFaceAuthRepository by
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFaceAuthRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFaceAuthRepository.kt
index a1b6587..e96aeada 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFaceAuthRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFaceAuthRepository.kt
@@ -16,10 +16,11 @@
package com.android.systemui.keyguard.data.repository
-import com.android.keyguard.FaceAuthUiEvent
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus
-import com.android.systemui.keyguard.shared.model.FaceDetectionStatus
+import com.android.systemui.deviceentry.data.repository.DeviceEntryFaceAuthRepository
+import com.android.systemui.deviceentry.shared.FaceAuthUiEvent
+import com.android.systemui.deviceentry.shared.model.FaceAuthenticationStatus
+import com.android.systemui.deviceentry.shared.model.FaceDetectionStatus
import dagger.Binds
import dagger.Module
import javax.inject.Inject
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorFactory.kt
index 3cabf0c..5f5d428 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorFactory.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorFactory.kt
@@ -27,6 +27,7 @@
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.bouncer.ui.BouncerView
import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
@@ -73,7 +74,7 @@
trustRepository,
testScope.backgroundScope,
mock(SelectedUserInteractor::class.java),
- mock(KeyguardFaceAuthInteractor::class.java),
+ mock(DeviceEntryFaceAuthInteractor::class.java),
)
val alternateBouncerInteractor =
AlternateBouncerInteractor(
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
index 9f71161..09ab655 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
@@ -52,20 +52,20 @@
import com.android.systemui.communal.data.repository.FakeCommunalRepository
import com.android.systemui.communal.domain.interactor.CommunalInteractor
import com.android.systemui.communal.domain.interactor.CommunalInteractorFactory
+import com.android.systemui.deviceentry.data.repository.DeviceEntryFaceAuthRepository
import com.android.systemui.deviceentry.data.repository.DeviceEntryRepository
import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.doze.DozeLogger
import com.android.systemui.flags.FakeFeatureFlagsClassic
import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository
import com.android.systemui.keyguard.data.repository.FakeCommandQueue
import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFaceAuthRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.FakeTrustRepository
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.keyguard.data.repository.TrustRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel
import com.android.systemui.kosmos.Kosmos
@@ -266,14 +266,14 @@
fun bouncerInteractor(
authenticationInteractor: AuthenticationInteractor,
- keyguardFaceAuthInteractor: KeyguardFaceAuthInteractor = mock(),
+ deviceEntryFaceAuthInteractor: DeviceEntryFaceAuthInteractor = mock(),
): BouncerInteractor {
return BouncerInteractor(
applicationScope = applicationScope(),
applicationContext = context,
repository = bouncerRepository,
authenticationInteractor = authenticationInteractor,
- keyguardFaceAuthInteractor = keyguardFaceAuthInteractor,
+ deviceEntryFaceAuthInteractor = deviceEntryFaceAuthInteractor,
falsingInteractor = falsingInteractor(),
powerInteractor = powerInteractor(),
simBouncerInteractor = simBouncerInteractor,
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 7ac4dd3..a1b6f29 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -7879,7 +7879,6 @@
DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_A2DP_SET);
DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_BLE_SET);
DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_USB_SET);
- DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_HDMI);
}
/** only public for mocking/spying, do not call outside of AudioService */
diff --git a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
index 6e503cb..030585f 100644
--- a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
@@ -970,9 +970,14 @@
if (!mIsBackUpSmoothDisplayAndForcePeakRefreshRateEnabled) {
// The flag had been turned off, we need to restore the original value
- Settings.System.putFloatForUser(cr,
- Settings.System.MIN_REFRESH_RATE, minRefreshRate, cr.getUserId());
+ Settings.System.putFloatForUser(cr, Settings.System.MIN_REFRESH_RATE,
+ highestRefreshRate, cr.getUserId());
}
+ } else if (mIsBackUpSmoothDisplayAndForcePeakRefreshRateEnabled
+ && Math.round(minRefreshRate) == Math.round(highestRefreshRate)) {
+ // The flag has been turned on, we need to upgrade the setting
+ Settings.System.putFloatForUser(cr, Settings.System.MIN_REFRESH_RATE,
+ Float.POSITIVE_INFINITY, cr.getUserId());
}
float peakRefreshRate = Settings.System.getFloatForUser(cr,
@@ -983,9 +988,14 @@
if (!mIsBackUpSmoothDisplayAndForcePeakRefreshRateEnabled) {
// The flag had been turned off, we need to restore the original value
- Settings.System.putFloatForUser(cr,
- Settings.System.PEAK_REFRESH_RATE, peakRefreshRate, cr.getUserId());
+ Settings.System.putFloatForUser(cr, Settings.System.PEAK_REFRESH_RATE,
+ highestRefreshRate, cr.getUserId());
}
+ } else if (mIsBackUpSmoothDisplayAndForcePeakRefreshRateEnabled
+ && Math.round(peakRefreshRate) == Math.round(highestRefreshRate)) {
+ // The flag has been turned on, we need to upgrade the setting
+ Settings.System.putFloatForUser(cr, Settings.System.PEAK_REFRESH_RATE,
+ Float.POSITIVE_INFINITY, cr.getUserId());
}
updateRefreshRateSettingLocked(minRefreshRate, peakRefreshRate, mDefaultRefreshRate);
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 24bcb4e..d722242 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -16,6 +16,7 @@
package com.android.server.inputmethod;
+import static android.content.Context.DEVICE_ID_DEFAULT;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
import static android.os.IServiceManager.DUMP_FLAG_PROTO;
@@ -315,10 +316,14 @@
// All known input methods.
final ArrayList<InputMethodInfo> mMethodList = new ArrayList<>();
private final ArrayMap<String, InputMethodInfo> mMethodMap = new ArrayMap<>();
+
// Mapping from deviceId to the device-specific imeId for that device.
+ @GuardedBy("ImfLock.class")
private final SparseArray<String> mVirtualDeviceMethodMap = new SparseArray<>();
- private final InputMethodSubtypeSwitchingController mSwitchingController;
+ // TODO: Instantiate mSwitchingController for each user.
+ @NonNull
+ private InputMethodSubtypeSwitchingController mSwitchingController;
final HardwareKeyboardShortcutController mHardwareKeyboardShortcutController =
new HardwareKeyboardShortcutController();
@@ -339,6 +344,9 @@
@GuardedBy("ImfLock.class")
private int mDisplayIdToShowIme = INVALID_DISPLAY;
+ @GuardedBy("ImfLock.class")
+ private int mDeviceIdToShowIme = DEVICE_ID_DEFAULT;
+
@Nullable private StatusBarManagerInternal mStatusBarManagerInternal;
private boolean mShowOngoingImeSwitcherForPhones;
@GuardedBy("ImfLock.class")
@@ -1699,7 +1707,8 @@
AdditionalSubtypeUtils.load(mAdditionalSubtypeMap, userId);
mSwitchingController =
- InputMethodSubtypeSwitchingController.createInstanceLocked(mSettings, context);
+ InputMethodSubtypeSwitchingController.createInstanceLocked(context, mMethodMap,
+ userId);
mHardwareKeyboardShortcutController.reset(mSettings);
mMenuController = new InputMethodMenuController(this);
mBindingController =
@@ -2464,11 +2473,7 @@
@StartInputReason int startInputReason,
int unverifiedTargetSdkVersion,
@NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
- // If no method is currently selected, do nothing.
- final String selectedMethodId = getSelectedMethodIdLocked();
- if (selectedMethodId == null) {
- return InputBindResult.NO_IME;
- }
+ String selectedMethodId = getSelectedMethodIdLocked();
if (!mSystemReady) {
// If the system is not yet ready, we shouldn't be running third
@@ -2493,8 +2498,21 @@
return InputBindResult.NOT_IME_TARGET_WINDOW;
}
final int csDisplayId = cs.mSelfReportedDisplayId;
+ final int oldDisplayIdToShowIme = mDisplayIdToShowIme;
mDisplayIdToShowIme = mVisibilityStateComputer.computeImeDisplayId(winState, csDisplayId);
+ // Potentially override the selected input method if the new display belongs to a virtual
+ // device with a custom IME.
+ if (oldDisplayIdToShowIme != mDisplayIdToShowIme) {
+ final String deviceMethodId = computeCurrentDeviceMethodIdLocked(selectedMethodId);
+ if (deviceMethodId == null) {
+ mVisibilityStateComputer.getImePolicy().setImeHiddenByDisplayPolicy(true);
+ } else if (!Objects.equals(deviceMethodId, selectedMethodId)) {
+ setInputMethodLocked(deviceMethodId, NOT_A_SUBTYPE_ID, mDeviceIdToShowIme);
+ selectedMethodId = deviceMethodId;
+ }
+ }
+
if (mVisibilityStateComputer.getImePolicy().isImeHiddenByDisplayPolicy()) {
hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */, 0 /* flags */,
null /* resultReceiver */,
@@ -2502,6 +2520,11 @@
return InputBindResult.NO_IME;
}
+ // If no method is currently selected, do nothing.
+ if (selectedMethodId == null) {
+ return InputBindResult.NO_IME;
+ }
+
if (mCurClient != cs) {
prepareClientSwitchLocked(cs);
}
@@ -2568,6 +2591,62 @@
return mBindingController.bindCurrentMethod();
}
+ /**
+ * Update the current deviceId and return the relevant imeId for this device.
+ * 1. If the device changes to virtual and its custom IME is not available, then disable IME.
+ * 2. If the device changes to virtual with valid custom IME, then return the custom IME. If
+ * the old device was default, then store the current imeId so it can be restored.
+ * 3. If the device changes to default, restore the default device IME.
+ * 4. Otherwise keep the current imeId.
+ */
+ @GuardedBy("ImfLock.class")
+ private String computeCurrentDeviceMethodIdLocked(String currentMethodId) {
+ if (mVdmInternal == null) {
+ mVdmInternal = LocalServices.getService(VirtualDeviceManagerInternal.class);
+ }
+ if (mVdmInternal == null || !android.companion.virtual.flags.Flags.vdmCustomIme()) {
+ return currentMethodId;
+ }
+
+ final int oldDeviceId = mDeviceIdToShowIme;
+ mDeviceIdToShowIme = mVdmInternal.getDeviceIdForDisplayId(mDisplayIdToShowIme);
+ if (mDeviceIdToShowIme == oldDeviceId) {
+ return currentMethodId;
+ }
+ if (mDeviceIdToShowIme == DEVICE_ID_DEFAULT) {
+ final String defaultDeviceMethodId = mSettings.getSelectedDefaultDeviceInputMethod();
+ if (DEBUG) {
+ Slog.v(TAG, "Restoring default device input method: " + defaultDeviceMethodId);
+ }
+ return defaultDeviceMethodId;
+ }
+
+ final String deviceMethodId =
+ mVirtualDeviceMethodMap.get(mDeviceIdToShowIme, currentMethodId);
+ if (Objects.equals(deviceMethodId, currentMethodId)) {
+ return currentMethodId;
+ } else if (!mMethodMap.containsKey(deviceMethodId)) {
+ if (DEBUG) {
+ Slog.v(TAG, "Disabling IME on virtual device with id " + mDeviceIdToShowIme
+ + " because its custom input method is not available: " + deviceMethodId);
+ }
+ return null;
+ }
+
+ if (oldDeviceId == DEVICE_ID_DEFAULT) {
+ if (DEBUG) {
+ Slog.v(TAG, "Storing default device input method " + currentMethodId);
+ }
+ mSettings.putSelectedDefaultDeviceInputMethod(currentMethodId);
+ }
+ if (DEBUG) {
+ Slog.v(TAG, "Switching current input method from " + currentMethodId
+ + " to device-specific one " + deviceMethodId + " because the current display "
+ + mDisplayIdToShowIme + " belongs to device with id " + mDeviceIdToShowIme);
+ }
+ return deviceMethodId;
+ }
+
@GuardedBy("ImfLock.class")
void invalidateAutofillSessionLocked() {
mAutofillController.invalidateAutofillSession();
@@ -3218,13 +3297,16 @@
// There is no longer an input method set, so stop any current one.
resetCurrentMethodAndClientLocked(UnbindReason.NO_IME);
}
- // Here is not the perfect place to reset the switching controller. Ideally
- // mSwitchingController and mSettings should be able to share the same state.
- // TODO: Make sure that mSwitchingController and mSettings are sharing the
- // the same enabled IMEs list.
- mSwitchingController.resetCircularListLocked(mContext);
- mHardwareKeyboardShortcutController.reset(mSettings);
+ // TODO: Instantiate mSwitchingController for each user.
+ if (mSettings.getCurrentUserId() == mSwitchingController.getUserId()) {
+ mSwitchingController.resetCircularListLocked(mMethodMap);
+ } else {
+ mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked(
+ mContext, mMethodMap, mSettings.getCurrentUserId());
+ }
+
+ mHardwareKeyboardShortcutController.reset(mSettings);
sendOnNavButtonFlagsChangedLocked();
}
@@ -3242,6 +3324,11 @@
@GuardedBy("ImfLock.class")
void setInputMethodLocked(String id, int subtypeId) {
+ setInputMethodLocked(id, subtypeId, DEVICE_ID_DEFAULT);
+ }
+
+ @GuardedBy("ImfLock.class")
+ void setInputMethodLocked(String id, int subtypeId, int deviceId) {
InputMethodInfo info = mMethodMap.get(id);
if (info == null) {
throw getExceptionForUnknownImeId(id);
@@ -3285,6 +3372,14 @@
}
// Changing to a different IME.
+ if (mDeviceIdToShowIme != DEVICE_ID_DEFAULT && deviceId == DEVICE_ID_DEFAULT) {
+ // This change should only be applicable to the default device but the current input
+ // method is a custom one specific to a virtual device. So only update the settings
+ // entry used to restore the default device input method once we want to show the IME
+ // back on the default device.
+ mSettings.putSelectedDefaultDeviceInputMethod(id);
+ return;
+ }
IInputMethodInvoker curMethod = getCurMethodLocked();
if (curMethod != null) {
curMethod.removeStylusHandwritingWindow();
@@ -4598,6 +4693,9 @@
}
return;
}
+ if (mSettings.getCurrentUserId() != mSwitchingController.getUserId()) {
+ return;
+ }
final InputMethodInfo imi = mMethodMap.get(getSelectedMethodIdLocked());
if (imi != null) {
mSwitchingController.onUserActionLocked(imi, mCurrentSubtype);
@@ -4835,9 +4933,10 @@
int lastInputMethodSubtypeId =
mSettings.getSelectedInputMethodSubtypeId(lastInputMethodId);
- final List<ImeSubtypeListItem> imList = mSwitchingController
- .getSortedInputMethodAndSubtypeListForImeMenuLocked(
- showAuxSubtypes, isScreenLocked);
+ final List<ImeSubtypeListItem> imList = InputMethodSubtypeSwitchingController
+ .getSortedInputMethodAndSubtypeList(
+ showAuxSubtypes, isScreenLocked, false, mContext,
+ mMethodMap, mSettings.getCurrentUserId());
mMenuController.showInputMethodMenuLocked(showAuxSubtypes, displayId,
lastInputMethodId, lastInputMethodSubtypeId, imList);
}
@@ -5222,11 +5321,13 @@
updateDefaultVoiceImeIfNeededLocked();
- // Here is not the perfect place to reset the switching controller. Ideally
- // mSwitchingController and mSettings should be able to share the same state.
- // TODO: Make sure that mSwitchingController and mSettings are sharing the
- // the same enabled IMEs list.
- mSwitchingController.resetCircularListLocked(mContext);
+ // TODO: Instantiate mSwitchingController for each user.
+ if (mSettings.getCurrentUserId() == mSwitchingController.getUserId()) {
+ mSwitchingController.resetCircularListLocked(mMethodMap);
+ } else {
+ mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked(
+ mContext, mMethodMap, mSettings.getCurrentUserId());
+ }
mHardwareKeyboardShortcutController.reset(mSettings);
sendOnNavButtonFlagsChangedLocked();
@@ -5308,11 +5409,21 @@
StringBuilder builder = new StringBuilder();
if (mSettings.buildAndPutEnabledInputMethodsStrRemovingIdLocked(
builder, enabledInputMethodsList, id)) {
- // Disabled input method is currently selected, switch to another one.
- final String selId = mSettings.getSelectedInputMethod();
- if (id.equals(selId) && !chooseNewDefaultIMELocked()) {
- Slog.i(TAG, "Can't find new IME, unsetting the current input method.");
- resetSelectedInputMethodAndSubtypeLocked("");
+ if (mDeviceIdToShowIme == DEVICE_ID_DEFAULT) {
+ // Disabled input method is currently selected, switch to another one.
+ final String selId = mSettings.getSelectedInputMethod();
+ if (id.equals(selId) && !chooseNewDefaultIMELocked()) {
+ Slog.i(TAG, "Can't find new IME, unsetting the current input method.");
+ resetSelectedInputMethodAndSubtypeLocked("");
+ }
+ } else if (id.equals(mSettings.getSelectedDefaultDeviceInputMethod())) {
+ // Disabled default device IME while using a virtual device one, choose a
+ // new default one but only update the settings.
+ InputMethodInfo newDefaultIme =
+ InputMethodInfoUtils.getMostApplicableDefaultIME(
+ mSettings.getEnabledInputMethodListLocked());
+ mSettings.putSelectedDefaultDeviceInputMethod(
+ newDefaultIme == null ? "" : newDefaultIme.getId());
}
// Previous state was enabled.
return true;
@@ -5652,9 +5763,8 @@
@Override
public void setVirtualDeviceInputMethodForAllUsers(int deviceId, @Nullable String imeId) {
- // TODO(b/287269288): validate that id belongs to a valid virtual device instead.
- Preconditions.checkArgument(deviceId != Context.DEVICE_ID_DEFAULT,
- "DeviceId " + deviceId + " does not belong to a virtual device.");
+ Preconditions.checkArgument(deviceId != DEVICE_ID_DEFAULT,
+ TextUtils.formatSimple("DeviceId %d is not a virtual device id.", deviceId));
synchronized (ImfLock.class) {
if (imeId == null) {
mVirtualDeviceMethodMap.remove(deviceId);
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java b/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java
index 431aabd..4439b06 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java
@@ -16,10 +16,14 @@
package com.android.server.inputmethod;
+import android.annotation.AnyThread;
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.content.Context;
-import android.content.pm.PackageManager;
+import android.os.UserHandle;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Printer;
import android.util.Slog;
@@ -32,7 +36,6 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.Locale;
import java.util.Objects;
/**
@@ -154,79 +157,71 @@
}
}
- private static class InputMethodAndSubtypeList {
- private final Context mContext;
- // Used to load label
- private final PackageManager mPm;
- private final String mSystemLocaleStr;
- private final InputMethodSettings mSettings;
+ static List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeList(
+ boolean includeAuxiliarySubtypes, boolean isScreenLocked, boolean forImeMenu,
+ @NonNull Context context, @NonNull ArrayMap<String, InputMethodInfo> methodMap,
+ @UserIdInt int userId) {
+ final Context userAwareContext = context.getUserId() == userId
+ ? context
+ : context.createContextAsUser(UserHandle.of(userId), 0 /* flags */);
+ final String mSystemLocaleStr = SystemLocaleWrapper.get(userId).get(0).toLanguageTag();
+ final InputMethodSettings settings = new InputMethodSettings(methodMap, userId);
- InputMethodAndSubtypeList(Context context, InputMethodSettings settings) {
- mContext = context;
- mSettings = settings;
- mPm = context.getPackageManager();
- final Locale locale = context.getResources().getConfiguration().locale;
- mSystemLocaleStr = locale != null ? locale.toString() : "";
+ final ArrayList<InputMethodInfo> imis = settings.getEnabledInputMethodListLocked();
+ if (imis.isEmpty()) {
+ return Collections.emptyList();
}
-
- public List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeList(
- boolean includeAuxiliarySubtypes, boolean isScreenLocked, boolean forImeMenu) {
- final ArrayList<InputMethodInfo> imis = mSettings.getEnabledInputMethodListLocked();
- if (imis.isEmpty()) {
- return Collections.emptyList();
+ if (isScreenLocked && includeAuxiliarySubtypes) {
+ if (DEBUG) {
+ Slog.w(TAG, "Auxiliary subtypes are not allowed to be shown in lock screen.");
}
- if (isScreenLocked && includeAuxiliarySubtypes) {
+ includeAuxiliarySubtypes = false;
+ }
+ final ArrayList<ImeSubtypeListItem> imList = new ArrayList<>();
+ final int numImes = imis.size();
+ for (int i = 0; i < numImes; ++i) {
+ final InputMethodInfo imi = imis.get(i);
+ if (forImeMenu && !imi.shouldShowInInputMethodPicker()) {
+ continue;
+ }
+ final List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypeList =
+ settings.getEnabledInputMethodSubtypeListLocked(imi, true);
+ final ArraySet<String> enabledSubtypeSet = new ArraySet<>();
+ for (InputMethodSubtype subtype : explicitlyOrImplicitlyEnabledSubtypeList) {
+ enabledSubtypeSet.add(String.valueOf(subtype.hashCode()));
+ }
+ final CharSequence imeLabel = imi.loadLabel(userAwareContext.getPackageManager());
+ if (enabledSubtypeSet.size() > 0) {
+ final int subtypeCount = imi.getSubtypeCount();
if (DEBUG) {
- Slog.w(TAG, "Auxiliary subtypes are not allowed to be shown in lock screen.");
+ Slog.v(TAG, "Add subtypes: " + subtypeCount + ", " + imi.getId());
}
- includeAuxiliarySubtypes = false;
- }
- final ArrayList<ImeSubtypeListItem> imList = new ArrayList<>();
- final int numImes = imis.size();
- for (int i = 0; i < numImes; ++i) {
- final InputMethodInfo imi = imis.get(i);
- if (forImeMenu && !imi.shouldShowInInputMethodPicker()) {
- continue;
- }
- final List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypeList =
- mSettings.getEnabledInputMethodSubtypeListLocked(imi, true);
- final ArraySet<String> enabledSubtypeSet = new ArraySet<>();
- for (InputMethodSubtype subtype : explicitlyOrImplicitlyEnabledSubtypeList) {
- enabledSubtypeSet.add(String.valueOf(subtype.hashCode()));
- }
- final CharSequence imeLabel = imi.loadLabel(mPm);
- if (enabledSubtypeSet.size() > 0) {
- final int subtypeCount = imi.getSubtypeCount();
- if (DEBUG) {
- Slog.v(TAG, "Add subtypes: " + subtypeCount + ", " + imi.getId());
- }
- for (int j = 0; j < subtypeCount; ++j) {
- final InputMethodSubtype subtype = imi.getSubtypeAt(j);
- final String subtypeHashCode = String.valueOf(subtype.hashCode());
- // We show all enabled IMEs and subtypes when an IME is shown.
- if (enabledSubtypeSet.contains(subtypeHashCode)
- && (includeAuxiliarySubtypes || !subtype.isAuxiliary())) {
- final CharSequence subtypeLabel =
- subtype.overridesImplicitlyEnabledSubtype() ? null : subtype
- .getDisplayName(mContext, imi.getPackageName(),
- imi.getServiceInfo().applicationInfo);
- imList.add(new ImeSubtypeListItem(imeLabel,
- subtypeLabel, imi, j, subtype.getLocale(), mSystemLocaleStr));
+ for (int j = 0; j < subtypeCount; ++j) {
+ final InputMethodSubtype subtype = imi.getSubtypeAt(j);
+ final String subtypeHashCode = String.valueOf(subtype.hashCode());
+ // We show all enabled IMEs and subtypes when an IME is shown.
+ if (enabledSubtypeSet.contains(subtypeHashCode)
+ && (includeAuxiliarySubtypes || !subtype.isAuxiliary())) {
+ final CharSequence subtypeLabel =
+ subtype.overridesImplicitlyEnabledSubtype() ? null : subtype
+ .getDisplayName(userAwareContext, imi.getPackageName(),
+ imi.getServiceInfo().applicationInfo);
+ imList.add(new ImeSubtypeListItem(imeLabel,
+ subtypeLabel, imi, j, subtype.getLocale(), mSystemLocaleStr));
- // Removing this subtype from enabledSubtypeSet because we no
- // longer need to add an entry of this subtype to imList to avoid
- // duplicated entries.
- enabledSubtypeSet.remove(subtypeHashCode);
- }
+ // Removing this subtype from enabledSubtypeSet because we no
+ // longer need to add an entry of this subtype to imList to avoid
+ // duplicated entries.
+ enabledSubtypeSet.remove(subtypeHashCode);
}
- } else {
- imList.add(new ImeSubtypeListItem(imeLabel, null, imi, NOT_A_SUBTYPE_ID, null,
- mSystemLocaleStr));
}
+ } else {
+ imList.add(new ImeSubtypeListItem(imeLabel, null, imi, NOT_A_SUBTYPE_ID, null,
+ mSystemLocaleStr));
}
- Collections.sort(imList);
- return imList;
}
+ Collections.sort(imList);
+ return imList;
}
private static int calculateSubtypeId(InputMethodInfo imi, InputMethodSubtype subtype) {
@@ -479,18 +474,32 @@
}
}
- private final InputMethodSettings mSettings;
- private InputMethodAndSubtypeList mSubtypeList;
+ private final Context mContext;
+ @UserIdInt
+ private final int mUserId;
private ControllerImpl mController;
- private InputMethodSubtypeSwitchingController(InputMethodSettings settings, Context context) {
- mSettings = settings;
- resetCircularListLocked(context);
+ private InputMethodSubtypeSwitchingController(@NonNull Context context,
+ @NonNull ArrayMap<String, InputMethodInfo> methodMap, @UserIdInt int userId) {
+ mContext = context;
+ mUserId = userId;
+ mController = ControllerImpl.createFrom(null,
+ getSortedInputMethodAndSubtypeList(
+ false /* includeAuxiliarySubtypes */, false /* isScreenLocked */,
+ false /* forImeMenu */, context, methodMap, userId));
}
+ @NonNull
public static InputMethodSubtypeSwitchingController createInstanceLocked(
- InputMethodSettings settings, Context context) {
- return new InputMethodSubtypeSwitchingController(settings, context);
+ @NonNull Context context,
+ @NonNull ArrayMap<String, InputMethodInfo> methodMap, @UserIdInt int userId) {
+ return new InputMethodSubtypeSwitchingController(context, methodMap, userId);
+ }
+
+ @AnyThread
+ @UserIdInt
+ int getUserId() {
+ return mUserId;
}
public void onUserActionLocked(InputMethodInfo imi, InputMethodSubtype subtype) {
@@ -503,12 +512,12 @@
mController.onUserActionLocked(imi, subtype);
}
- public void resetCircularListLocked(Context context) {
- mSubtypeList = new InputMethodAndSubtypeList(context, mSettings);
+ public void resetCircularListLocked(
+ @NonNull ArrayMap<String, InputMethodInfo> methodMap) {
mController = ControllerImpl.createFrom(mController,
- mSubtypeList.getSortedInputMethodAndSubtypeList(
+ getSortedInputMethodAndSubtypeList(
false /* includeAuxiliarySubtypes */, false /* isScreenLocked */,
- false /* forImeMenu */));
+ false /* forImeMenu */, mContext, methodMap, mUserId));
}
public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme, InputMethodInfo imi,
@@ -522,12 +531,6 @@
return mController.getNextInputMethod(onlyCurrentIme, imi, subtype);
}
- public List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeListForImeMenuLocked(
- boolean includingAuxiliarySubtypes, boolean isScreenLocked) {
- return mSubtypeList.getSortedInputMethodAndSubtypeList(
- includingAuxiliarySubtypes, isScreenLocked, true /* forImeMenu */);
- }
-
public void dump(final Printer pw) {
if (mController != null) {
mController.dump(pw);
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
index a0b55ed..f9b06de 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
@@ -51,6 +51,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
import java.util.StringJoiner;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -241,6 +242,12 @@
Slog.d(TAG, "--- Switch the current user from " + mCurrentUserId + " to " + userId);
}
mCurrentUserId = userId;
+ String ime = getSelectedInputMethod();
+ String defaultDeviceIme = getSelectedDefaultDeviceInputMethod();
+ if (defaultDeviceIme != null && !Objects.equals(ime, defaultDeviceIme)) {
+ putSelectedInputMethod(defaultDeviceIme);
+ putSelectedDefaultDeviceInputMethod(null);
+ }
}
private void putString(@NonNull String key, @Nullable String str) {
@@ -636,6 +643,24 @@
return imi;
}
+ @Nullable
+ String getSelectedDefaultDeviceInputMethod() {
+ final String imi = getString(Settings.Secure.DEFAULT_DEVICE_INPUT_METHOD, null);
+ if (DEBUG) {
+ Slog.d(TAG, "getSelectedDefaultDeviceInputMethodStr: " + imi + ", "
+ + mCurrentUserId);
+ }
+ return imi;
+ }
+
+ void putSelectedDefaultDeviceInputMethod(String imeId) {
+ if (DEBUG) {
+ Slog.d(TAG, "putSelectedDefaultDeviceInputMethodStr: " + imeId + ", "
+ + mCurrentUserId);
+ }
+ putString(Settings.Secure.DEFAULT_DEVICE_INPUT_METHOD, imeId);
+ }
+
void putDefaultVoiceInputMethod(String imeId) {
if (DEBUG) {
Slog.d(TAG, "putDefaultVoiceInputMethodStr: " + imeId + ", " + mCurrentUserId);
diff --git a/services/core/java/com/android/server/pm/InitAppsHelper.java b/services/core/java/com/android/server/pm/InitAppsHelper.java
index 41d0176..22951d5 100644
--- a/services/core/java/com/android/server/pm/InitAppsHelper.java
+++ b/services/core/java/com/android/server/pm/InitAppsHelper.java
@@ -180,7 +180,9 @@
// priority of system overlays.
final ArrayMap<String, File> apkInApexPreInstalledPaths = new ArrayMap<>();
for (ApexManager.ActiveApexInfo apexInfo : mApexManager.getActiveApexInfos()) {
- for (String packageName : mApexManager.getApksInApex(apexInfo.apexModuleName)) {
+ final String apexPackageName = mApexManager.getActivePackageNameForApexModuleName(
+ apexInfo.apexModuleName);
+ for (String packageName : mApexManager.getApksInApex(apexPackageName)) {
apkInApexPreInstalledPaths.put(packageName, apexInfo.preInstalledApexPath);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageArchiver.java b/services/core/java/com/android/server/pm/PackageArchiver.java
index dcfc855d..376b061 100644
--- a/services/core/java/com/android/server/pm/PackageArchiver.java
+++ b/services/core/java/com/android/server/pm/PackageArchiver.java
@@ -25,6 +25,7 @@
import static android.content.pm.ArchivedActivityInfo.bytesFromBitmap;
import static android.content.pm.ArchivedActivityInfo.drawableToBitmap;
import static android.content.pm.PackageInstaller.EXTRA_UNARCHIVE_STATUS;
+import static android.content.pm.PackageInstaller.STATUS_PENDING_USER_ACTION;
import static android.content.pm.PackageInstaller.UNARCHIVAL_OK;
import static android.content.pm.PackageManager.DELETE_ARCHIVE;
import static android.content.pm.PackageManager.DELETE_KEEP_DATA;
@@ -72,10 +73,12 @@
import android.os.IBinder;
import android.os.ParcelableException;
import android.os.Process;
+import android.os.RemoteException;
import android.os.SELinux;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.ExceptionUtils;
+import android.util.Pair;
import android.util.Slog;
import com.android.internal.R;
@@ -93,7 +96,9 @@
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
@@ -140,15 +145,23 @@
private final Context mContext;
private final PackageManagerService mPm;
+ private final AppStateHelper mAppStateHelper;
+
@Nullable
private LauncherApps mLauncherApps;
@Nullable
private AppOpsManager mAppOpsManager;
+ /* IntentSender store that maps key: {userId, appPackageName} to respective existing attached
+ unarchival intent sender. */
+ private final Map<Pair<Integer, String>, IntentSender> mLauncherIntentSenders;
+
PackageArchiver(Context context, PackageManagerService mPm) {
this.mContext = context;
this.mPm = mPm;
+ this.mAppStateHelper = new AppStateHelper(mContext);
+ this.mLauncherIntentSenders = new HashMap<>();
}
/** Returns whether a package is archived for a user. */
@@ -235,37 +248,32 @@
// Return early as the calling UID does not match caller package's UID.
return START_CLASS_NOT_FOUND;
}
+
String currentLauncherPackageName = getCurrentLauncherPackageName(userId);
if ((currentLauncherPackageName == null || !callerPackageName.equals(
currentLauncherPackageName)) && callingUid != Process.SHELL_UID) {
// TODO(b/311619990): Remove dependency on SHELL_UID for testing
Slog.e(TAG, TextUtils.formatSimple(
- "callerPackageName: %s does not qualify for archival of package: " + "%s!",
+ "callerPackageName: %s does not qualify for unarchival of package: " + "%s!",
callerPackageName, packageName));
return START_PERMISSION_DENIED;
}
- // TODO(b/302114464): Handle edge cases & also divert to a dialog based on
- // permissions + compat options
- Slog.i(TAG, TextUtils.formatSimple("Unarchival is starting for: %s", packageName));
- try {
- final IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
- @Override
- public void send(int code, Intent intent, String resolvedType,
- IBinder allowlistToken,
- IIntentReceiver finishedReceiver, String requiredPermission,
- Bundle options) {
- // TODO(b/302114464): Handle intent sender status codes
- }
- };
+ Slog.i(TAG, TextUtils.formatSimple("Unarchival is starting for: %s", packageName));
+
+ try {
+ // TODO(b/311709794) Make showUnarchivalConfirmation dependent on the compat options.
requestUnarchive(packageName, callerPackageName,
- new IntentSender((IIntentSender) mLocalSender), UserHandle.of(userId));
+ getOrCreateUnarchiveIntentSender(userId, packageName),
+ UserHandle.of(userId),
+ false /* showUnarchivalConfirmation= */);
} catch (Throwable t) {
Slog.e(TAG, TextUtils.formatSimple(
"Unexpected error occurred while unarchiving package %s: %s.", packageName,
t.getLocalizedMessage()));
return START_ABORTED;
}
+
return START_SUCCESS;
}
@@ -321,6 +329,20 @@
return true;
}
+ private IntentSender getOrCreateUnarchiveIntentSender(int userId, String packageName) {
+ Pair<Integer, String> key = Pair.create(userId, packageName);
+ synchronized (mLauncherIntentSenders) {
+ IntentSender intentSender = mLauncherIntentSenders.get(key);
+ if (intentSender != null) {
+ return intentSender;
+ }
+ IntentSender unarchiveIntentSender = new IntentSender(
+ (IIntentSender) new UnarchiveIntentSender());
+ mLauncherIntentSenders.put(key, unarchiveIntentSender);
+ return unarchiveIntentSender;
+ }
+ }
+
/** Creates archived state for the package and user. */
private CompletableFuture<ArchiveState> createArchiveState(String packageName, int userId)
throws PackageManager.NameNotFoundException {
@@ -553,6 +575,15 @@
@NonNull String callerPackageName,
@NonNull IntentSender statusReceiver,
@NonNull UserHandle userHandle) {
+ requestUnarchive(packageName, callerPackageName, statusReceiver, userHandle,
+ false /* showUnarchivalConfirmation= */);
+ }
+
+ private void requestUnarchive(
+ @NonNull String packageName,
+ @NonNull String callerPackageName,
+ @NonNull IntentSender statusReceiver,
+ @NonNull UserHandle userHandle, boolean showUnarchivalConfirmation) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(callerPackageName);
Objects.requireNonNull(statusReceiver);
@@ -597,8 +628,8 @@
+ "an unarchival.");
}
- if (!hasInstallPackages) {
- requestUnarchiveConfirmation(packageName, statusReceiver);
+ if (!hasInstallPackages || showUnarchivalConfirmation) {
+ requestUnarchiveConfirmation(packageName, statusReceiver, userHandle);
return;
}
@@ -622,7 +653,8 @@
() -> unarchiveInternal(packageName, userHandle, installerPackage, draftSessionId));
}
- private void requestUnarchiveConfirmation(String packageName, IntentSender statusReceiver) {
+ private void requestUnarchiveConfirmation(String packageName, IntentSender statusReceiver,
+ UserHandle user) {
final Intent dialogIntent = new Intent(ACTION_UNARCHIVE_DIALOG);
dialogIntent.putExtra(EXTRA_UNARCHIVE_INTENT_SENDER, statusReceiver);
dialogIntent.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, packageName);
@@ -632,6 +664,7 @@
broadcastIntent.putExtra(EXTRA_UNARCHIVE_STATUS,
PackageInstaller.STATUS_PENDING_USER_ACTION);
broadcastIntent.putExtra(Intent.EXTRA_INTENT, dialogIntent);
+ broadcastIntent.putExtra(Intent.EXTRA_USER, user);
sendIntent(statusReceiver, packageName, /* message= */ "", broadcastIntent);
}
@@ -656,6 +689,7 @@
int installerUid = mPm.snapshotComputer().getPackageUid(installerPackage, 0, userId);
// Handles case of repeated unarchival calls for the same package.
+ // TODO(b/316881759) Allow attaching multiple intentSenders to one session.
int existingSessionId = mPm.mInstallerService.getExistingDraftSessionId(installerUid,
sessionParams,
userId);
@@ -849,7 +883,13 @@
void notifyUnarchivalListener(int status, String installerPackageName, String appPackageName,
long requiredStorageBytes, @Nullable PendingIntent userActionIntent,
- IntentSender unarchiveIntentSender, int userId) {
+ @Nullable IntentSender unarchiveIntentSender, int userId) {
+ if (unarchiveIntentSender == null) {
+ // Maybe this can happen if the installer calls reportUnarchivalStatus twice in quick
+ // succession.
+ return;
+ }
+
final Intent broadcastIntent = new Intent();
broadcastIntent.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, appPackageName);
broadcastIntent.putExtra(EXTRA_UNARCHIVE_STATUS, status);
@@ -863,6 +903,7 @@
return;
}
broadcastIntent.putExtra(Intent.EXTRA_INTENT, dialogIntent);
+ broadcastIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(userId));
}
final BroadcastOptions options = BroadcastOptions.makeBasic();
@@ -874,6 +915,10 @@
options.toBundle());
} catch (IntentSender.SendIntentException e) {
Slog.e(TAG, TextUtils.formatSimple("Failed to send unarchive intent"), e);
+ } finally {
+ synchronized (mLauncherIntentSenders) {
+ mLauncherIntentSenders.remove(Pair.create(userId, appPackageName));
+ }
}
}
@@ -883,6 +928,7 @@
long requiredStorageBytes, PendingIntent userActionIntent, int userId) {
final Intent dialogIntent = new Intent(ACTION_UNARCHIVE_ERROR_DIALOG);
dialogIntent.putExtra(EXTRA_UNARCHIVE_STATUS, status);
+ dialogIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(userId));
if (requiredStorageBytes > 0) {
dialogIntent.putExtra(EXTRA_REQUIRED_BYTES, requiredStorageBytes);
}
@@ -1118,4 +1164,25 @@
return activities.toArray(new ArchivedActivityParcel[activities.size()]);
}
+
+ private class UnarchiveIntentSender extends IIntentSender.Stub {
+ @Override
+ public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
+ IIntentReceiver finishedReceiver, String requiredPermission, Bundle options)
+ throws RemoteException {
+ int status = intent.getExtras().getInt(PackageInstaller.EXTRA_UNARCHIVE_STATUS,
+ STATUS_PENDING_USER_ACTION);
+ if (status == UNARCHIVAL_OK) {
+ return;
+ }
+ Intent extraIntent = intent.getParcelableExtra(Intent.EXTRA_INTENT, Intent.class);
+ UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER, UserHandle.class);
+ if (extraIntent != null && user != null
+ && mAppStateHelper.isAppTopVisible(
+ getCurrentLauncherPackageName(user.getIdentifier()))) {
+ extraIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivityAsUser(extraIntent, user);
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/pm/RemovePackageHelper.java b/services/core/java/com/android/server/pm/RemovePackageHelper.java
index 02e28dd..7bd6a43 100644
--- a/services/core/java/com/android/server/pm/RemovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/RemovePackageHelper.java
@@ -487,6 +487,8 @@
synchronized (mPm.mInstallLock) {
cleanUpResourcesLI(codeFile, instructionSets);
}
+ // TODO: open logging to help debug, will delete or add debug flag
+ Slog.d(TAG, "cleanUpResources for " + codeFile);
if (packageName == null) {
return;
}
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 3ecc985..fdff89a 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -958,7 +958,8 @@
final boolean vibrate = Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.CHARGING_VIBRATION_ENABLED, 1, userId) != 0;
if (vibrate) {
- mVibrator.vibrate(CHARGING_VIBRATION_EFFECT,
+ mVibrator.vibrate(Process.SYSTEM_UID, mContext.getOpPackageName(),
+ CHARGING_VIBRATION_EFFECT, /* reason= */ "Charging started",
HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES);
}
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 1577cef..2d584c4 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -98,6 +98,8 @@
import android.view.animation.Interpolator;
import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.TraceBuffer;
import com.android.internal.util.function.pooled.PooledLambda;
@@ -297,6 +299,18 @@
}
}
+ /** It is only used by unit test. */
+ @VisibleForTesting
+ Surface forceShowMagnifierSurface(int displayId) {
+ final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
+ if (displayMagnifier != null) {
+ displayMagnifier.mMagnifedViewport.mWindow.setAlpha(DisplayMagnifier.MagnifiedViewport
+ .ViewportWindow.AnimationController.MAX_ALPHA);
+ return displayMagnifier.mMagnifedViewport.mWindow.mSurface;
+ }
+ return null;
+ }
+
void onWindowLayersChanged(int displayId) {
if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK
| FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK)) {
@@ -448,6 +462,7 @@
}
}
+ // TODO(b/318327737): Remove parameter 't' when removing flag DRAW_IN_WM_LOCK.
void drawMagnifiedRegionBorderIfNeeded(int displayId, SurfaceControl.Transaction t) {
if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) {
mAccessibilityTracing.logTrace(
@@ -1106,11 +1121,19 @@
}
void setMagnifiedRegionBorderShown(boolean shown, boolean animate) {
- if (shown) {
+ if (ViewportWindow.DRAW_IN_WM_LOCK) {
+ if (shown) {
+ mFullRedrawNeeded = true;
+ mOldMagnificationRegion.set(0, 0, 0, 0);
+ }
+ mWindow.setShown(shown, animate);
+ return;
+ }
+ if (mWindow.setShown(shown, animate)) {
mFullRedrawNeeded = true;
+ // Clear the old region, so recomputeBounds will refresh the current region.
mOldMagnificationRegion.set(0, 0, 0, 0);
}
- mWindow.setShown(shown, animate);
}
void getMagnifiedFrameInContentCoords(Rect rect) {
@@ -1130,7 +1153,11 @@
void drawWindowIfNeeded(SurfaceControl.Transaction t) {
recomputeBounds();
- mWindow.drawIfNeeded(t);
+ if (ViewportWindow.DRAW_IN_WM_LOCK) {
+ mWindow.drawOrRemoveIfNeeded(t);
+ return;
+ }
+ mWindow.postDrawIfNeeded();
}
void destroyWindow() {
@@ -1158,23 +1185,28 @@
mWindow.dump(pw, prefix);
}
- private final class ViewportWindow {
+ private final class ViewportWindow implements Runnable {
private static final String SURFACE_TITLE = "Magnification Overlay";
+ // TODO(b/318327737): Remove if it is stable.
+ static final boolean DRAW_IN_WM_LOCK = !Flags.drawMagnifierBorderOutsideWmlock();
private final Region mBounds = new Region();
private final Rect mDirtyRect = new Rect();
private final Paint mPaint = new Paint();
private final SurfaceControl mSurfaceControl;
+ /** After initialization, it should only be accessed from animation thread. */
+ private final SurfaceControl.Transaction mTransaction;
private final BLASTBufferQueue mBlastBufferQueue;
private final Surface mSurface;
private final AnimationController mAnimationController;
private boolean mShown;
+ private boolean mLastSurfaceShown;
private int mAlpha;
- private boolean mInvalidated;
+ private volatile boolean mInvalidated;
ViewportWindow(Context context) {
SurfaceControl surfaceControl = null;
@@ -1202,6 +1234,7 @@
InputMonitor.setTrustedOverlayInputInfo(mSurfaceControl, t,
mDisplayContent.getDisplayId(), "Magnification Overlay");
t.apply();
+ mTransaction = t;
mSurface = mBlastBufferQueue.createSurface();
mAnimationController = new AnimationController(context,
@@ -1219,10 +1252,11 @@
mInvalidated = true;
}
- void setShown(boolean shown, boolean animate) {
+ /** Returns {@code true} if the state is changed to shown. */
+ boolean setShown(boolean shown, boolean animate) {
synchronized (mService.mGlobalLock) {
if (mShown == shown) {
- return;
+ return false;
}
mShown = shown;
mAnimationController.onFrameShownStateChanged(shown, animate);
@@ -1230,6 +1264,7 @@
Slog.i(LOG_TAG, "ViewportWindow shown: " + mShown);
}
}
+ return shown;
}
@SuppressWarnings("unused")
@@ -1285,7 +1320,22 @@
mService.scheduleAnimationLocked();
}
- void drawIfNeeded(SurfaceControl.Transaction t) {
+ void postDrawIfNeeded() {
+ if (mInvalidated) {
+ mService.mAnimationHandler.post(this);
+ }
+ }
+
+ @Override
+ public void run() {
+ drawOrRemoveIfNeeded(mTransaction);
+ }
+
+ /**
+ * This method must only be called by animation handler directly to make sure
+ * thread safe and there is no lock held outside.
+ */
+ private void drawOrRemoveIfNeeded(SurfaceControl.Transaction t) {
// Drawing variables (alpha, dirty rect, and bounds) access is synchronized
// using WindowManagerGlobalLock. Grab copies of these values before
// drawing on the canvas so that drawing can be performed outside of the lock.
@@ -1293,6 +1343,14 @@
Rect drawingRect = null;
Region drawingBounds = null;
synchronized (mService.mGlobalLock) {
+ if (!DRAW_IN_WM_LOCK && mBlastBufferQueue.mNativeObject == 0) {
+ // Complete removal since releaseSurface has been called.
+ if (mSurface.isValid()) {
+ mTransaction.remove(mSurfaceControl).apply();
+ mSurface.release();
+ }
+ return;
+ }
if (!mInvalidated) {
return;
}
@@ -1314,6 +1372,7 @@
}
}
+ final boolean showSurface;
// Draw without holding WindowManagerGlobalLock.
if (alpha > 0) {
Canvas canvas = null;
@@ -1329,18 +1388,38 @@
mPaint.setAlpha(alpha);
canvas.drawPath(drawingBounds.getBoundaryPath(), mPaint);
mSurface.unlockCanvasAndPost(canvas);
- t.show(mSurfaceControl);
+ if (DRAW_IN_WM_LOCK) {
+ t.show(mSurfaceControl);
+ return;
+ }
+ showSurface = true;
} else {
- t.hide(mSurfaceControl);
+ if (DRAW_IN_WM_LOCK) {
+ t.hide(mSurfaceControl);
+ return;
+ }
+ showSurface = false;
+ }
+
+ if (showSurface && !mLastSurfaceShown) {
+ mTransaction.show(mSurfaceControl).apply();
+ mLastSurfaceShown = true;
+ } else if (!showSurface && mLastSurfaceShown) {
+ mTransaction.hide(mSurfaceControl).apply();
+ mLastSurfaceShown = false;
}
}
+ @GuardedBy("mService.mGlobalLock")
void releaseSurface() {
- if (mBlastBufferQueue != null) {
- mBlastBufferQueue.destroy();
+ mBlastBufferQueue.destroy();
+ if (DRAW_IN_WM_LOCK) {
+ mService.mTransactionFactory.get().remove(mSurfaceControl).apply();
+ mSurface.release();
+ return;
}
- mService.mTransactionFactory.get().remove(mSurfaceControl).apply();
- mSurface.release();
+ // Post to perform cleanup on the thread which handles mSurface.
+ mService.mAnimationHandler.post(this);
}
void dump(PrintWriter pw, String prefix) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
index e0232b1..14dc0eb 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
@@ -32,6 +32,7 @@
import android.annotation.Nullable;
import android.app.AppGlobals;
import android.app.BroadcastOptions;
+import android.app.admin.BooleanPolicyValue;
import android.app.admin.DevicePolicyIdentifiers;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyState;
@@ -142,6 +143,67 @@
mAdminPolicySize = new SparseArray<>();
}
+ private void maybeForceEnforcementRefreshLocked(@NonNull PolicyDefinition<?> policyDefinition) {
+ try {
+ if (shouldForceEnforcementRefresh(policyDefinition)) {
+ // This is okay because it's only true for user restrictions which are all <Boolean>
+ forceEnforcementRefreshLocked((PolicyDefinition<Boolean>) policyDefinition);
+ }
+ } catch (Throwable e) {
+ // Catch any possible exceptions just to be on the safe side
+ Log.e(TAG, "Exception throw during maybeForceEnforcementRefreshLocked", e);
+ }
+ }
+
+ private boolean shouldForceEnforcementRefresh(@NonNull PolicyDefinition<?> policyDefinition) {
+ // These are all "not nullable" but for the purposes of maximum safety for a lightly tested
+ // change we check here
+ if (policyDefinition == null) {
+ return false;
+ }
+ PolicyKey policyKey = policyDefinition.getPolicyKey();
+ if (policyKey == null) {
+ return false;
+ }
+
+ if (policyKey instanceof UserRestrictionPolicyKey) {
+ // b/307481299 We must force all user restrictions to re-sync local
+ // + global on each set/clear
+ return true;
+ }
+
+ return false;
+ }
+
+ private void forceEnforcementRefreshLocked(PolicyDefinition<Boolean> policyDefinition) {
+ Binder.withCleanCallingIdentity(() -> {
+ // Sync global state
+ PolicyValue<Boolean> globalValue = new BooleanPolicyValue(false);
+ try {
+ PolicyState<Boolean> policyState = getGlobalPolicyStateLocked(policyDefinition);
+ globalValue = policyState.getCurrentResolvedPolicy();
+ } catch (IllegalArgumentException e) {
+ // Expected for local-only policies
+ }
+
+ enforcePolicy(policyDefinition, globalValue, UserHandle.USER_ALL);
+
+ // Loop through each user and sync that user's state
+ for (UserInfo user : mUserManager.getUsers()) {
+ PolicyValue<Boolean> localValue = new BooleanPolicyValue(false);
+ try {
+ PolicyState<Boolean> localPolicyState = getLocalPolicyStateLocked(
+ policyDefinition, user.id);
+ localValue = localPolicyState.getCurrentResolvedPolicy();
+ } catch (IllegalArgumentException e) {
+ // Expected for global-only policies
+ }
+
+ enforcePolicy(policyDefinition, localValue, user.id);
+ }
+ });
+ }
+
/**
* Set the policy for the provided {@code policyDefinition} (see {@link PolicyDefinition}) and
* {@code enforcingAdmin} to the provided {@code value}.
@@ -188,6 +250,7 @@
// No need to notify admins as no new policy is actually enforced, we're just filling in
// the data structures.
if (!skipEnforcePolicy) {
+ maybeForceEnforcementRefreshLocked(policyDefinition);
if (policyChanged) {
onLocalPolicyChangedLocked(policyDefinition, enforcingAdmin, userId);
}
@@ -278,6 +341,7 @@
Objects.requireNonNull(enforcingAdmin);
synchronized (mLock) {
+ maybeForceEnforcementRefreshLocked(policyDefinition);
if (!hasLocalPolicyLocked(policyDefinition, userId)) {
return;
}
@@ -451,6 +515,7 @@
// No need to notify admins as no new policy is actually enforced, we're just filling in
// the data structures.
if (!skipEnforcePolicy) {
+ maybeForceEnforcementRefreshLocked(policyDefinition);
if (policyChanged) {
onGlobalPolicyChangedLocked(policyDefinition, enforcingAdmin);
}
@@ -506,6 +571,7 @@
boolean policyChanged = policyState.removePolicy(enforcingAdmin);
+ maybeForceEnforcementRefreshLocked(policyDefinition);
if (policyChanged) {
onGlobalPolicyChangedLocked(policyDefinition, enforcingAdmin);
}
diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp
index 113511e..321d945 100644
--- a/services/tests/mockingservicestests/Android.bp
+++ b/services/tests/mockingservicestests/Android.bp
@@ -73,6 +73,7 @@
// TODO: remove once Android migrates to JUnit 4.12, which provides assertThrows
"testng",
"compatibility-device-util-axt",
+ "flag-junit",
],
libs: [
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java
index 57326b2..d08cdc7 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java
@@ -343,10 +343,12 @@
List<ApexManager.ScanResult> scanResults = scanApexInfos(apexInfo);
mApexManager.notifyScanResult(scanResults);
- assertThat(mApexManager.getApkInApexInstallError(activeApex.apexModuleName)).isNull();
+ final String apexPackageName = mApexManager.getActivePackageNameForApexModuleName(
+ activeApex.apexModuleName);
+ assertThat(mApexManager.getApkInApexInstallError(apexPackageName)).isNull();
mApexManager.reportErrorWithApkInApex(activeApex.apexDirectory.getAbsolutePath(),
"Some random error");
- assertThat(mApexManager.getApkInApexInstallError(activeApex.apexModuleName))
+ assertThat(mApexManager.getApkInApexInstallError(apexPackageName))
.isEqualTo("Some random error");
}
@@ -370,9 +372,11 @@
List<ApexManager.ScanResult> scanResults = scanApexInfos(apexInfo);
mApexManager.notifyScanResult(scanResults);
- assertThat(mApexManager.getApksInApex(activeApex.apexModuleName)).isEmpty();
+ final String apexPackageName = mApexManager.getActivePackageNameForApexModuleName(
+ activeApex.apexModuleName);
+ assertThat(mApexManager.getApksInApex(apexPackageName)).isEmpty();
mApexManager.registerApkInApex(fakeApkInApex);
- assertThat(mApexManager.getApksInApex(activeApex.apexModuleName)).isEmpty();
+ assertThat(mApexManager.getApksInApex(apexPackageName)).isEmpty();
}
@Test
diff --git a/services/tests/powerservicetests/src/com/android/server/power/NotifierTest.java b/services/tests/powerservicetests/src/com/android/server/power/NotifierTest.java
index 91d8ceb..a9ff3a1 100644
--- a/services/tests/powerservicetests/src/com/android/server/power/NotifierTest.java
+++ b/services/tests/powerservicetests/src/com/android/server/power/NotifierTest.java
@@ -26,6 +26,7 @@
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -113,7 +114,8 @@
mTestExecutor.simulateAsyncExecutionOfLastCommand();
// THEN the device vibrates once
- verify(mVibrator, times(1)).vibrate(any(), any(VibrationAttributes.class));
+ verify(mVibrator, times(1)).vibrate(anyInt(), any(), any(), any(),
+ any(VibrationAttributes.class));
}
@Test
@@ -129,7 +131,7 @@
mTestExecutor.simulateAsyncExecutionOfLastCommand();
// THEN the device doesn't vibrate
- verify(mVibrator, never()).vibrate(any(), any(VibrationAttributes.class));
+ verifyZeroInteractions(mVibrator);
}
@Test
@@ -145,14 +147,15 @@
mTestExecutor.simulateAsyncExecutionOfLastCommand();
// THEN the device vibrates once
- verify(mVibrator, times(1)).vibrate(any(), any(VibrationAttributes.class));
+ verify(mVibrator, times(1)).vibrate(anyInt(), any(), any(), any(),
+ any(VibrationAttributes.class));
}
@Test
public void testVibrateDisabled_wirelessCharging() {
createNotifier();
- // GIVEN the charging vibration is disabeld
+ // GIVEN the charging vibration is disabled
enableChargingVibration(false);
// WHEN wireless charging starts
@@ -161,7 +164,7 @@
mTestExecutor.simulateAsyncExecutionOfLastCommand();
// THEN the device doesn't vibrate
- verify(mVibrator, never()).vibrate(any(), any(VibrationAttributes.class));
+ verifyZeroInteractions(mVibrator);
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
index 8bf4833..21fee72 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
@@ -37,6 +37,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
@@ -85,6 +86,7 @@
import android.view.InputChannel;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
+import android.view.Surface;
import android.view.SurfaceControl;
import android.view.View;
import android.view.WindowInsets;
@@ -952,6 +954,57 @@
}
@Test
+ public void testDrawMagnifiedViewport() {
+ final int displayId = mDisplayContent.mDisplayId;
+ // Use real surface, so ViewportWindow's BlastBufferQueue can be created.
+ final ArrayList<SurfaceControl> surfaceControls = new ArrayList<>();
+ mWm.mSurfaceControlFactory = s -> new SurfaceControl.Builder() {
+ @Override
+ public SurfaceControl build() {
+ final SurfaceControl sc = super.build();
+ surfaceControls.add(sc);
+ return sc;
+ }
+ };
+ mWm.mAccessibilityController.setMagnificationCallbacks(displayId,
+ mock(WindowManagerInternal.MagnificationCallbacks.class));
+ final boolean[] lockCanvasInWmLock = { false };
+ final Surface surface = mWm.mAccessibilityController.forceShowMagnifierSurface(displayId);
+ spyOn(surface);
+ doAnswer(invocationOnMock -> {
+ lockCanvasInWmLock[0] |= Thread.holdsLock(mWm.mGlobalLock);
+ invocationOnMock.callRealMethod();
+ return null;
+ }).when(surface).lockCanvas(any());
+ mWm.mAccessibilityController.drawMagnifiedRegionBorderIfNeeded(displayId, mTransaction);
+ waitUntilHandlersIdle();
+ try {
+ verify(surface).lockCanvas(any());
+
+ clearInvocations(surface);
+ // Invalidate and redraw.
+ mWm.mAccessibilityController.onDisplaySizeChanged(mDisplayContent);
+ mWm.mAccessibilityController.drawMagnifiedRegionBorderIfNeeded(displayId, mTransaction);
+ // Turn off magnification to release surface.
+ mWm.mAccessibilityController.setMagnificationCallbacks(displayId, null);
+ if (!com.android.window.flags.Flags.drawMagnifierBorderOutsideWmlock()) {
+ verify(surface).release();
+ assertTrue(lockCanvasInWmLock[0]);
+ return;
+ }
+ waitUntilHandlersIdle();
+ // lockCanvas must not be called after releasing.
+ verify(surface, never()).lockCanvas(any());
+ verify(surface).release();
+ assertFalse(lockCanvasInWmLock[0]);
+ } finally {
+ for (int i = surfaceControls.size() - 1; i >= 0; --i) {
+ surfaceControls.get(i).release();
+ }
+ }
+ }
+
+ @Test
public void testRequestKeyboardShortcuts_noWindow() {
doNothing().when(mWm.mContext).enforceCallingOrSelfPermission(anyString(), anyString());
doReturn(null).when(mWm).getFocusedWindowLocked();
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 9e292be..1b47dfe 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -510,7 +510,7 @@
/** @hide */
@UnsupportedAppUsage
public TelephonyManager(Context context) {
- this(context, SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
+ this(context, SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
}
/** @hide */
@@ -2140,10 +2140,14 @@
* the IMEI/SV for GSM phones. Return null if the software version is
* not available.
* <p>
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY}.
*/
@RequiresPermission(anyOf = {
android.Manifest.permission.READ_PHONE_STATE,
android.Manifest.permission.READ_BASIC_PHONE_STATE})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY)
@Nullable
public String getDeviceSoftwareVersion() {
return getDeviceSoftwareVersion(getSlotIndex());
@@ -2158,10 +2162,13 @@
*
* @param slotIndex of which deviceID is returned
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY}.
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY)
@Nullable
public String getDeviceSoftwareVersion(int slotIndex) {
ITelephony telephony = getITelephony();
@@ -2288,6 +2295,9 @@
*
* See {@link #getImei(int)} for details on the required permissions and behavior
* when the caller does not hold sufficient permissions.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_GSM}.
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -2330,6 +2340,9 @@
* </ul>
*
* @param slotIndex of which IMEI is returned
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_GSM}.
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -2350,6 +2363,9 @@
/**
* Returns the Type Allocation Code from the IMEI. Return null if Type Allocation Code is not
* available.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_GSM}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_GSM)
@Nullable
@@ -2362,6 +2378,9 @@
* available.
*
* @param slotIndex of which Type Allocation Code is returned
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_GSM}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_GSM)
@Nullable
@@ -2407,6 +2426,9 @@
* the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
* higher, then a SecurityException is thrown.</li>
* </ul>
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CDMA}.
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -2446,6 +2468,9 @@
* </ul>
*
* @param slotIndex of which MEID is returned
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CDMA}.
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -2472,6 +2497,9 @@
/**
* Returns the Manufacturer Code from the MEID. Return null if Manufacturer Code is not
* available.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CDMA}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_CDMA)
@Nullable
@@ -2484,6 +2512,9 @@
* available.
*
* @param slotIndex of which Type Allocation Code is returned
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CDMA}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_CDMA)
@Nullable
@@ -2528,6 +2559,9 @@
* the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
* higher, then a SecurityException is thrown.</li>
* </ul>
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -2563,10 +2597,14 @@
*<p>
* @return Current location of the device or null if not available.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
+ *
* @deprecated use {@link #getAllCellInfo} instead, which returns a superset of this API.
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public CellLocation getCellLocation() {
try {
ITelephony telephony = getITelephony();
@@ -2596,12 +2634,15 @@
*
* @return List of NeighboringCellInfo or null if info unavailable.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @removed
* @deprecated Use {@link #getAllCellInfo} which returns a superset of the information
* from NeighboringCellInfo, including LTE cell information.
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public List<NeighboringCellInfo> getNeighboringCellInfo() {
try {
ITelephony telephony = getITelephony();
@@ -2648,9 +2689,12 @@
* @see #PHONE_TYPE_CDMA
* @see #PHONE_TYPE_SIP
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY}.
* {@hide}
*/
@SystemApi
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY)
public int getCurrentPhoneType() {
return getCurrentPhoneType(getSubId());
}
@@ -2663,9 +2707,13 @@
* @see #PHONE_TYPE_CDMA
*
* @param subId for which phone type is returned
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY}.
* @hide
*/
@SystemApi
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY)
public int getCurrentPhoneType(int subId) {
int phoneId;
if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
@@ -2712,7 +2760,11 @@
* @see #PHONE_TYPE_GSM
* @see #PHONE_TYPE_CDMA
* @see #PHONE_TYPE_SIP
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY}.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY)
public int getPhoneType() {
if (!isVoiceCapable()) {
return PHONE_TYPE_NONE;
@@ -2912,6 +2964,9 @@
* @see CarrierConfigManager#getConfigForSubId(int)
* @see #createForSubscriptionId(int)
* @see #createForPhoneAccountHandle(PhoneAccountHandle)
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@WorkerThread
@@ -2958,6 +3013,9 @@
* <p>
* @return the lowercase 2 character ISO-3166-1 alpha-2 country code, or empty string if not
* available.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public String getNetworkCountryIso() {
@@ -2980,6 +3038,8 @@
* available.
*
* @throws IllegalArgumentException when the slotIndex is invalid.
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
@@ -3108,9 +3168,13 @@
*
* @deprecated use {@link #getDataNetworkType()}
* @return the NETWORK_TYPE_xxxx for current data connection.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public @NetworkType int getNetworkType() {
return getNetworkType(getSubId(SubscriptionManager.getActiveDataSubscriptionId()));
}
@@ -3199,12 +3263,15 @@
* @see #NETWORK_TYPE_EHRPD
* @see #NETWORK_TYPE_HSPAP
* @see #NETWORK_TYPE_NR
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(anyOf = {
android.Manifest.permission.READ_PHONE_STATE,
android.Manifest.permission.READ_BASIC_PHONE_STATE})
- @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public @NetworkType int getDataNetworkType() {
return getDataNetworkType(getSubId(SubscriptionManager.getActiveDataSubscriptionId()));
}
@@ -3245,6 +3312,9 @@
* or {@link android.Manifest.permission#READ_BASIC_PHONE_STATE
* READ_BASIC_PHONE_STATE} or that the calling app has carrier privileges
* (see {@link #hasCarrierPrivileges}).
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(anyOf = {
@@ -3597,6 +3667,9 @@
* of whether an active SIM profile is present or not so this API would always return true.
*
* @return true if a ICC card is present.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public boolean hasIccCard() {
@@ -3640,6 +3713,9 @@
* @see #SIM_STATE_PERM_DISABLED
* @see #SIM_STATE_CARD_IO_ERROR
* @see #SIM_STATE_CARD_RESTRICTED
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public @SimState int getSimState() {
@@ -3681,6 +3757,8 @@
* @see #SIM_STATE_CARD_RESTRICTED
* @see #SIM_STATE_PRESENT
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@SystemApi
@@ -3701,11 +3779,14 @@
* @see #SIM_STATE_CARD_RESTRICTED
* @see #SIM_STATE_PRESENT
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
* @deprecated instead use {@link #getSimCardState(int, int)}
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@Deprecated
public @SimState int getSimCardState(int physicalSlotIndex) {
int activePort = getFirstActivePortIndex(physicalSlotIndex);
@@ -3727,6 +3808,8 @@
* @see #SIM_STATE_CARD_RESTRICTED
* @see #SIM_STATE_PRESENT
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@SystemApi
@@ -3785,6 +3868,8 @@
* @see #SIM_STATE_PERM_DISABLED
* @see #SIM_STATE_LOADED
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@SystemApi
@@ -3808,11 +3893,14 @@
* @see #SIM_STATE_PERM_DISABLED
* @see #SIM_STATE_LOADED
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
* @deprecated instead use {@link #getSimApplicationState(int, int)}
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@Deprecated
public @SimState int getSimApplicationState(int physicalSlotIndex) {
int activePort = getFirstActivePortIndex(physicalSlotIndex);
@@ -3836,6 +3924,8 @@
* @see #SIM_STATE_PERM_DISABLED
* @see #SIM_STATE_LOADED
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@SystemApi
@@ -3876,6 +3966,9 @@
*
* @param appType the uicc app type like {@link APPTYPE_CSIM}
* @return true if the specified type of application in UICC CARD or false if no uicc or error.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@SystemApi
@@ -3908,6 +4001,9 @@
* @see #SIM_STATE_PERM_DISABLED
* @see #SIM_STATE_CARD_IO_ERROR
* @see #SIM_STATE_CARD_RESTRICTED
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public @SimState int getSimState(int slotIndex) {
@@ -4105,6 +4201,9 @@
* the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
* higher, then a SecurityException is thrown.</li>
* </ul>
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -4172,6 +4271,9 @@
*
* @return {@code true} if 3GPP and 3GPP2 radio technologies can be supported at the same time
* {@code false} if not supported or unknown
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
*/
@SystemApi
@@ -4219,6 +4321,9 @@
* through a factory reset.
*
* @return card ID of the default eUICC card, if loaded.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_EUICC}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_EUICC)
public int getCardIdForDefaultEuicc() {
@@ -4252,6 +4357,9 @@
* @return a list of UiccCardInfo objects, representing information on the currently inserted
* UICCs and eUICCs. Each UiccCardInfo in the list will have private information filtered out if
* the caller does not have adequate permissions for that card.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@@ -4276,6 +4384,8 @@
*
* @return UiccSlotInfo array.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@SystemApi
@@ -4319,6 +4429,9 @@
* @param physicalSlots The content of the array represents the physical slot index. The array
* size should be same as {@link #getUiccSlotsInfo()}.
* @return boolean Return true if the switch succeeds, false if the switch fails.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
* @deprecated {@link #setSimSlotMapping(Collection, Executor, Consumer)}
*/
@@ -4328,6 +4441,7 @@
@SystemApi
@Deprecated
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public boolean switchSlots(int[] physicalSlots) {
try {
ITelephony telephony = getITelephony();
@@ -4420,6 +4534,8 @@
* @throws IllegalArgumentException if the caller passes in an invalid collection of
* UiccSlotMapping like duplicate data, etc
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@SystemApi
@@ -4452,11 +4568,14 @@
* @return a map indicates the mapping from logical slots to physical slots. The size of the map
* should be {@link #getPhoneCount()} if success, otherwise return an empty map.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
* @deprecated use {@link #getSimSlotMapping()} instead.
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@NonNull
@Deprecated
public Map<Integer, Integer> getLogicalToPhysicalSlotMapping() {
@@ -4484,6 +4603,9 @@
*
* @return a collection of {@link UiccSlotMapping} which indicates the mapping from logical
* slots to ports and physical slots.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@SystemApi
@@ -4541,6 +4663,9 @@
* the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
* higher, then a SecurityException is thrown.</li>
* </ul>
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -4593,6 +4718,8 @@
* found, and the carrier does not require a key.
* @throws IllegalArgumentException when an invalid key is found or when key is required but
* not found.
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -4638,6 +4765,9 @@
* Requires Permission: MODIFY_PHONE_STATE.
*
* @see #getCarrierInfoForImsiEncryption
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -4840,6 +4970,9 @@
* from disk, as well as on which {@code callback} will be called.
* @param callback A callback called when the upload operation terminates, either in success
* or in error.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public void uploadCallComposerPicture(@NonNull Path pictureToUpload,
@@ -4947,6 +5080,9 @@
* read, as well as on which the callback will be called.
* @param callback A callback called when the upload operation terminates, either in success
* or in error.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public void uploadCallComposerPicture(@NonNull InputStream pictureToUpload,
@@ -5081,6 +5217,9 @@
*
* <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
* or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
@@ -5139,6 +5278,8 @@
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
* for apps targeting SDK API level 29 and below.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @deprecated use {@link SubscriptionManager#getPhoneNumber(int)} instead.
*/
@Deprecated
@@ -5148,6 +5289,7 @@
android.Manifest.permission.READ_SMS,
android.Manifest.permission.READ_PHONE_NUMBERS
})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public String getLine1Number() {
return getLine1Number(getSubId());
}
@@ -5214,9 +5356,13 @@
* @param alphaTag alpha-tagging of the dailing nubmer
* @param number The dialing number
* @return true if the operation was executed correctly.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @deprecated use {@link SubscriptionManager#setCarrierPhoneNumber(int, String)} instead.
*/
@Deprecated
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public boolean setLine1NumberForDisplay(String alphaTag, String number) {
return setLine1NumberForDisplay(getSubId(), alphaTag, number);
}
@@ -5336,6 +5482,8 @@
* {@link SubscriptionManager#createSubscriptionGroup(List)} for the definition of a group,
* otherwise return an empty array if there is a failure.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@SystemApi
@@ -5421,6 +5569,9 @@
*
* <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
* or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
@@ -5459,6 +5610,9 @@
*
* @param alphaTag The alpha tag to display.
* @param number The voicemail number.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public boolean setVoiceMailNumber(String alphaTag, String number) {
@@ -5533,6 +5687,8 @@
* @see #KEY_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL
* @see #KEY_VOICEMAIL_SCRAMBLED_PIN_STRING
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
* @hide
*/
@SystemApi
@@ -5563,6 +5719,9 @@
* @see #createForSubscriptionId(int)
* @see #createForPhoneAccountHandle(PhoneAccountHandle)
* @see VisualVoicemailService
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*/
@Nullable
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@@ -5593,6 +5752,9 @@
*
* @see TelecomManager#getDefaultDialerPackage()
* @see CarrierConfigManager#KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public void setVisualVoicemailSmsFilterSettings(VisualVoicemailSmsFilterSettings settings) {
@@ -5623,6 +5785,9 @@
*
* @see SmsManager#sendDataMessage(String, String, short, byte[], PendingIntent, PendingIntent)
* @see SmsManager#sendTextMessage(String, String, String, PendingIntent, PendingIntent)
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public void sendVisualVoicemailSms(String number, int port, String text,
@@ -5808,6 +5973,9 @@
* @see #SIM_ACTIVATION_STATE_ACTIVATING
* @see #SIM_ACTIVATION_STATE_ACTIVATED
* @see #SIM_ACTIVATION_STATE_DEACTIVATED
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}
* @hide
*/
@SystemApi
@@ -5856,6 +6024,9 @@
* @see #SIM_ACTIVATION_STATE_ACTIVATED
* @see #SIM_ACTIVATION_STATE_DEACTIVATED
* @see #SIM_ACTIVATION_STATE_RESTRICTED
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
* @hide
*/
@SystemApi
@@ -5904,6 +6075,9 @@
* @see #SIM_ACTIVATION_STATE_ACTIVATING
* @see #SIM_ACTIVATION_STATE_ACTIVATED
* @see #SIM_ACTIVATION_STATE_DEACTIVATED
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
* @hide
*/
@SystemApi
@@ -5954,6 +6128,9 @@
* @see #SIM_ACTIVATION_STATE_ACTIVATED
* @see #SIM_ACTIVATION_STATE_DEACTIVATED
* @see #SIM_ACTIVATION_STATE_RESTRICTED
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
* @hide
*/
@SystemApi
@@ -6032,6 +6209,9 @@
*
* <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
* or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
@@ -6072,7 +6252,10 @@
*
* @throws SecurityException if the caller does not have carrier privileges or is not the
* current default dialer
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public void sendDialerSpecialCode(String inputCode) {
try {
final ITelephony telephony = getITelephony();
@@ -6143,6 +6326,9 @@
*
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@Nullable
@@ -6168,6 +6354,9 @@
* Returns the IMS public user identities (IMPU) that were loaded from the ISIM.
* @return an array of IMPU strings, with one IMPU per string, or null if
* not present or not loaded
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
* @deprecated use {@link #getImsPublicUserIdentities()}
*/
@@ -6199,6 +6388,8 @@
* EF_IMPU is not available.
* @throws IllegalStateException in case the ISIM hasn’t been loaded
* @throws SecurityException if the caller does not have the required permission/privilege
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@NonNull
@@ -6254,6 +6445,10 @@
* targeting API level 31+.
*
* @return the current call state.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELECOM}.
+ *
* @deprecated Use {@link #getCallStateForSubscription} to retrieve the call state for a
* specific telephony subscription (which allows carrier privileged apps),
* {@link TelephonyCallback.CallStateListener} for real-time call state updates, or
@@ -6261,6 +6456,7 @@
* device.
*/
@RequiresPermission(value = android.Manifest.permission.READ_PHONE_STATE, conditional = true)
+ @RequiresFeature(PackageManager.FEATURE_TELECOM)
@Deprecated
public @CallState int getCallState() {
if (mContext != null) {
@@ -6281,6 +6477,9 @@
* @see TelephonyManager#createForSubscriptionId(int)
* @see TelephonyManager#createForPhoneAccountHandle(PhoneAccountHandle)
* @return The call state of the subscription associated with this TelephonyManager instance.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
@@ -6341,6 +6540,9 @@
* @see #DATA_ACTIVITY_OUT
* @see #DATA_ACTIVITY_INOUT
* @see #DATA_ACTIVITY_DORMANT
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public int getDataActivity() {
@@ -6414,6 +6616,9 @@
* @see #DATA_SUSPENDED
* @see #DATA_DISCONNECTING
* @see #DATA_HANDOVER_IN_PROGRESS
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public int getDataState() {
@@ -6599,10 +6804,14 @@
* Returns the CDMA ERI icon display number. The number is assigned by
* 3GPP2 C.R1001-H v1.0 Table 8.1-1. Additionally carriers define their own ERI display numbers.
* Defined values are {@link #ERI_ON}, {@link #ERI_OFF}, and {@link #ERI_FLASH}.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CDMA}.
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CDMA)
public @EriIconIndex int getCdmaEnhancedRoamingIndicatorDisplayNumber() {
return getCdmaEriIconIndex(getSubId());
}
@@ -6810,6 +7019,9 @@
*
* @return List of {@link android.telephony.CellInfo}; null if cell
* information is unavailable.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
@@ -6905,6 +7117,9 @@
*
* @param executor the executor on which callback will be invoked.
* @param callback a callback to receive CellInfo.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
@@ -6966,6 +7181,9 @@
* @param workSource the requestor to whom the power consumption for this should be attributed.
* @param executor the executor on which callback will be invoked.
* @param callback a callback to receive CellInfo.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
*/
@SystemApi
@@ -7052,6 +7270,9 @@
/**
* Returns the MMS user agent.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_MESSAGING}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING)
public String getMmsUserAgent() {
@@ -7068,6 +7289,9 @@
/**
* Returns the MMS user agent profile URL.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_MESSAGING}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING)
public String getMmsUAProfUrl() {
@@ -7111,8 +7335,12 @@
*
* @param AID Application id. See ETSI 102.221 and 101.220.
* @return an IccOpenLogicalChannelResponse object.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @deprecated Replaced by {@link #iccOpenLogicalChannel(String, int)}
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@Deprecated
public IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID) {
return iccOpenLogicalChannel(getSubId(), AID, -1);
@@ -7145,6 +7373,8 @@
* @param aid Application id. See ETSI 102.221 and 101.220.
* @param p2 P2 parameter (described in ISO 7816-4).
* @return an IccOpenLogicalChannelResponse object.
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
* @deprecated This API is not compatible on eUICC supporting Multiple Enabled Profile(MEP),
* instead use {@link #iccOpenLogicalChannelByPort(int, int, String, int)}
@@ -7200,9 +7430,13 @@
* @param aid Application id. See ETSI 102.221 and 101.220.
* @param p2 P2 parameter (described in ISO 7816-4).
* @return an IccOpenLogicalChannelResponse object.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@SystemApi
@NonNull
public IccOpenLogicalChannelResponse iccOpenLogicalChannelByPort(int slotIndex,
@@ -7255,6 +7489,9 @@
* @param AID Application id. See ETSI 102.221 and 101.220.
* @param p2 P2 parameter (described in ISO 7816-4).
* @return an IccOpenLogicalChannelResponse object.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID, int p2) {
@@ -7321,6 +7558,9 @@
* @param channel is the channel id to be closed as returned by a successful
* iccOpenLogicalChannel.
* @return true if the channel was closed successfully.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
* @deprecated This API is not compatible on eUICC supporting Multiple Enabled Profile(MEP),
* instead use {@link #iccCloseLogicalChannelByPort(int, int, int)}
@@ -7365,9 +7605,12 @@
* @throws IllegalStateException if the Telephony process is not currently available or modem
* currently can't process this command.
* @throws IllegalArgumentException if invalid arguments are passed.
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@SystemApi
public void iccCloseLogicalChannelByPort(int slotIndex, int portIndex, int channel) {
try {
@@ -7403,6 +7646,8 @@
* iccOpenLogicalChannel.
* @return true if the channel was closed successfully.
* @throws IllegalArgumentException if input parameters are wrong. e.g., invalid channel
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public boolean iccCloseLogicalChannel(int channel) {
@@ -7469,6 +7714,8 @@
* @param data Data to be sent with the APDU.
* @return The APDU response from the ICC card with the status appended at the end, or null if
* there is an issue connecting to the Telephony service.
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
* @deprecated This API is not compatible on eUICC supporting Multiple Enabled Profile(MEP),
* instead use
@@ -7516,9 +7763,13 @@
* @param data Data to be sent with the APDU.
* @return The APDU response from the ICC card with the status appended at the end, or null if
* there is an issue connecting to the Telephony service.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@SystemApi
@NonNull
public String iccTransmitApduLogicalChannelByPort(int slotIndex, int portIndex, int channel,
@@ -7563,6 +7814,9 @@
* @param data Data to be sent with the APDU.
* @return The APDU response from the ICC card with the status appended at
* the end.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public String iccTransmitApduLogicalChannel(int channel, int cla,
@@ -7628,6 +7882,9 @@
* @param data Data to be sent with the APDU.
* @return The APDU response from the ICC card with the status appended at
* the end.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
* @deprecated This API is not compatible on eUICC supporting Multiple Enabled Profile(MEP),
* instead use
@@ -7673,9 +7930,13 @@
* @param data Data to be sent with the APDU.
* @return The APDU response from the ICC card with the status appended at
* the end.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@SystemApi
@NonNull
public String iccTransmitApduBasicChannelByPort(int slotIndex, int portIndex, int cla,
@@ -7712,6 +7973,9 @@
* @param data Data to be sent with the APDU.
* @return The APDU response from the ICC card with the status appended at
* the end.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public String iccTransmitApduBasicChannel(int cla,
@@ -7768,6 +8032,9 @@
* @param p3 P3 value of the APDU command.
* @param filePath
* @return The APDU response.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public byte[] iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
@@ -7817,6 +8084,9 @@
* @return The APDU response from the ICC card in hexadecimal format
* with the last 4 bytes being the status word. If the command fails,
* returns an empty string.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public String sendEnvelopeWithStatus(String content) {
@@ -7978,6 +8248,8 @@
*
* @return {@code true} on success; {@code false} on any failure.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
@@ -8008,6 +8280,8 @@
*
* @deprecated Using {@link #rebootModem()} instead.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
@@ -8035,6 +8309,8 @@
* app has carrier privileges (see {@link #hasCarrierPrivileges}).
* @throws IllegalStateException if the Telephony process is not currently available.
* @throws RuntimeException
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
@@ -8166,6 +8442,9 @@
* {@link #getMaxNumberVerificationTimeoutMillis()}, whichever is lesser.
* @param executor The {@link Executor} that callbacks should be executed on.
* @param callback The callback to use for delivering results.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*/
@SystemApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
@@ -8378,6 +8657,9 @@
* See 3GPP TS 31.103 (Section 4.2.7) for the definition and more information on this table.
*
* @return IMS Service Table or null if not present or not loaded
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@Nullable
@@ -8496,6 +8778,9 @@
* Key freshness failure
* Authentication error, no memory space available
* Authentication error, no memory space available in EFMUK
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
// TODO(b/73660190): This should probably require MODIFY_PHONE_STATE, not
// READ_PRIVILEGED_PHONE_STATE. It certainly shouldn't reference the permission in Javadoc since
@@ -8552,6 +8837,9 @@
* or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @return an array of forbidden PLMNs or null if not available
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
@@ -8602,6 +8890,9 @@
* @return number of PLMNs that were successfully written to the SIM FPLMN list.
* This may be less than the number of PLMNs passed in where the SIM file does not have enough
* room for all of the values passed in. Return -1 in the event of an unexpected failure
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -8637,6 +8928,8 @@
* @param appType of type int of either {@link #APPTYPE_USIM} or {@link #APPTYPE_ISIM}.
* @return HexString represents sim service table else null.
* @throws SecurityException if the caller does not have the required permission/privileges
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@@ -8673,6 +8966,9 @@
* state.
*
* @param slotIndex the sim slot to reset the IMS stack on.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_IMS}.
* @hide */
@SystemApi
@WorkerThread
@@ -9084,12 +9380,15 @@
*
* @return The bitmask of preferred network types.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
* @deprecated Use {@link #getAllowedNetworkTypesBitmask} instead.
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@SystemApi
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public @NetworkTypeBitMask long getPreferredNetworkTypeBitmask() {
return getAllowedNetworkTypesBitmask();
}
@@ -9108,6 +9407,8 @@
*
* @return The bitmask of allowed network types.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -9133,10 +9434,14 @@
* or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @return the allowed network type bitmask
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
* @deprecated Use {@link #getAllowedNetworkTypesForReason} instead.
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
@SystemApi
@Deprecated
public @NetworkTypeBitMask long getAllowedNetworkTypes() {
@@ -9161,6 +9466,9 @@
* <p>Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
* app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -9247,6 +9555,9 @@
* tasks one at a time in serial order.
* @param callback Returns network scan results or errors.
* @return A NetworkScan obj which contains a callback which can be used to stop the scan.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(allOf = {
@@ -9295,11 +9606,15 @@
* tasks one at a time in serial order.
* @param callback Returns network scan results or errors.
* @return A NetworkScan obj which contains a callback which can be used to stop the scan.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(allOf = {
android.Manifest.permission.MODIFY_PHONE_STATE
})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public @Nullable NetworkScan requestNetworkScan(
@IncludeLocationData int includeLocationData,
@NonNull NetworkScanRequest request,
@@ -9317,6 +9632,9 @@
}
/**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
+ *
* @deprecated
* Use {@link
* #requestNetworkScan(NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}
@@ -9327,6 +9645,7 @@
android.Manifest.permission.MODIFY_PHONE_STATE,
Manifest.permission.ACCESS_FINE_LOCATION
})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public NetworkScan requestNetworkScan(
NetworkScanRequest request, TelephonyScanManager.NetworkScanCallback callback) {
return requestNetworkScan(request, AsyncTask.SERIAL_EXECUTOR, callback);
@@ -9347,6 +9666,9 @@
* attaching to the selected PLMN until reboot; otherwise, attach to the chosen PLMN and resume
* normal network selection next time.
* @return {@code true} on success; {@code false} on any failure.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -9378,6 +9700,9 @@
* {@link AccessNetworkConstants.AccessNetworkType#UNKNOWN}, modem will select
* the next best RAN for network registration.
* @return {@code true} on success; {@code false} on any failure.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
@@ -9430,6 +9755,9 @@
* or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @return the network selection mode.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@SuppressAutoDoc // No support for carrier privileges (b/72967236).
@RequiresPermission(anyOf = {
@@ -9459,6 +9787,9 @@
* (see {@link #hasCarrierPrivileges})
*
* @return manually selected network info on success or empty string on failure
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@SuppressAutoDoc // No support carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
@@ -9488,6 +9819,8 @@
*
* @return {@code true} if this device is in emergency SMS mode, {@code false} otherwise.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_MESSAGING}.
* @hide
*/
@SystemApi
@@ -9557,11 +9890,15 @@
*
* @param networkTypeBitmask The bitmask of preferred network types.
* @return true on success; false on any failure.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
* @deprecated Use {@link #setAllowedNetworkTypesForReason} instead.
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
@SystemApi
public boolean setPreferredNetworkTypeBitmask(@NetworkTypeBitMask long networkTypeBitmask) {
try {
@@ -9603,6 +9940,10 @@
*
* @param allowedNetworkTypes The bitmask of allowed network types.
* @return true on success; false on any failure.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
+ *
* @hide
* @deprecated Use {@link #setAllowedNetworkTypesForReason} instead with reason
* {@link #ALLOWED_NETWORK_TYPES_REASON_CARRIER}.
@@ -9690,11 +10031,16 @@
* @throws IllegalStateException if the Telephony process is not currently available.
* @throws IllegalArgumentException if invalid AllowedNetworkTypesReason is passed.
* @throws SecurityException if the caller does not have the required privileges or if the
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* caller tries to use one of the following security-based reasons without
* {@link android.Manifest.permission#MODIFY_PHONE_STATE} permissions.
* <ol>
* <li>{@code TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G}</li>
* </ol>
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@RequiresFeature(
@@ -9734,6 +10080,8 @@
* @throws IllegalStateException if the Telephony process is not currently available.
* @throws IllegalArgumentException if invalid AllowedNetworkTypesReason is passed.
* @throws SecurityException if the caller does not have the required permission/privileges
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@RequiresFeature(
@@ -9808,6 +10156,9 @@
* <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @return true on success; false on any failure.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public boolean setPreferredNetworkTypeToGlobal() {
@@ -9833,6 +10184,9 @@
* Requires Permission: MODIFY_PHONE_STATE.
*
* @return {@code true} if DUN APN is required for tethering.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
* @hide
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -9886,6 +10240,9 @@
* is a superset of the checks done in SubscriptionManager#canManageSubscription.
*
* @return true if the app has carrier privileges.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public boolean hasCarrierPrivileges() {
@@ -9933,6 +10290,9 @@
*
* @param brand The brand name to display/set.
* @return true if the operation was executed correctly.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public boolean setOperatorBrandOverride(String brand) {
@@ -10034,7 +10394,11 @@
* Expose the rest of ITelephony to @SystemApi
*/
- /** @hide */
+ /**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CDMA}.
+ * @hide
+ */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_CDMA)
@@ -10042,7 +10406,11 @@
return getCdmaMdn(getSubId());
}
- /** @hide */
+ /**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CDMA}.
+ * @hide
+ */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_CDMA)
@@ -10059,7 +10427,11 @@
}
}
- /** @hide */
+ /**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CDMA}.
+ * @hide
+ */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_CDMA)
@@ -10067,7 +10439,11 @@
return getCdmaMin(getSubId());
}
- /** @hide */
+ /**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CDMA}.
+ * @hide
+ */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_CDMA)
@@ -10084,7 +10460,11 @@
}
}
- /** @hide */
+ /**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
+ * @hide
+ */
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@@ -10101,7 +10481,11 @@
return CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
}
- /** @hide */
+ /**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
+ * @hide
+ */
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@@ -10118,14 +10502,22 @@
return CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
}
- /** @hide */
+ /**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
+ * @hide
+ */
@SystemApi
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public List<String> getCarrierPackageNamesForIntent(Intent intent) {
return getCarrierPackageNamesForIntentAndPhone(intent, getPhoneId());
}
- /** @hide */
+ /**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
+ * @hide
+ */
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@@ -10152,10 +10544,13 @@
* @return The system-selected package that provides the {@link CarrierService} implementation
* for the current subscription, or {@code null} if none is resolved
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public @Nullable String getCarrierServicePackageName() {
return getCarrierServicePackageNameForLogicalSlot(getPhoneId());
}
@@ -10169,10 +10564,13 @@
* @return The system-selected package that provides the {@link CarrierService} implementation
* for the slot, or {@code null} if none is resolved
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public @Nullable String getCarrierServicePackageNameForLogicalSlot(int logicalSlotIndex) {
try {
ITelephony telephony = getITelephony();
@@ -10206,6 +10604,8 @@
/**
* Get the names of packages with carrier privileges for all the active subscriptions.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@SystemApi
@@ -10256,6 +10656,8 @@
*
* @throws IllegalArgumentException if requested state is invalid.
* @throws SecurityException if the caller does not have the permission.
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
@@ -10285,6 +10687,9 @@
*
* @return the user-set status for enriched calling with call composer, either of
* {@link #CALL_COMPOSER_STATUS_ON} or {@link #CALL_COMPOSER_STATUS_OFF}.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
@@ -10301,7 +10706,11 @@
return CALL_COMPOSER_STATUS_OFF;
}
- /** @hide */
+ /**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
+ * @hide
+ */
@SystemApi
@SuppressLint("RequiresPermission")
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
@@ -10316,6 +10725,9 @@
}
/**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
+ *
* @deprecated Use {@link android.telecom.TelecomManager#placeCall(Uri address,
* Bundle extras)} instead.
* @hide
@@ -10323,6 +10735,7 @@
@Deprecated
@SystemApi
@RequiresPermission(android.Manifest.permission.CALL_PHONE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public void call(String callingPackage, String number) {
try {
ITelephony telephony = getITelephony();
@@ -10369,6 +10782,8 @@
}
/**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELECOM}.
* @deprecated Use {@link android.telecom.TelecomManager#isInCall} instead
* @hide
*/
@@ -10378,12 +10793,15 @@
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
android.Manifest.permission.READ_PHONE_STATE
})
+ @RequiresFeature(PackageManager.FEATURE_TELECOM)
public boolean isOffhook() {
TelecomManager tm = (TelecomManager) mContext.getSystemService(TELECOM_SERVICE);
return tm.isInCall();
}
/**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELECOM}.
* @deprecated Use {@link android.telecom.TelecomManager#isRinging} instead
* @hide
*/
@@ -10393,12 +10811,15 @@
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
android.Manifest.permission.READ_PHONE_STATE
})
+ @RequiresFeature(PackageManager.FEATURE_TELECOM)
public boolean isRinging() {
TelecomManager tm = (TelecomManager) mContext.getSystemService(TELECOM_SERVICE);
return tm.isRinging();
}
/**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELECOM}.
* @deprecated Use {@link android.telecom.TelecomManager#isInCall} instead
* @hide
*/
@@ -10408,12 +10829,15 @@
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
android.Manifest.permission.READ_PHONE_STATE
})
+ @RequiresFeature(PackageManager.FEATURE_TELECOM)
public boolean isIdle() {
TelecomManager tm = (TelecomManager) mContext.getSystemService(TELECOM_SERVICE);
return !tm.isInCall();
}
/**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @deprecated Use {@link android.telephony.TelephonyManager#getServiceState} instead
* @hide
*/
@@ -10423,6 +10847,7 @@
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
android.Manifest.permission.READ_PHONE_STATE
})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public boolean isRadioOn() {
try {
ITelephony telephony = getITelephony();
@@ -10434,7 +10859,11 @@
return false;
}
- /** @hide */
+ /**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
+ * @hide
+ */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@@ -10449,7 +10878,11 @@
return false;
}
- /** @hide */
+ /**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
+ * @hide
+ */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@@ -10465,11 +10898,15 @@
}
/**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
+ *
* @deprecated use {@link #supplyIccLockPin(String)} instead.
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@Deprecated
public int[] supplyPinReportResult(String pin) {
try {
@@ -10483,11 +10920,15 @@
}
/**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
+ *
* @deprecated use {@link #supplyIccLockPuk(String, String)} instead.
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@Deprecated
public int[] supplyPukReportResult(String puk, String pin) {
try {
@@ -10513,6 +10954,8 @@
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
* app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@SystemApi
@@ -10549,6 +10992,8 @@
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
* app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@SystemApi
@@ -10622,6 +11067,9 @@
* @param callback called by the framework to inform the caller of the result of executing the
* USSD request (see {@link UssdResponseCallback}).
* @param handler the {@link Handler} to run the request on.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@RequiresPermission(android.Manifest.permission.CALL_PHONE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
@@ -10666,6 +11114,9 @@
* voice and data simultaneously. This can change based on location or network condition.
*
* @return {@code true} if simultaneous voice and data supported, and {@code false} otherwise.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public boolean isConcurrentVoiceAndDataSupported() {
@@ -10679,9 +11130,13 @@
return false;
}
- /** @hide */
+ /**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
+ * @hide */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public boolean handlePinMmi(String dialString) {
try {
ITelephony telephony = getITelephony();
@@ -10693,9 +11148,14 @@
return false;
}
- /** @hide */
+ /**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
+ * @hide
+ */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public boolean handlePinMmiForSubscriber(int subId, String dialString) {
try {
ITelephony telephony = getITelephony();
@@ -10707,7 +11167,11 @@
return false;
}
- /** @hide */
+ /**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
+ * @hide
+ */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
@@ -10725,6 +11189,8 @@
* @deprecated - use the APIs {@link requestRadioPowerOffForReason} and
* {@link clearRadioPowerOffForReason}.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
*/
@Deprecated
@@ -10752,6 +11218,8 @@
* @deprecated - use the APIs {@link requestRadioPowerOffForReason} and
* {@link clearRadioPowerOffForReason}.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
*/
@Deprecated
@@ -10799,6 +11267,8 @@
* @throws SecurityException if the caller does not have MODIFY_PHONE_STATE permission.
* @throws IllegalStateException if the Telephony service is not currently available.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
*/
@SystemApi
@@ -10828,6 +11298,8 @@
* @throws SecurityException if the caller does not have MODIFY_PHONE_STATE permission.
* @throws IllegalStateException if the Telephony service is not currently available.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
*/
@SystemApi
@@ -10857,6 +11329,8 @@
* @throws SecurityException if the caller does not have READ_PRIVILEGED_PHONE_STATE permission.
* @throws IllegalStateException if the Telephony service is not currently available.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
*/
@SystemApi
@@ -10886,6 +11360,8 @@
* <p>To know when the radio has completed powering off, use
* {@link PhoneStateListener#LISTEN_SERVICE_STATE LISTEN_SERVICE_STATE}.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
*/
@SystemApi
@@ -10907,6 +11383,9 @@
* Check if any radio is on over all the slot indexes.
*
* @return {@code true} if any radio is on over any slot index.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
*/
@SystemApi
@@ -10953,6 +11432,8 @@
* {@link android.Manifest.permission#READ_PHONE_STATE} or that the calling
* app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
*/
@SystemApi
@@ -10982,7 +11463,11 @@
Log.e(TAG, "Do not call TelephonyManager#updateServiceLocation()");
}
- /** @hide */
+ /**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
+ * @hide
+ */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
@@ -10997,7 +11482,11 @@
return false;
}
- /** @hide */
+ /**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
+ * @hide
+ */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
@@ -11012,7 +11501,11 @@
return false;
}
- /** @hide */
+ /**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
+ * @hide
+ */
@SystemApi
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public boolean isDataConnectivityPossible() {
@@ -11027,7 +11520,11 @@
return false;
}
- /** @hide */
+ /**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
+ * @hide
+ */
@SystemApi
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public boolean needsOtaServiceProvisioning() {
@@ -11078,23 +11575,29 @@
* app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param enable Whether to enable mobile data.
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
* @deprecated use setDataEnabledForReason with reason DATA_ENABLED_REASON_USER instead.
*
*/
@Deprecated
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public void setDataEnabled(boolean enable) {
setDataEnabled(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()), enable);
}
/**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
* @hide
* @deprecated use {@link #setDataEnabledForReason(int, boolean)} instead.
*/
@SystemApi
@Deprecated
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public void setDataEnabled(int subId, boolean enable) {
try {
setDataEnabledForReason(subId, DATA_ENABLED_REASON_USER, enable);
@@ -11105,10 +11608,14 @@
/**
* @deprecated use {@link #isDataEnabled()} instead.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
* @hide
*/
@SystemApi
@Deprecated
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public boolean getDataEnabled() {
return isDataEnabled();
}
@@ -11132,6 +11639,9 @@
* {@link ConnectivityManager#getRestrictBackgroundStatus}.
*
* @return true if mobile data is enabled.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
*/
@RequiresPermission(anyOf = {android.Manifest.permission.ACCESS_NETWORK_STATE,
android.Manifest.permission.MODIFY_PHONE_STATE,
@@ -11162,6 +11672,9 @@
* has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @return {@code true} if the data roaming is enabled on the subscription, otherwise return
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
* {@code false}.
*/
@RequiresPermission(anyOf = {android.Manifest.permission.ACCESS_NETWORK_STATE,
@@ -11201,6 +11714,8 @@
* {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
* or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CDMA}.
* @hide
*/
@SystemApi
@@ -11243,6 +11758,8 @@
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
* app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CDMA}.
* @hide
*/
@SystemApi
@@ -11311,6 +11828,8 @@
* {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
* or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CDMA}.
* @hide
*/
@SystemApi
@@ -11349,6 +11868,8 @@
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
* app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CDMA}.
* @hide
*/
@SystemApi
@@ -11384,6 +11905,8 @@
*
* @param isEnabled {@code true} to enable mobile data roaming, otherwise disable it.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
* @hide
*/
@SystemApi
@@ -11402,11 +11925,15 @@
}
/**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
+ *
* @deprecated use {@link #isDataEnabled()} instead.
* @hide
*/
@Deprecated
@SystemApi
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public boolean getDataEnabled(int subId) {
try {
return isDataEnabledForReason(subId, DATA_ENABLED_REASON_USER);
@@ -11417,6 +11944,8 @@
}
/**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_IMS}.
* @deprecated Use {@link android.telephony.ims.ImsMmTelManager#setVtSettingEnabled(boolean)}
* instead.
* @hide
@@ -11424,6 +11953,7 @@
@Deprecated
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_IMS)
public void enableVideoCalling(boolean enable) {
try {
ITelephony telephony = getITelephony();
@@ -11435,6 +11965,8 @@
}
/**
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_IMS}.
* @deprecated Use {@link ImsMmTelManager#isVtSettingEnabled()} instead to check if the user
* has enabled the Video Calling setting, {@link ImsMmTelManager#isAvailable(int, int)} to
* determine if video calling is available, or {@link ImsMmTelManager#isCapable(int, int)} to
@@ -11447,6 +11979,7 @@
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
android.Manifest.permission.READ_PHONE_STATE
})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_IMS)
public boolean isVideoCallingEnabled() {
try {
ITelephony telephony = getITelephony();
@@ -11462,6 +11995,9 @@
* Whether the device supports configuring the DTMF tone length.
*
* @return {@code true} if the DTMF tone length can be changed, and {@code false} otherwise.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public boolean canChangeDtmfToneLength() {
@@ -11483,7 +12019,11 @@
* Whether the device is a world phone.
*
* @return {@code true} if the device is a world phone, and {@code false} otherwise.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY}.
*/
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY)
public boolean isWorldPhone() {
try {
ITelephony telephony = getITelephony();
@@ -11504,8 +12044,11 @@
*
* @return {@code true} if the device supports TTY mode, and {@code false} otherwise.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELECOM}.
*/
@Deprecated
+ @RequiresFeature(PackageManager.FEATURE_TELECOM)
public boolean isTtyModeSupported() {
try {
TelecomManager telecomManager = null;
@@ -11526,6 +12069,9 @@
* support for the feature and device firmware support.
*
* @return {@code true} if the device and carrier both support RTT, {@code false} otherwise.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_IMS}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_IMS)
public boolean isRttSupported() {
@@ -11546,6 +12092,9 @@
*
* @return {@code true} if the device supports hearing aid compatibility, and {@code false}
* otherwise.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public boolean isHearingAidCompatibilitySupported() {
@@ -11808,11 +12357,14 @@
* <p>Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* {@hide}
**/
@SystemApi
@Deprecated
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public void setSimPowerState(int state) {
setSimPowerStateForSlot(getSlotIndex(), state);
}
@@ -11834,11 +12386,14 @@
* <p>Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* {@hide}
**/
@SystemApi
@Deprecated
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public void setSimPowerStateForSlot(int slotIndex, int state) {
try {
ITelephony telephony = getITelephony();
@@ -11871,6 +12426,8 @@
* <p>Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* {@hide}
**/
@SystemApi
@@ -11901,6 +12458,8 @@
* <p>Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* {@hide}
**/
@SystemApi
@@ -12055,6 +12614,9 @@
* application currently configured for this user.
* @return component name of the app and class to direct Respond Via Message intent to, or
* {@code null} if the functionality is not supported.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_MESSAGING}.
* @hide
*/
@SystemApi
@@ -12077,6 +12639,9 @@
* user associated with this subscription.
* @return component name of the app and class to direct Respond Via Message intent to, or
* {@code null} if the functionality is not supported.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_MESSAGING}.
* @hide
*/
@SystemApi
@@ -12213,9 +12778,13 @@
* @return The {@link PhoneAccountHandle} associated with the TelphonyManager, or {@code null}
* if there is no associated {@link PhoneAccountHandle}; this can happen if the subscription is
* data-only or an opportunistic subscription.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public @Nullable PhoneAccountHandle getPhoneAccountHandle() {
return getPhoneAccountHandleForSubscriptionId(getSubId());
}
@@ -12277,10 +12846,14 @@
* Resets Telephony and IMS settings back to factory defaults only for the subscription
* associated with this instance.
* @see #createForSubscriptionId(int)
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY}.
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.CONNECTIVITY_INTERNAL)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY)
public void resetSettings() {
try {
Log.d(TAG, "resetSettings: subId=" + getSubId());
@@ -12302,6 +12875,8 @@
*
* @see Locale#toLanguageTag()
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@SystemApi
@@ -12394,10 +12969,14 @@
* @param callback A callback object to which the result will be delivered. If there was an
* error processing the request, {@link OutcomeReceiver#onError} will be called
* with more details about the error.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY}.
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY)
public void requestModemActivityInfo(@NonNull @CallbackExecutor Executor executor,
@NonNull OutcomeReceiver<ModemActivityInfo, ModemActivityInfoException> callback) {
Objects.requireNonNull(executor);
@@ -12484,6 +13063,9 @@
* and {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}.
* May return {@code null} when the subscription is inactive or when there was an error
* communicating with the phone process.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(allOf = {
@@ -12516,12 +13098,16 @@
* location related information.
* May return {@code null} when the subscription is inactive or when there was an error
* communicating with the phone process.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(allOf = {
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.ACCESS_COARSE_LOCATION
})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public @Nullable ServiceState getServiceState(@IncludeLocationData int includeLocationData) {
return getServiceStateForSubscriber(getSubId(),
includeLocationData != INCLUDE_LOCATION_DATA_FINE,
@@ -12580,6 +13166,9 @@
* voicemail ringtone.
* @return The URI for the ringtone to play when receiving a voicemail from a specific
* PhoneAccount. May be {@code null} if no ringtone is set.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public @Nullable Uri getVoicemailRingtoneUri(PhoneAccountHandle accountHandle) {
@@ -12606,10 +13195,13 @@
* @param uri The URI for the ringtone to play when receiving a voicemail from a specific
* PhoneAccount.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
* @deprecated Use {@link android.provider.Settings#ACTION_CHANNEL_NOTIFICATION_SETTINGS}
* instead.
*/
@Deprecated
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public void setVoicemailRingtoneUri(PhoneAccountHandle phoneAccountHandle, Uri uri) {
try {
ITelephony service = getITelephony();
@@ -12627,6 +13219,9 @@
* @param accountHandle The handle for the {@link PhoneAccount} for which to retrieve the
* voicemail vibration setting.
* @return {@code true} if the vibration is set for this PhoneAccount, {@code false} otherwise.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public boolean isVoicemailVibrationEnabled(PhoneAccountHandle accountHandle) {
@@ -12653,10 +13248,13 @@
* @param enabled Whether to enable or disable vibration for voicemail notifications from a
* specific PhoneAccount.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
* @deprecated Use {@link android.provider.Settings#ACTION_CHANNEL_NOTIFICATION_SETTINGS}
* instead.
*/
@Deprecated
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public void setVoicemailVibrationEnabled(PhoneAccountHandle phoneAccountHandle,
boolean enabled) {
try {
@@ -12682,6 +13280,9 @@
*
* @return Carrier id of the current subscription. Return {@link #UNKNOWN_CARRIER_ID} if the
* subscription is unavailable or the carrier cannot be identified.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public int getSimCarrierId() {
@@ -12707,6 +13308,9 @@
*
* @return Carrier name of the current subscription. Return {@code null} if the subscription is
* unavailable or the carrier cannot be identified.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public @Nullable CharSequence getSimCarrierIdName() {
@@ -12745,6 +13349,9 @@
* @return Returns fine-grained carrier id of the current subscription.
* Return {@link #UNKNOWN_CARRIER_ID} if the subscription is unavailable or the carrier cannot
* be identified.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public int getSimSpecificCarrierId() {
@@ -12771,6 +13378,9 @@
*
* @return user-facing name of the subscription specific carrier id. Return {@code null} if the
* subscription is unavailable or the carrier cannot be identified.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public @Nullable CharSequence getSimSpecificCarrierIdName() {
@@ -12799,6 +13409,9 @@
*
* @return matching carrier id from sim MCCMNC. Return {@link #UNKNOWN_CARRIER_ID} if the
* subscription is unavailable or the carrier cannot be identified.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public int getCarrierIdFromSimMccMnc() {
@@ -12874,6 +13487,9 @@
*
* @param appType the uicc app type.
* @return Application ID for specified app type or {@code null} if no uicc or error.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@Nullable
@@ -12939,6 +13555,9 @@
* Requires that the calling app has READ_PRIVILEGED_PHONE_STATE permission
*
* @return PRLVersion or null if error.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CDMA}.
* @hide
*/
@SystemApi
@@ -13004,6 +13623,9 @@
*
* @return The number of carriers set successfully. Should be length of
* carrierList on success; -1 if carrierList null or on error.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CARRIERLOCK}.
* @hide
*/
@SystemApi
@@ -13130,6 +13752,9 @@
* @return {@link #SET_CARRIER_RESTRICTION_SUCCESS} in case of success.
* {@link #SET_CARRIER_RESTRICTION_NOT_SUPPORTED} if the modem does not support the
* configuration. {@link #SET_CARRIER_RESTRICTION_ERROR} in all other error cases.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CARRIERLOCK}.
* @hide
*/
@SystemApi
@@ -13163,11 +13788,15 @@
*
* @return List of {@link android.telephony.CarrierIdentifier}; empty list
* means all carriers are allowed.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CARRIERLOCK}.
* @hide
*/
@Deprecated
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CARRIERLOCK)
public List<CarrierIdentifier> getAllowedCarriers(int slotIndex) {
if (SubscriptionManager.isValidPhoneId(slotIndex)) {
CarrierRestrictionRules carrierRestrictionRule = getCarrierRestrictionRules();
@@ -13189,6 +13818,9 @@
* @return {@link CarrierRestrictionRules} which contains the allowed carrier list and the
* excluded carrier list with the priority between the two lists. Returns {@code null}
* in case of error.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CARRIERLOCK}.
* @hide
*/
@SystemApi
@@ -13257,6 +13889,8 @@
* status result fetched from the radio
* @throws SecurityException if the caller does not have the required permission/privileges or
* if the caller is not pre-registered.
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
@@ -13323,11 +13957,15 @@
* @see #resetAllCarrierActions()
* @deprecated use {@link #setDataEnabledForReason(int, boolean) with
* reason {@link #DATA_ENABLED_REASON_CARRIER}} instead.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
* @hide
*/
@Deprecated
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public void setCarrierDataEnabled(boolean enabled) {
try {
setDataEnabledForReason(DATA_ENABLED_REASON_CARRIER, enabled);
@@ -13351,6 +13989,8 @@
* @deprecated - use the APIs {@link requestRadioPowerOffForReason} and
* {@link clearRadioPowerOffForReason}.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
*/
@Deprecated
@@ -13470,6 +14110,9 @@
*
* @param report control start/stop reporting network status.
* @see #resetAllCarrierActions()
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
*/
@SystemApi
@@ -13496,6 +14139,8 @@
*
* <p>Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@SystemApi
@@ -13618,6 +14263,8 @@
* has {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} irrespective of
* the reason.
* @throws IllegalStateException if the Telephony process is not currently available.
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
@@ -13661,6 +14308,8 @@
* {@link android.Manifest.permission#MODIFY_PHONE_STATE}
* {@link android.Manifest.permission#READ_BASIC_PHONE_STATE}
* @throws IllegalStateException if the Telephony process is not currently available.
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
*/
@RequiresPermission(anyOf = {android.Manifest.permission.ACCESS_NETWORK_STATE,
android.Manifest.permission.READ_PHONE_STATE,
@@ -13717,6 +14366,9 @@
* given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
*
* @return true if phone is in emergency callback mode.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
* @hide
*/
@SystemApi
@@ -13756,6 +14408,9 @@
* given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}.
*
* @return {@code true} if manual network selection is allowed, otherwise return {@code false}.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@SuppressAutoDoc // No support carrier privileges (b/72967236).
@RequiresPermission(anyOf = {android.Manifest.permission.READ_PRECISE_PHONE_STATE,
@@ -13779,6 +14434,9 @@
* Get the most recent SignalStrength information reported by the modem. Due
* to power saving this information may not always be current.
* @return the most recent cached signal strength info from the modem
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@Nullable
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
@@ -13805,6 +14463,9 @@
* <LI>And possibly others.</LI>
* </UL>
* @return {@code true} if the overall data connection is allowed; {@code false} if not.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
*/
@RequiresPermission(anyOf = {android.Manifest.permission.ACCESS_NETWORK_STATE,
android.Manifest.permission.READ_PHONE_STATE,
@@ -13975,6 +14636,9 @@
*
* @param enable enable(True) or disable(False)
* @return returns true if successfully set.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -14004,6 +14668,9 @@
* <p>
* Requires Permission:
* {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -14205,6 +14872,8 @@
* that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @throws SecurityException if the caller does not have the required permission
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
@@ -14240,6 +14909,8 @@
* <p> Requires permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
* @hide
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -14267,6 +14938,8 @@
* <p> Requires permission:
* {@link android.Manifest.permission#READ_ACTIVE_EMERGENCY_SESSION}
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
* @hide
*/
@RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
@@ -14293,6 +14966,8 @@
* <p> Requires permission:
* {@link android.Manifest.permission#READ_ACTIVE_EMERGENCY_SESSION}
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
* @hide
*/
@RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
@@ -14353,6 +15028,9 @@
* subscription, the key is {@link SubscriptionManager#getDefaultSubscriptionId}) and the value
* as the list of {@link EmergencyNumber}; empty Map if this information is not available;
* or throw a SecurityException if the caller does not have the permission.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
@NonNull
@@ -14409,6 +15087,8 @@
* as the list of {@link EmergencyNumber}; empty Map if this information is not available;
* or throw a SecurityException if the caller does not have the permission.
* @throws IllegalStateException if the Telephony process is not currently available.
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
@NonNull
@@ -14477,6 +15157,8 @@
* @return {@code true} if the given number is an emergency number based on current locale,
* SIM card(s), Android database, modem, network or defaults; {@code false} otherwise.
* @throws IllegalStateException if the Telephony process is not currently available.
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public boolean isEmergencyNumber(@NonNull String number) {
@@ -14514,6 +15196,8 @@
* network; {@code false} if it is not; or throw an SecurityException if the caller does not
* have the required permission/privileges
* @throws IllegalStateException if the Telephony process is not currently available.
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*
* @deprecated Please use {@link TelephonyManager#isEmergencyNumber(String)} instead.
* @hide
@@ -14543,6 +15227,8 @@
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
* @hide
*/
@SystemApi
@@ -14694,6 +15380,9 @@
* @param callback Callback will be triggered once it succeeds or failed.
* See the {@code SET_OPPORTUNISTIC_SUB_*} constants
* for more details. Pass null if don't care about the result.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public void setPreferredOpportunisticDataSubscription(int subId, boolean needValidation,
@@ -14754,6 +15443,8 @@
* {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} if there are no preferred
* subscription id
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
*/
@RequiresPermission(anyOf = {
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
@@ -14793,6 +15484,8 @@
* @param executor The executor of where the callback will execute.
* @param callback Callback will be triggered once it succeeds or failed.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
@@ -14853,10 +15546,13 @@
* @param enable whether to enable or disable the modem stack.
* @return whether the operation is successful.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY}.
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY)
public boolean enableModemForSlot(int slotIndex, boolean enable) {
boolean ret = false;
try {
@@ -14879,10 +15575,14 @@
* {@link #hasCarrierPrivileges()}).
*
* @param slotIndex which slot it's checking.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY}.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(anyOf = {android.Manifest.permission.READ_PHONE_STATE,
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY)
public boolean isModemEnabledForSlot(int slotIndex) {
try {
ITelephony telephony = getITelephony();
@@ -14945,6 +15645,8 @@
* @param isMultiSimCarrierRestricted true if usage of multiple SIMs is restricted, false
* otherwise.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CARRIERLOCK}.
* @hide
*/
@SystemApi
@@ -15000,6 +15702,9 @@
* {@link #MULTISIM_NOT_SUPPORTED_BY_HARDWARE} if the device does not support multiple SIMs.
* {@link #MULTISIM_NOT_SUPPORTED_BY_CARRIER} in the device supports multiple SIMs, but the
* functionality is restricted by the carrier.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
@@ -15031,6 +15736,8 @@
*
* @param numOfSims number of live SIMs we want to switch to
* @throws android.os.RemoteException
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -15058,6 +15765,9 @@
*
* @return {@code true} if reboot will be triggered after making changes to modem
* configurations, otherwise return {@code false}.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*/
@RequiresPermission(Manifest.permission.READ_PHONE_STATE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@@ -15220,6 +15930,8 @@
* {@link #CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED}, or
* {@link #CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES}
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@SystemApi
@@ -15334,6 +16046,8 @@
* @param apnType Value indicating the apn type. Apn types are defined in {@link ApnSetting}.
* @return whether data is enabled for a apn type.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
* @hide
*/
@SystemApi
@@ -15356,6 +16070,8 @@
* Whether an APN type is metered or not. It will be evaluated with the subId associated
* with the TelephonyManager instance.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
* @hide
*/
@SystemApi
@@ -15385,6 +16101,9 @@
* @param executor The executor to execute the callback on
* @param callback The callback that gets invoked when the radio responds to the request. Called
* with {@code true} if the request succeeded, {@code false} otherwise.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
*/
@SystemApi
@@ -15403,6 +16122,9 @@
* Same as {@link #setSystemSelectionChannels(List, Executor, Consumer<Boolean>)}, but to be
* used when the caller does not need feedback on the results of the operation.
* @param specifiers which bands to scan.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
*/
@SystemApi
@@ -15450,6 +16172,8 @@
* @return a list of {@link RadioAccessSpecifier}, or an empty list if no bands are specified.
* @throws IllegalStateException if the Telephony process is not currently available.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
*/
@SystemApi
@@ -15478,6 +16202,8 @@
* @return {@code true} if input mccmnc and mvno matches with data from sim operator.
* {@code false} otherwise.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* {@hide}
*/
@SystemApi
@@ -15568,6 +16294,8 @@
* {@link CallForwardingInfo#REASON_UNCONDITIONAL}, {@link CallForwardingInfo#REASON_BUSY},
* {@link CallForwardingInfo#REASON_NO_REPLY}, {@link CallForwardingInfo#REASON_NOT_REACHABLE},
* {@link CallForwardingInfo#REASON_ALL}, or {@link CallForwardingInfo#REASON_ALL_CONDITIONAL}
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
*
* @hide
*/
@@ -15645,6 +16373,8 @@
* <li>{@link CallForwardingInfo#getTimeoutSeconds()} returns a non-positive value when
* enabling call forwarding</li>
* </ul>
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
* @hide
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -15769,6 +16499,9 @@
* <li>{@link #CALL_WAITING_STATUS_NOT_SUPPORTED}}</li>
* <li>{@link #CALL_WAITING_STATUS_FDN_CHECK_FAILURE}}</li>
* </ul>
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
* @hide
*/
@SystemApi
@@ -15819,6 +16552,9 @@
* {@link #CALL_WAITING_STATUS_NOT_SUPPORTED} or
* {@link #CALL_WAITING_STATUS_UNKNOWN_ERROR} or
* {@link #CALL_WAITING_STATUS_FDN_CHECK_FAILURE} if it failed.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_CALLING}.
* @hide
*/
@SystemApi
@@ -15919,6 +16655,9 @@
*
* @param policy The data policy to enable.
* @param enabled Whether to enable or disable the policy.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
* @hide
*/
@SystemApi
@@ -15940,6 +16679,9 @@
*
* @param policy The data policy that you want the status for.
* @return {@code true} if enabled, {@code false} otherwise.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
* @hide
*/
@SystemApi
@@ -15975,6 +16717,8 @@
* {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
* or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@WorkerThread
@@ -16009,6 +16753,8 @@
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
* app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@SystemApi
@@ -16051,6 +16797,8 @@
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
* app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@SystemApi
@@ -16199,6 +16947,8 @@
* </ol>
* @return operation result.
* @throws IllegalStateException if the Telephony process is not currently available.
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
*/
@SystemApi
@@ -16233,6 +16983,8 @@
* connectivity is active. It means the device is allowed to connect to both primary and
* secondary cell.
* @throws IllegalStateException if the Telephony process is not currently available.
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
*/
@SystemApi
@@ -16470,6 +17222,8 @@
*
* @throws IllegalStateException if the Telephony process is not currently available.
* @throws SecurityException if the caller doesn't have the permission.
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
*
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
@@ -16586,6 +17340,9 @@
*
* @param capability the name of the capability to check for
* @return the availability of the capability
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)
public boolean isRadioInterfaceCapabilitySupported(
@@ -16705,6 +17462,8 @@
* @throws IllegalArgumentException if the thermalMitigationRequest had invalid parameters or
* if the device's modem does not support data throttling.
*
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
* @hide
*/
@SystemApi
@@ -17037,6 +17796,9 @@
* contain the GBA Ks_NAF/Ks_ext_NAF when available. If the NAF keys are
* available and valid at the time of call and bootstrapping is not requested,
* then the callback shall be invoked with the available keys.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@SystemApi
@@ -17135,6 +17897,8 @@
* @param request the SignalStrengthUpdateRequest to be set into the System
*
* @throws IllegalStateException if a new request is set with same subId from the same caller
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -17165,6 +17929,9 @@
* @see #setSignalStrengthUpdateRequest(SignalStrengthUpdateRequest)
*
* @param request the SignalStrengthUpdateRequest to be cleared from the System
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -17188,10 +17955,14 @@
* @return the PhoneCapability which describes the data connection capability of modem.
* It's used to evaluate possible phone config change, for example from single
* SIM device to multi-SIM device.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public @NonNull PhoneCapability getPhoneCapability() {
try {
ITelephony telephony = getITelephony();
@@ -17256,11 +18027,15 @@
* at least one SIM card for which the user needs to manually enter the PIN
* code after the reboot. {@link #PREPARE_UNATTENDED_REBOOT_ERROR} in case
* of error.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.REBOOT)
@PrepareUnattendedRebootResult
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public int prepareForUnattendedReboot() {
try {
ITelephony service = getITelephony();
@@ -17363,6 +18138,9 @@
*
* @param executor the executor on which callback will be invoked.
* @param callback a callback to receive the current slicing configuration.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_RADIO_ACCESS}.
*/
@RequiresFeature(
enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported",
@@ -17444,8 +18222,11 @@
* @param capability The premium capability to check.
* @return Whether the given premium capability is available to purchase.
* @throws SecurityException if the caller does not hold permission READ_BASIC_PHONE_STATE.
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
*/
@RequiresPermission(android.Manifest.permission.READ_BASIC_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public boolean isPremiumCapabilityAvailableForPurchase(@PremiumCapability int capability) {
try {
ITelephony telephony = getITelephony();
@@ -17685,10 +18466,13 @@
* @param callback The result of the purchase request.
* @throws SecurityException if the caller does not hold permissions
* READ_BASIC_PHONE_STATE or INTERNET.
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_DATA}.
* @see #isPremiumCapabilityAvailableForPurchase(int) to check whether the capability is valid.
*/
@RequiresPermission(allOf = {android.Manifest.permission.READ_BASIC_PHONE_STATE,
android.Manifest.permission.INTERNET})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public void purchasePremiumCapability(@PremiumCapability int capability,
@NonNull @CallbackExecutor Executor executor,
@NonNull @PurchasePremiumCapabilityResult Consumer<Integer> callback) {
@@ -18142,10 +18926,14 @@
* Get current cell broadcast message identifier ranges.
*
* @throws SecurityException if the caller does not have the required permission
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_MESSAGING}.
+ *
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING)
@NonNull
public List<CellBroadcastIdRange> getCellBroadcastIdRanges() {
try {
@@ -18299,10 +19087,13 @@
* the result when the operation completes.
* @throws SecurityException if the caller does not have the required permission
* @throws IllegalArgumentException when the ranges are invalid.
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_MESSAGING}.
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING)
public void setCellBroadcastIdRanges(@NonNull List<CellBroadcastIdRange> ranges,
@NonNull @CallbackExecutor Executor executor,
@NonNull Consumer<Integer> callback) {
@@ -18378,7 +19169,8 @@
* </ul>
*
* @return Primary IMEI of type string
- * @throws UnsupportedOperationException if the radio doesn't support this feature.
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_GSM}.
* @throws SecurityException if the caller does not have the required permission/privileges
*/
@NonNull
diff --git a/tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt b/tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt
index 9c33576..bbd4567 100644
--- a/tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt
+++ b/tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt
@@ -36,12 +36,12 @@
import android.view.InputDevice
import android.view.inputmethod.InputMethodInfo
import android.view.inputmethod.InputMethodSubtype
-import androidx.test.core.R
import androidx.test.core.app.ApplicationProvider
import com.android.dx.mockito.inline.extended.ExtendedMockito
import com.android.internal.os.KeyboardConfiguredProto
import com.android.internal.util.FrameworkStatsLog
import com.android.modules.utils.testing.ExtendedMockitoRule
+import com.android.test.input.R
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals