diff options
94 files changed, 1835 insertions, 625 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index a03f8c5c167f..cbc35299fff3 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -6235,6 +6235,7 @@ package android.app { } public class KeyguardManager { + method @FlaggedApi("android.app.device_unlock_listener") @RequiresPermission(android.Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE) public void addDeviceLockedStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.KeyguardManager.DeviceLockedStateListener); method @RequiresPermission(android.Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE) public void addKeyguardLockedStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.KeyguardManager.KeyguardLockedStateListener); method @Deprecated public android.content.Intent createConfirmDeviceCredentialIntent(CharSequence, CharSequence); method @Deprecated @RequiresPermission(android.Manifest.permission.DISABLE_KEYGUARD) public void exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult); @@ -6244,10 +6245,15 @@ package android.app { method public boolean isKeyguardLocked(); method public boolean isKeyguardSecure(); method @Deprecated public android.app.KeyguardManager.KeyguardLock newKeyguardLock(String); + method @FlaggedApi("android.app.device_unlock_listener") @RequiresPermission(android.Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE) public void removeDeviceLockedStateListener(@NonNull android.app.KeyguardManager.DeviceLockedStateListener); method @RequiresPermission(android.Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE) public void removeKeyguardLockedStateListener(@NonNull android.app.KeyguardManager.KeyguardLockedStateListener); method public void requestDismissKeyguard(@NonNull android.app.Activity, @Nullable android.app.KeyguardManager.KeyguardDismissCallback); } + @FlaggedApi("android.app.device_unlock_listener") @java.lang.FunctionalInterface public static interface KeyguardManager.DeviceLockedStateListener { + method public void onDeviceLockedStateChanged(boolean); + } + public abstract static class KeyguardManager.KeyguardDismissCallback { ctor public KeyguardManager.KeyguardDismissCallback(); method public void onDismissCancelled(); diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 25434e88aadd..decfc8cceeae 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -15146,6 +15146,32 @@ package android.telephony { method @NonNull public android.telephony.CellIdentityWcdma sanitizeLocationInfo(); } + @FlaggedApi("com.android.internal.telephony.flags.cellular_identifier_disclosure_indications") public final class CellularIdentifierDisclosure implements android.os.Parcelable { + method public int describeContents(); + method public int getCellularIdentifier(); + method public int getNasProtocolMessage(); + method @NonNull public String getPlmn(); + method public boolean isEmergency(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field public static final int CELLULAR_IDENTIFIER_IMEI = 2; // 0x2 + field public static final int CELLULAR_IDENTIFIER_IMSI = 1; // 0x1 + field public static final int CELLULAR_IDENTIFIER_SUCI = 3; // 0x3 + field public static final int CELLULAR_IDENTIFIER_UNKNOWN = 0; // 0x0 + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellularIdentifierDisclosure> CREATOR; + field public static final int NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST = 1; // 0x1 + field public static final int NAS_PROTOCOL_MESSAGE_AUTHENTICATION_AND_CIPHERING_RESPONSE = 6; // 0x6 + field public static final int NAS_PROTOCOL_MESSAGE_CM_REESTABLISHMENT_REQUEST = 9; // 0x9 + field public static final int NAS_PROTOCOL_MESSAGE_CM_SERVICE_REQUEST = 10; // 0xa + field public static final int NAS_PROTOCOL_MESSAGE_DEREGISTRATION_REQUEST = 8; // 0x8 + field public static final int NAS_PROTOCOL_MESSAGE_DETACH_REQUEST = 3; // 0x3 + field public static final int NAS_PROTOCOL_MESSAGE_IDENTITY_RESPONSE = 2; // 0x2 + field public static final int NAS_PROTOCOL_MESSAGE_IMSI_DETACH_INDICATION = 11; // 0xb + field public static final int NAS_PROTOCOL_MESSAGE_LOCATION_UPDATE_REQUEST = 5; // 0x5 + field public static final int NAS_PROTOCOL_MESSAGE_REGISTRATION_REQUEST = 7; // 0x7 + field public static final int NAS_PROTOCOL_MESSAGE_TRACKING_AREA_UPDATE_REQUEST = 4; // 0x4 + field public static final int NAS_PROTOCOL_MESSAGE_UNKNOWN = 0; // 0x0 + } + public final class DataFailCause { field @Deprecated public static final int VSNCP_APN_UNATHORIZED = 2238; // 0x8be } @@ -15597,6 +15623,75 @@ package android.telephony { field public static final int USER_NOT_MEMBER_OF_CUG = 87; // 0x57 } + @FlaggedApi("com.android.internal.telephony.flags.security_algorithms_update_indications") public final class SecurityAlgorithmUpdate implements android.os.Parcelable { + method public int describeContents(); + method public int getConnectionEvent(); + method public int getEncryption(); + method public int getIntegrity(); + method public boolean isUnprotectedEmergency(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field public static final int CONNECTION_EVENT_AS_SIGNALLING_5G = 11; // 0xb + field public static final int CONNECTION_EVENT_AS_SIGNALLING_LTE = 5; // 0x5 + field public static final int CONNECTION_EVENT_CS_SIGNALLING_3G = 2; // 0x2 + field public static final int CONNECTION_EVENT_CS_SIGNALLING_GSM = 0; // 0x0 + field public static final int CONNECTION_EVENT_NAS_SIGNALLING_5G = 10; // 0xa + field public static final int CONNECTION_EVENT_NAS_SIGNALLING_LTE = 4; // 0x4 + field public static final int CONNECTION_EVENT_PS_SIGNALLING_3G = 3; // 0x3 + field public static final int CONNECTION_EVENT_PS_SIGNALLING_GPRS = 1; // 0x1 + field public static final int CONNECTION_EVENT_VOLTE_RTP = 8; // 0x8 + field public static final int CONNECTION_EVENT_VOLTE_RTP_SOS = 9; // 0x9 + field public static final int CONNECTION_EVENT_VOLTE_SIP = 6; // 0x6 + field public static final int CONNECTION_EVENT_VOLTE_SIP_SOS = 7; // 0x7 + field public static final int CONNECTION_EVENT_VONR_RTP = 14; // 0xe + field public static final int CONNECTION_EVENT_VONR_RTP_SOS = 15; // 0xf + field public static final int CONNECTION_EVENT_VONR_SIP = 12; // 0xc + field public static final int CONNECTION_EVENT_VONR_SIP_SOS = 13; // 0xd + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SecurityAlgorithmUpdate> CREATOR; + field public static final int SECURITY_ALGORITHM_A50 = 0; // 0x0 + field public static final int SECURITY_ALGORITHM_A51 = 1; // 0x1 + field public static final int SECURITY_ALGORITHM_A52 = 2; // 0x2 + field public static final int SECURITY_ALGORITHM_A53 = 3; // 0x3 + field public static final int SECURITY_ALGORITHM_A54 = 4; // 0x4 + field public static final int SECURITY_ALGORITHM_AES_CBC = 71; // 0x47 + field public static final int SECURITY_ALGORITHM_AES_EDE3_CBC = 73; // 0x49 + field public static final int SECURITY_ALGORITHM_AES_GCM = 69; // 0x45 + field public static final int SECURITY_ALGORITHM_AES_GMAC = 70; // 0x46 + field public static final int SECURITY_ALGORITHM_AUTH_HMAC_SHA2_256_128 = 101; // 0x65 + field public static final int SECURITY_ALGORITHM_DES_EDE3_CBC = 72; // 0x48 + field public static final int SECURITY_ALGORITHM_EEA0 = 41; // 0x29 + field public static final int SECURITY_ALGORITHM_EEA1 = 42; // 0x2a + field public static final int SECURITY_ALGORITHM_EEA2 = 43; // 0x2b + field public static final int SECURITY_ALGORITHM_EEA3 = 44; // 0x2c + field public static final int SECURITY_ALGORITHM_ENCR_AES_CBC = 100; // 0x64 + field public static final int SECURITY_ALGORITHM_ENCR_AES_GCM_16 = 99; // 0x63 + field public static final int SECURITY_ALGORITHM_GEA0 = 14; // 0xe + field public static final int SECURITY_ALGORITHM_GEA1 = 15; // 0xf + field public static final int SECURITY_ALGORITHM_GEA2 = 16; // 0x10 + field public static final int SECURITY_ALGORITHM_GEA3 = 17; // 0x11 + field public static final int SECURITY_ALGORITHM_GEA4 = 18; // 0x12 + field public static final int SECURITY_ALGORITHM_GEA5 = 19; // 0x13 + field public static final int SECURITY_ALGORITHM_HMAC_MD5_96 = 75; // 0x4b + field public static final int SECURITY_ALGORITHM_HMAC_SHA1_96 = 74; // 0x4a + field public static final int SECURITY_ALGORITHM_IMS_NULL = 67; // 0x43 + field public static final int SECURITY_ALGORITHM_NEA0 = 55; // 0x37 + field public static final int SECURITY_ALGORITHM_NEA1 = 56; // 0x38 + field public static final int SECURITY_ALGORITHM_NEA2 = 57; // 0x39 + field public static final int SECURITY_ALGORITHM_NEA3 = 58; // 0x3a + field public static final int SECURITY_ALGORITHM_ORYX = 124; // 0x7c + field public static final int SECURITY_ALGORITHM_OTHER = 114; // 0x72 + field public static final int SECURITY_ALGORITHM_RTP = 85; // 0x55 + field public static final int SECURITY_ALGORITHM_SIP_NO_IPSEC_CONFIG = 66; // 0x42 + field public static final int SECURITY_ALGORITHM_SIP_NULL = 68; // 0x44 + field public static final int SECURITY_ALGORITHM_SRTP_AES_COUNTER = 87; // 0x57 + field public static final int SECURITY_ALGORITHM_SRTP_AES_F8 = 88; // 0x58 + field public static final int SECURITY_ALGORITHM_SRTP_HMAC_SHA1 = 89; // 0x59 + field public static final int SECURITY_ALGORITHM_SRTP_NULL = 86; // 0x56 + field public static final int SECURITY_ALGORITHM_UEA0 = 29; // 0x1d + field public static final int SECURITY_ALGORITHM_UEA1 = 30; // 0x1e + field public static final int SECURITY_ALGORITHM_UEA2 = 31; // 0x1f + field public static final int SECURITY_ALGORITHM_UNKNOWN = 113; // 0x71 + } + public class ServiceState implements android.os.Parcelable { method @Nullable public android.telephony.NetworkRegistrationInfo getNetworkRegistrationInfo(int, int); method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoListForDomain(int); @@ -15821,6 +15916,7 @@ package android.telephony { field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_CALL_FORWARDING_INDICATOR_CHANGED = 4; // 0x4 field public static final int EVENT_CALL_STATE_CHANGED = 6; // 0x6 field public static final int EVENT_CARRIER_NETWORK_CHANGED = 17; // 0x11 + field @FlaggedApi("com.android.internal.telephony.flags.cellular_identifier_disclosure_indications") @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int EVENT_CELLULAR_IDENTIFIER_DISCLOSED_CHANGED = 47; // 0x2f field @RequiresPermission(allOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public static final int EVENT_CELL_INFO_CHANGED = 11; // 0xb field @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public static final int EVENT_CELL_LOCATION_CHANGED = 5; // 0x5 field public static final int EVENT_DATA_ACTIVATION_STATE_CHANGED = 19; // 0x13 @@ -15845,6 +15941,7 @@ package android.telephony { field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED = 13; // 0xd field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int EVENT_RADIO_POWER_STATE_CHANGED = 24; // 0x18 field @RequiresPermission(allOf={android.Manifest.permission.READ_PRECISE_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public static final int EVENT_REGISTRATION_FAILURE = 31; // 0x1f + field @FlaggedApi("com.android.internal.telephony.flags.cellular_identifier_disclosure_indications") @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int EVENT_SECURITY_ALGORITHMS_CHANGED = 46; // 0x2e field public static final int EVENT_SERVICE_STATE_CHANGED = 1; // 0x1 field public static final int EVENT_SIGNAL_STRENGTHS_CHANGED = 9; // 0x9 field public static final int EVENT_SIGNAL_STRENGTH_CHANGED = 2; // 0x2 @@ -15863,6 +15960,10 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public default void onCallStatesChanged(@NonNull java.util.List<android.telephony.CallState>); } + @FlaggedApi("com.android.internal.telephony.flags.cellular_identifier_disclosure_indications") public static interface TelephonyCallback.CellularIdentifierDisclosedListener { + method public void onCellularIdentifierDisclosedChanged(@NonNull android.telephony.CellularIdentifierDisclosure); + } + public static interface TelephonyCallback.DataEnabledListener { method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onDataEnabledChanged(boolean, int); } @@ -15901,6 +16002,10 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void onRadioPowerStateChanged(int); } + @FlaggedApi("com.android.internal.telephony.flags.security_algorithms_update_indications") public static interface TelephonyCallback.SecurityAlgorithmsListener { + method public void onSecurityAlgorithmsChanged(@NonNull android.telephony.SecurityAlgorithmUpdate); + } + @FlaggedApi("com.android.internal.telephony.flags.simultaneous_calling_indications") public static interface TelephonyCallback.SimultaneousCellularCallingSupportListener { method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void onSimultaneousCellularCallingSubscriptionsChanged(@NonNull java.util.Set<java.lang.Integer>); } diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 8fd2cd55b8a8..44bcc2a737b9 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -3398,6 +3398,10 @@ package android.telephony { ctor public BarringInfo.BarringServiceInfo(int, boolean, int, int); } + @FlaggedApi("com.android.internal.telephony.flags.cellular_identifier_disclosure_indications") public final class CellularIdentifierDisclosure implements android.os.Parcelable { + ctor public CellularIdentifierDisclosure(int, int, @NonNull String, boolean); + } + public class MbmsDownloadSession implements java.lang.AutoCloseable { field public static final String MBMS_DOWNLOAD_SERVICE_OVERRIDE_METADATA = "mbms-download-service-override"; } @@ -3425,6 +3429,10 @@ package android.telephony { ctor @Deprecated public PreciseDataConnectionState(int, int, int, @NonNull String, @Nullable android.net.LinkProperties, int); } + @FlaggedApi("com.android.internal.telephony.flags.security_algorithms_update_indications") public final class SecurityAlgorithmUpdate implements android.os.Parcelable { + ctor public SecurityAlgorithmUpdate(int, int, int, boolean); + } + public class ServiceState implements android.os.Parcelable { method public void addNetworkRegistrationInfo(android.telephony.NetworkRegistrationInfo); method public int getDataNetworkType(); diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java index 62820ad5a4d6..67f7bee4028e 100644 --- a/core/java/android/app/KeyguardManager.java +++ b/core/java/android/app/KeyguardManager.java @@ -18,6 +18,7 @@ package android.app; import android.Manifest; import android.annotation.CallbackExecutor; +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -52,7 +53,9 @@ import android.view.IOnKeyguardExitResult; import android.view.IWindowManager; import android.view.WindowManagerGlobal; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.policy.IDeviceLockedStateListener; import com.android.internal.policy.IKeyguardDismissCallback; import com.android.internal.policy.IKeyguardLockedStateListener; import com.android.internal.util.Preconditions; @@ -253,6 +256,26 @@ public class KeyguardManager { private final ArrayMap<KeyguardLockedStateListener, Executor> mKeyguardLockedStateListeners = new ArrayMap<>(); + private final IDeviceLockedStateListener mIDeviceLockedStateListener = + new IDeviceLockedStateListener.Stub() { + @Override + public void onDeviceLockedStateChanged(boolean isDeviceLocked) { + if (!Flags.deviceUnlockListener()) { + return; + } + synchronized (mDeviceLockedStateListeners) { + mDeviceLockedStateListeners.forEach((listener, executor) -> { + executor.execute( + () -> listener.onDeviceLockedStateChanged(isDeviceLocked)); + }); + } + } + }; + + @GuardedBy("mDeviceLockedStateListeners") + private final ArrayMap<DeviceLockedStateListener, Executor> + mDeviceLockedStateListeners = new ArrayMap<>(); + /** * Get an intent to prompt the user to confirm credentials (pin, pattern, password or biometrics * if enrolled) for the current user of the device. The caller is expected to launch this @@ -1370,4 +1393,77 @@ public class KeyguardManager { } } } + + + /** + * Listener for device locked state changes. + */ + @FunctionalInterface + @FlaggedApi(Flags.FLAG_DEVICE_UNLOCK_LISTENER) + public interface DeviceLockedStateListener { + /** + * Callback function that executes when the device locked state changes. + */ + void onDeviceLockedStateChanged(boolean isDeviceLocked); + } + + + /** + * Registers a listener to execute when the device locked state changes. + * + * @param executor The {@link Executor} where the {@code listener} will be invoked + * @param listener The listener to add to receive device locked state changes. + * + * @see #isDeviceLocked() + * @see #removeDeviceLockedStateListener(DeviceLockedStateListener) + */ + @RequiresPermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE) + @FlaggedApi(Flags.FLAG_DEVICE_UNLOCK_LISTENER) + public void addDeviceLockedStateListener(@NonNull @CallbackExecutor Executor executor, + @NonNull DeviceLockedStateListener listener) { + if (!Flags.deviceUnlockListener()) { + return; + } + + synchronized (mDeviceLockedStateListeners) { + mDeviceLockedStateListeners.put(listener, executor); + if (mDeviceLockedStateListeners.size() > 1) { + return; + } + try { + mTrustManager.registerDeviceLockedStateListener(mIDeviceLockedStateListener, + mContext.getDeviceId()); + } catch (RemoteException re) { + Log.d(TAG, "TrustManager service died", re); + } + } + } + + /** + * Unregisters a listener that executes when the device locked state changes. + * + * @param listener The listener to remove. + * + * @see #isDeviceLocked() + * @see #addDeviceLockedStateListener(Executor, DeviceLockedStateListener) + */ + @RequiresPermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE) + @FlaggedApi(Flags.FLAG_DEVICE_UNLOCK_LISTENER) + public void removeDeviceLockedStateListener(@NonNull DeviceLockedStateListener listener) { + if (!Flags.deviceUnlockListener()) { + return; + } + + synchronized (mDeviceLockedStateListeners) { + mDeviceLockedStateListeners.remove(listener); + if (!mDeviceLockedStateListeners.isEmpty()) { + return; + } + try { + mTrustManager.unregisterDeviceLockedStateListener(mIDeviceLockedStateListener); + } catch (RemoteException re) { + Log.d(TAG, "TrustManager service died", re); + } + } + } } diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index cfe0ff9440e7..1c23ec799599 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -9520,7 +9520,6 @@ public class Notification implements Parcelable contentView.setViewVisibility(R.id.icon, View.GONE); contentView.setViewVisibility(R.id.conversation_face_pile, View.GONE); contentView.setViewVisibility(R.id.conversation_icon, View.VISIBLE); - contentView.setBoolean(R.id.conversation_icon, "setApplyCircularCrop", true); contentView.setImageViewIcon(R.id.conversation_icon, conversationIcon); } else if (mIsGroupConversation) { contentView.setViewVisibility(R.id.icon, View.GONE); diff --git a/core/java/android/app/keyguard.aconfig b/core/java/android/app/keyguard.aconfig new file mode 100644 index 000000000000..9cd1c1579416 --- /dev/null +++ b/core/java/android/app/keyguard.aconfig @@ -0,0 +1,10 @@ +package: "android.app" +container: "system" + +flag { + namespace: "wallet_integration" + name: "device_unlock_listener" + is_exported: true + description: "Enable listener API for device unlock." + bug: "296195355" +}
\ No newline at end of file diff --git a/core/java/android/app/trust/ITrustManager.aidl b/core/java/android/app/trust/ITrustManager.aidl index 730bb73da3bb..ffa54881cb9d 100644 --- a/core/java/android/app/trust/ITrustManager.aidl +++ b/core/java/android/app/trust/ITrustManager.aidl @@ -18,6 +18,7 @@ package android.app.trust; import android.app.trust.ITrustListener; import android.hardware.biometrics.BiometricSourceType; +import com.android.internal.policy.IDeviceLockedStateListener; /** * System private API to comunicate with trust service. @@ -43,4 +44,8 @@ interface ITrustManager { boolean isActiveUnlockRunning(int userId); @EnforcePermission("ACCESS_FINE_LOCATION") boolean isInSignificantPlace(); + @EnforcePermission("SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE") + void registerDeviceLockedStateListener(in IDeviceLockedStateListener listener, int deviceId); + @EnforcePermission("SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE") + void unregisterDeviceLockedStateListener(in IDeviceLockedStateListener listener); } diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java index 1ef83cdf3f85..8c8970ea5834 100644 --- a/core/java/android/app/trust/TrustManager.java +++ b/core/java/android/app/trust/TrustManager.java @@ -31,6 +31,8 @@ import android.os.Message; import android.os.RemoteException; import android.util.ArrayMap; +import com.android.internal.policy.IDeviceLockedStateListener; + import java.util.ArrayList; import java.util.List; @@ -259,6 +261,35 @@ public class TrustManager { } /** + * Registers a listener for device lock state events. + * + * Requires the {@link android.Manifest.permission#SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE} + * permission. + */ + public void registerDeviceLockedStateListener(final IDeviceLockedStateListener listener, + int deviceId) { + try { + mService.registerDeviceLockedStateListener(listener, deviceId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Unregisters a listener for device lock state events. + * + * Requires the {@link android.Manifest.permission#SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE} + * permission. + */ + public void unregisterDeviceLockedStateListener(final IDeviceLockedStateListener listener) { + try { + mService.unregisterDeviceLockedStateListener(listener); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * @return whether {@param userId} has enabled and configured trust agents. Ignores short-term * unavailability of trust due to {@link LockPatternUtils.StrongAuthTracker}. */ diff --git a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java index e9e8578af787..05c8f31df5d6 100644 --- a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java +++ b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java @@ -537,6 +537,9 @@ public class ApkLiteParseUtils { hasBindDeviceAdminPermission); break; case TAG_USES_SDK_LIBRARY: + if (!android.content.pm.Flags.sdkDependencyInstaller()) { + break; + } String usesSdkLibName = parser.getAttributeValue( ANDROID_RES_NAMESPACE, "name"); long usesSdkLibVersionMajor = parser.getAttributeIntValue( diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java index 1df3b4332754..c16a510ed729 100644 --- a/core/java/android/telephony/PhoneStateListener.java +++ b/core/java/android/telephony/PhoneStateListener.java @@ -1712,6 +1712,15 @@ public class PhoneStateListener { @NonNull NtnSignalStrength ntnSignalStrength) { // not supported on the deprecated interface - Use TelephonyCallback instead } + + public final void onSecurityAlgorithmsChanged(SecurityAlgorithmUpdate update) { + // not supported on the deprecated interface - Use TelephonyCallback instead + } + + public final void onCellularIdentifierDisclosedChanged( + CellularIdentifierDisclosure disclosure) { + // not supported on the deprecated interface - Use TelephonyCallback instead + } } private void log(String s) { diff --git a/core/java/android/telephony/TelephonyCallback.java b/core/java/android/telephony/TelephonyCallback.java index 0d1dc4611343..2c585e640fdd 100644 --- a/core/java/android/telephony/TelephonyCallback.java +++ b/core/java/android/telephony/TelephonyCallback.java @@ -705,6 +705,28 @@ public class TelephonyCallback { public static final int EVENT_CARRIER_ROAMING_NTN_SIGNAL_STRENGTH_CHANGED = 45; /** + * Event for changes to mobile network ciphering algorithms. + * See {@link SecurityAlgorithmsListener#onSecurityAlgorithmsChanged} + * + * @hide + */ + @FlaggedApi(Flags.FLAG_CELLULAR_IDENTIFIER_DISCLOSURE_INDICATIONS) + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @SystemApi + public static final int EVENT_SECURITY_ALGORITHMS_CHANGED = 46; + + /** + * Event for updates to sensitive device identifier disclosures (IMSI, IMEI, unciphered SUCI). + * See {@link CellularIdentifierDisclosedListener#onCellularIdentifierDisclosedChanged} + * + * @hide + */ + @FlaggedApi(Flags.FLAG_CELLULAR_IDENTIFIER_DISCLOSURE_INDICATIONS) + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @SystemApi + public static final int EVENT_CELLULAR_IDENTIFIER_DISCLOSED_CHANGED = 47; + + /** * @hide */ @IntDef(prefix = {"EVENT_"}, value = { @@ -752,7 +774,9 @@ public class TelephonyCallback { EVENT_CARRIER_ROAMING_NTN_MODE_CHANGED, EVENT_CARRIER_ROAMING_NTN_ELIGIBLE_STATE_CHANGED, EVENT_CARRIER_ROAMING_NTN_AVAILABLE_SERVICES_CHANGED, - EVENT_CARRIER_ROAMING_NTN_SIGNAL_STRENGTH_CHANGED + EVENT_CARRIER_ROAMING_NTN_SIGNAL_STRENGTH_CHANGED, + EVENT_SECURITY_ALGORITHMS_CHANGED, + EVENT_CELLULAR_IDENTIFIER_DISCLOSED_CHANGED }) @Retention(RetentionPolicy.SOURCE) public @interface TelephonyEvent { @@ -1827,6 +1851,41 @@ public class TelephonyCallback { } /** + * Interface for CellularIdentifierDisclosedListener + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_CELLULAR_IDENTIFIER_DISCLOSURE_INDICATIONS) + public interface CellularIdentifierDisclosedListener { + /** + * Callback invoked when a device identifier (IMSI, IMEI, or unciphered SUCI) + * is disclosed over the network before a security context is established + * ("pre-authentication"). + * + * @param disclosure details of the identifier disclosure + * See {@link CellularIdentifierDisclosure} for more details + */ + void onCellularIdentifierDisclosedChanged(@NonNull CellularIdentifierDisclosure disclosure); + } + + /** + * Interface for SecurityAlgorithmsListener + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_SECURITY_ALGORITHMS_UPDATE_INDICATIONS) + public interface SecurityAlgorithmsListener { + /** + * Callback invoked when the most recently reported security algorithms has changed, + * per a specified connection event. + * + * @param securityAlgorithmUpdate details of the security algorithm update + * See {@link SecurityAlgorithmUpdate} for more details + */ + void onSecurityAlgorithmsChanged(@NonNull SecurityAlgorithmUpdate securityAlgorithmUpdate); + } + + /** * The callback methods need to be called on the handler thread where * this object was created. If the binder did that for us it'd be nice. * <p> @@ -2302,5 +2361,27 @@ public class TelephonyCallback { () -> listener.onCarrierRoamingNtnSignalStrengthChanged(ntnSignalStrength))); } + + public void onSecurityAlgorithmsChanged(SecurityAlgorithmUpdate update) { + if (!Flags.securityAlgorithmsUpdateIndications()) return; + + SecurityAlgorithmsListener listener = + (SecurityAlgorithmsListener) mTelephonyCallbackWeakRef.get(); + if (listener == null) return; + + Binder.withCleanCallingIdentity(() -> mExecutor.execute( + () -> listener.onSecurityAlgorithmsChanged(update))); + } + + public void onCellularIdentifierDisclosedChanged(CellularIdentifierDisclosure disclosure) { + if (!Flags.cellularIdentifierDisclosureIndications()) return; + + CellularIdentifierDisclosedListener listener = + (CellularIdentifierDisclosedListener) mTelephonyCallbackWeakRef.get(); + if (listener == null) return; + + Binder.withCleanCallingIdentity(() -> mExecutor.execute( + () -> listener.onCellularIdentifierDisclosedChanged(disclosure))); + } } } diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java index 90b0bb34c145..4ec429d0c4ad 100644 --- a/core/java/android/telephony/TelephonyRegistryManager.java +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -1154,6 +1154,40 @@ public class TelephonyRegistryManager { } } + /** + * Notify external listeners that the radio security algorithms have changed. + * @param slotIndex for the phone object that got updated + * @param subId for which the security algorithm changed + * @param update details of the security algorithm update + * @hide + */ + public void notifySecurityAlgorithmsChanged( + int slotIndex, int subId, SecurityAlgorithmUpdate update) { + try { + sRegistry.notifySecurityAlgorithmsChanged(slotIndex, subId, update); + } catch (RemoteException ex) { + // system server crash + throw ex.rethrowFromSystemServer(); + } + } + + /** + * Notify external listeners of a new cellular identifier disclosure change. + * @param slotIndex for the phone object that the disclosure applies to + * @param subId for which the disclosure applies to + * @param disclosure details of the identifier disclosure + * @hide + */ + public void notifyCellularIdentifierDisclosedChanged( + int slotIndex, int subId, CellularIdentifierDisclosure disclosure) { + try { + sRegistry.notifyCellularIdentifierDisclosedChanged(slotIndex, subId, disclosure); + } catch (RemoteException ex) { + // system server crash + throw ex.rethrowFromSystemServer(); + } + } + /** * Processes potential event changes from the provided {@link TelephonyCallback}. * @@ -1313,6 +1347,15 @@ public class TelephonyRegistryManager { eventList.add(TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_AVAILABLE_SERVICES_CHANGED); eventList.add(TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_SIGNAL_STRENGTH_CHANGED); } + + if (telephonyCallback instanceof TelephonyCallback.CellularIdentifierDisclosedListener) { + eventList.add(TelephonyCallback.EVENT_CELLULAR_IDENTIFIER_DISCLOSED_CHANGED); + } + + if (telephonyCallback instanceof TelephonyCallback.SecurityAlgorithmsListener) { + eventList.add(TelephonyCallback.EVENT_SECURITY_ALGORITHMS_CHANGED); + } + return eventList; } diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java index 5a28d5f7fc01..80ae3c3d4e73 100644 --- a/core/java/android/view/ScaleGestureDetector.java +++ b/core/java/android/view/ScaleGestureDetector.java @@ -437,16 +437,16 @@ public class ScaleGestureDetector { } } - /** - * Return whether the quick scale gesture, in which the user performs a double tap followed by a - * swipe, should perform scaling. {@see #setQuickScaleEnabled(boolean)}. - */ + /** + * Return whether the quick scale gesture, in which the user performs a double tap followed by a + * swipe, should perform scaling. {@see #setQuickScaleEnabled(boolean)}. + */ public boolean isQuickScaleEnabled() { return mQuickScaleEnabled; } /** - * Sets whether the associates {@link OnScaleGestureListener} should receive + * Sets whether the associated {@link OnScaleGestureListener} should receive * onScale callbacks when the user uses a stylus and presses the button. * Note that this is enabled by default if the app targets API 23 and newer. * diff --git a/core/java/com/android/internal/policy/IDeviceLockedStateListener.aidl b/core/java/com/android/internal/policy/IDeviceLockedStateListener.aidl new file mode 100644 index 000000000000..cc626f699d43 --- /dev/null +++ b/core/java/com/android/internal/policy/IDeviceLockedStateListener.aidl @@ -0,0 +1,21 @@ +/* + * 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.internal.policy; + +oneway interface IDeviceLockedStateListener { + void onDeviceLockedStateChanged(boolean isDeviceLocked); +}
\ No newline at end of file diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl index 0e85e046e1b6..bf8a56508f54 100644 --- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl +++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl @@ -20,6 +20,7 @@ import android.telephony.BarringInfo; import android.telephony.CallState; import android.telephony.CellIdentity; import android.telephony.CellInfo; +import android.telephony.CellularIdentifierDisclosure; import android.telephony.DataConnectionRealTimeInfo; import android.telephony.LinkCapacityEstimate; import android.telephony.TelephonyDisplayInfo; @@ -28,6 +29,7 @@ import android.telephony.PhysicalChannelConfig; import android.telephony.PreciseCallState; import android.telephony.PreciseDataConnectionState; import android.telephony.satellite.NtnSignalStrength; +import android.telephony.SecurityAlgorithmUpdate; import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.emergency.EmergencyNumber; @@ -87,4 +89,6 @@ oneway interface IPhoneStateListener { void onCarrierRoamingNtnEligibleStateChanged(in boolean eligible); void onCarrierRoamingNtnAvailableServicesChanged(in int[] availableServices); void onCarrierRoamingNtnSignalStrengthChanged(in NtnSignalStrength ntnSignalStrength); + void onSecurityAlgorithmsChanged(in SecurityAlgorithmUpdate update); + void onCellularIdentifierDisclosedChanged(in CellularIdentifierDisclosure disclosure); } diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl index 0f268d5de62b..a296fbd1cfe4 100644 --- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -23,6 +23,7 @@ import android.telephony.BarringInfo; import android.telephony.CallQuality; import android.telephony.CellIdentity; import android.telephony.CellInfo; +import android.telephony.CellularIdentifierDisclosure; import android.telephony.LinkCapacityEstimate; import android.telephony.TelephonyDisplayInfo; import android.telephony.ims.ImsReasonInfo; @@ -30,6 +31,7 @@ import android.telephony.PhoneCapability; import android.telephony.PhysicalChannelConfig; import android.telephony.PreciseDataConnectionState; import android.telephony.satellite.NtnSignalStrength; +import android.telephony.SecurityAlgorithmUpdate; import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.emergency.EmergencyNumber; @@ -132,4 +134,7 @@ interface ITelephonyRegistry { void removeSatelliteStateChangeListener(ISatelliteStateChangeListener listener, String pkg); void notifySatelliteStateChanged(boolean isEnabled); + void notifySecurityAlgorithmsChanged(int phoneId, int subId, in SecurityAlgorithmUpdate update); + void notifyCellularIdentifierDisclosedChanged( + int phoneId, int subId, in CellularIdentifierDisclosure disclosure); } diff --git a/core/java/com/android/internal/widget/NotificationProgressBar.java b/core/java/com/android/internal/widget/NotificationProgressBar.java index f2b36c3b9981..7a21275d611e 100644 --- a/core/java/com/android/internal/widget/NotificationProgressBar.java +++ b/core/java/com/android/internal/widget/NotificationProgressBar.java @@ -59,6 +59,8 @@ import java.util.TreeSet; public final class NotificationProgressBar extends ProgressBar { private static final String TAG = "NotificationProgressBar"; + private NotificationProgressDrawable mNotificationProgressDrawable; + private NotificationProgressModel mProgressModel; @Nullable @@ -94,6 +96,12 @@ public final class NotificationProgressBar extends ProgressBar { defStyleAttr, defStyleRes); + try { + mNotificationProgressDrawable = getNotificationProgressDrawable(); + } catch (IllegalStateException ex) { + Log.e(TAG, "Can't get NotificationProgressDrawable", ex); + } + // Supports setting the tracker in xml, but ProgressStyle notifications set/override it // via {@code setProgressTrackerIcon}. final Drawable tracker = a.getDrawable(R.styleable.NotificationProgressBar_tracker); @@ -131,11 +139,8 @@ public final class NotificationProgressBar extends ProgressBar { progressMax, mProgressModel.isStyledByProgress()); - try { - final NotificationProgressDrawable drawable = getNotificationProgressDrawable(); - drawable.setParts(mProgressDrawableParts); - } catch (IllegalStateException ex) { - Log.e(TAG, "Can't set parts because can't get NotificationProgressDrawable", ex); + if (mNotificationProgressDrawable != null) { + mNotificationProgressDrawable.setParts(mProgressDrawableParts); } setMax(progressMax); @@ -195,10 +200,6 @@ public final class NotificationProgressBar extends ProgressBar { } private void setTracker(@Nullable Drawable tracker) { - if (isIndeterminate() && tracker != null) { - return; - } - final boolean needUpdate = mTracker != null && tracker != mTracker; if (needUpdate) { mTracker.setCallback(null); @@ -222,6 +223,9 @@ public final class NotificationProgressBar extends ProgressBar { } mTracker = tracker; + if (mNotificationProgressDrawable != null) { + mNotificationProgressDrawable.setHasTrackerIcon(mTracker != null); + } configureTrackerBounds(); @@ -275,16 +279,6 @@ public final class NotificationProgressBar extends ProgressBar { } @Override - @RemotableViewMethod - public synchronized void setIndeterminate(boolean indeterminate) { - super.setIndeterminate(indeterminate); - - if (isIndeterminate()) { - setTracker(null); - } - } - - @Override protected boolean verifyDrawable(@NonNull Drawable who) { return who == mTracker || super.verifyDrawable(who); } @@ -421,6 +415,8 @@ public final class NotificationProgressBar extends ProgressBar { @Override protected synchronized void onDraw(Canvas canvas) { super.onDraw(canvas); + + if (isIndeterminate()) return; drawTracker(canvas); } diff --git a/core/java/com/android/internal/widget/NotificationProgressDrawable.java b/core/java/com/android/internal/widget/NotificationProgressDrawable.java index fb6937c94a3e..e95225eede99 100644 --- a/core/java/com/android/internal/widget/NotificationProgressDrawable.java +++ b/core/java/com/android/internal/widget/NotificationProgressDrawable.java @@ -23,7 +23,6 @@ import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; -import android.graphics.DashPathEffect; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.Rect; @@ -62,21 +61,15 @@ public final class NotificationProgressDrawable extends Drawable { private boolean mMutated; private final ArrayList<Part> mParts = new ArrayList<>(); + private boolean mHasTrackerIcon; private final RectF mSegRectF = new RectF(); private final Rect mPointRect = new Rect(); private final RectF mPointRectF = new RectF(); - private final Paint mStrokePaint = new Paint(); - private final Paint mDashedStrokePaint = new Paint(); private final Paint mFillPaint = new Paint(); { - mStrokePaint.setStyle(Paint.Style.STROKE); - mStrokePaint.setStrokeCap(Paint.Cap.ROUND); - - mDashedStrokePaint.setStyle(Paint.Style.STROKE); - mFillPaint.setStyle(Paint.Style.FILL); } @@ -87,49 +80,15 @@ public final class NotificationProgressDrawable extends Drawable { } /** - * <p>Set the stroke width and default color for the drawable.</p> - * <p>Note: changing this property will affect all instances of a drawable loaded from a - * resource. It is recommended to invoke - * {@link #mutate()} before changing this property.</p> - * - * @param width The width in pixels of the stroke - * @param color The color of the stroke - * @see #mutate() - * @see #setStroke(int, int, float, float) - */ - public void setStroke(int width, @ColorInt int color) { - setStroke(width, color, 0, 0); - } - - /** - * <p>Set the stroke width and default color for the drawable. This method can also be used - * to dash the stroke for the dashed segments.</p> - * <p>Note: changing this property will affect all instances of a drawable loaded from a - * resource. It is recommended to invoke {@link #mutate()} before changing this property.</p> - * - * @param width The width in pixels of the stroke - * @param color The color of the stroke - * @param dashWidth The length in pixels of the dashes, set to 0 to disable dashes - * @param dashGap The gap in pixels between dashes - * @see #mutate() - * @see #setStroke(int, int) - */ - public void setStroke(int width, @ColorInt int color, float dashWidth, float dashGap) { - mState.setStroke(width, color, dashWidth, dashGap); - setStrokeInternal(width, dashWidth, dashGap); - } - - /** - * <p>Set the stroke default color for the drawable.</p> + * <p>Set the segment default color for the drawable.</p> * <p>Note: changing this property will affect all instances of a drawable loaded from a * resource. It is recommended to invoke {@link #mutate()} before changing this property.</p> * * @param color The color of the stroke * @see #mutate() - * @see #setStroke(int, int, float, float) */ - public void setStrokeDefaultColor(@ColorInt int color) { - mState.setStrokeColor(color); + public void setSegmentDefaultColor(@ColorInt int color) { + mState.setSegmentColor(color); } /** @@ -144,25 +103,14 @@ public final class NotificationProgressDrawable extends Drawable { mState.setPointRectColor(color); } - private void setStrokeInternal(int width, float dashWidth, float dashGap) { - mStrokePaint.setStrokeWidth(width); - - mDashedStrokePaint.setStrokeWidth(width); - DashPathEffect e = null; - if (dashWidth > 0) { - e = new DashPathEffect(new float[] { dashWidth, dashGap }, 0); - } - mDashedStrokePaint.setPathEffect(e); - - invalidateSelf(); - } - /** * Set the segments and points that constitute the drawable. */ public void setParts(List<Part> parts) { mParts.clear(); mParts.addAll(parts); + + invalidateSelf(); } /** @@ -172,6 +120,16 @@ public final class NotificationProgressDrawable extends Drawable { setParts(Arrays.asList(parts)); } + /** + * Set whether a tracker is drawn on top of this NotificationProgressDrawable. + */ + public void setHasTrackerIcon(boolean hasTrackerIcon) { + if (mHasTrackerIcon != hasTrackerIcon) { + mHasTrackerIcon = hasTrackerIcon; + invalidateSelf(); + } + } + @Override public void draw(@NonNull Canvas canvas) { final float pointRadius = @@ -181,6 +139,7 @@ public final class NotificationProgressDrawable extends Drawable { float x = (float) getBounds().left; final float centerY = (float) getBounds().centerY(); final float totalWidth = (float) getBounds().width(); + float segPointGap = mState.mSegPointGap; final int numParts = mParts.size(); for (int iPart = 0; iPart < numParts; iPart++) { @@ -188,15 +147,19 @@ public final class NotificationProgressDrawable extends Drawable { final Part prevPart = iPart == 0 ? null : mParts.get(iPart - 1); final Part nextPart = iPart + 1 == numParts ? null : mParts.get(iPart + 1); if (part instanceof Segment segment) { + // Update the segment-point gap to 2X upon seeing the first faded segment. + // (Assuming that all segments before are solid, and all segments after are faded.) + if (segment.mFaded) { + segPointGap = mState.mSegPointGap * 2; + } final float segWidth = segment.mFraction * totalWidth; // Advance the start position to account for a point immediately prior. - final float startOffset = getSegStartOffset(prevPart, pointRadius, - mState.mSegPointGap, x); + final float startOffset = getSegStartOffset(prevPart, pointRadius, segPointGap, x); final float start = x + startOffset; // Retract the end position to account for the padding and a point immediately // after. - final float endOffset = getSegEndOffset(nextPart, pointRadius, mState.mSegPointGap, - mState.mSegSegGap, x + segWidth, totalWidth); + final float endOffset = getSegEndOffset(segment, nextPart, pointRadius, segPointGap, + mState.mSegSegGap, x + segWidth, totalWidth, mHasTrackerIcon); final float end = x + segWidth - endOffset; // Advance the current position to account for the segment's fraction of the total @@ -206,35 +169,15 @@ public final class NotificationProgressDrawable extends Drawable { // No space left to draw the segment if (start > end) continue; - if (segment.mDashed) { - // No caps when the segment is dashed. - - mDashedStrokePaint.setColor(segment.mColor != Color.TRANSPARENT ? segment.mColor - : mState.mFadedStrokeColor); - canvas.drawLine(start, centerY, end, centerY, mDashedStrokePaint); - } else if (end - start < mState.mStrokeWidth) { - // Not enough segment length to draw the caps - - final float rad = (end - start) / 2F; - final float capWidth = mStrokePaint.getStrokeWidth() / 2F; - - mFillPaint.setColor(segment.mColor != Color.TRANSPARENT ? segment.mColor - : mState.mStrokeColor); - - mSegRectF.set(start, centerY - capWidth, end, centerY + capWidth); - canvas.drawRoundRect(mSegRectF, rad, rad, mFillPaint); - } else { - // Leave space for the rounded line cap which extends beyond start/end. - final float capWidth = mStrokePaint.getStrokeWidth() / 2F; + final float radiusY = segment.mFaded ? mState.mFadedSegmentHeight / 2F + : mState.mSegmentHeight / 2F; + final float cornerRadius = mState.mSegmentCornerRadius; - // Transparent is not allowed (and also is the default in the data), so use that - // as a sentinel to be replaced by default - mStrokePaint.setColor(segment.mColor != Color.TRANSPARENT ? segment.mColor - : mState.mStrokeColor); + mFillPaint.setColor(segment.mColor != Color.TRANSPARENT ? segment.mColor + : (segment.mFaded ? mState.mFadedSegmentColor : mState.mSegmentColor)); - canvas.drawLine(start + capWidth, centerY, end - capWidth, centerY, - mStrokePaint); - } + mSegRectF.set(start, centerY - radiusY, end, centerY + radiusY); + canvas.drawRoundRect(mSegRectF, cornerRadius, cornerRadius, mFillPaint); } else if (part instanceof Point point) { final float pointWidth = 2 * pointRadius; float start = x - pointRadius; @@ -275,10 +218,17 @@ public final class NotificationProgressDrawable extends Drawable { return pointOffset + pointRadius + segPointGap; } - private static float getSegEndOffset(Part nextPart, float pointRadius, float segPointGap, - float segSegGap, float endX, float totalWidth) { + private static float getSegEndOffset(Segment seg, Part nextPart, float pointRadius, + float segPointGap, + float segSegGap, float endX, float totalWidth, boolean hasTrackerIcon) { if (nextPart == null) return 0F; - if (!(nextPart instanceof Point)) return segSegGap; + if (nextPart instanceof Segment nextSeg) { + if (!seg.mFaded && nextSeg.mFaded) { + // @see Segment#mFaded + return hasTrackerIcon ? 0F : segSegGap * 4F; + } + return segSegGap; + } final float pointWidth = 2 * pointRadius; final float pointOffset = (endX + pointRadius > totalWidth && totalWidth > pointWidth) @@ -439,21 +389,17 @@ public final class NotificationProgressDrawable extends Drawable { // Extract the theme attributes, if any. state.mThemeAttrsSegments = a.extractThemeAttrs(); - final int width = a.getDimensionPixelSize( - R.styleable.NotificationProgressDrawableSegments_width, state.mStrokeWidth); - final float dashWidth = a.getDimension( - R.styleable.NotificationProgressDrawableSegments_dashWidth, state.mStrokeDashWidth); - + state.mSegmentHeight = a.getDimension( + R.styleable.NotificationProgressDrawableSegments_height, state.mSegmentHeight); + state.mFadedSegmentHeight = a.getDimension( + R.styleable.NotificationProgressDrawableSegments_fadedHeight, + state.mFadedSegmentHeight); + state.mSegmentCornerRadius = a.getDimension( + R.styleable.NotificationProgressDrawableSegments_cornerRadius, + state.mSegmentCornerRadius); final int color = a.getColor(R.styleable.NotificationProgressDrawableSegments_color, - state.mStrokeColor); - - if (dashWidth != 0.0f) { - final float dashGap = a.getDimension( - R.styleable.NotificationProgressDrawableSegments_dashGap, state.mStrokeDashGap); - setStroke(width, color, dashWidth, dashGap); - } else { - setStroke(width, color); - } + state.mSegmentColor); + setSegmentDefaultColor(color); } private void updatePointsFromTypedArray(TypedArray a) { @@ -532,11 +478,24 @@ public final class NotificationProgressDrawable extends Drawable { /** * A segment is a part of the progress bar with non-zero length. For example, it can * represent a portion in a navigation journey with certain traffic condition. + * */ public static final class Segment implements Part { private final float mFraction; @ColorInt private final int mColor; - private final boolean mDashed; + /** Whether the segment is faded or not. + * <p> + * <pre> + * When mFaded is set to true, a combination of the following is done to the segment: + * 1. The drawing color is mColor with opacity updated to 15%. + * 2. The segment-point gap is 2X the segment-point gap for non-faded segments. + * 3. The gap between faded and non-faded segments is: + * 4X the segment-segment gap, when there is no tracker icon + * 0, when there is tracker icon + * </pre> + * </p> + */ + private final boolean mFaded; public Segment(float fraction) { this(fraction, Color.TRANSPARENT); @@ -546,10 +505,10 @@ public final class NotificationProgressDrawable extends Drawable { this(fraction, color, false); } - public Segment(float fraction, @ColorInt int color, boolean dashed) { + public Segment(float fraction, @ColorInt int color, boolean faded) { mFraction = fraction; mColor = color; - mDashed = dashed; + mFaded = faded; } public float getFraction() { @@ -560,14 +519,14 @@ public final class NotificationProgressDrawable extends Drawable { return this.mColor; } - public boolean getDashed() { - return this.mDashed; + public boolean getFaded() { + return this.mFaded; } @Override public String toString() { - return "Segment(fraction=" + this.mFraction + ", color=" + this.mColor + ", dashed=" - + this.mDashed + ')'; + return "Segment(fraction=" + this.mFraction + ", color=" + this.mColor + ", faded=" + + this.mFaded + ')'; } // Needed for unit tests @@ -580,12 +539,12 @@ public final class NotificationProgressDrawable extends Drawable { Segment that = (Segment) other; if (Float.compare(this.mFraction, that.mFraction) != 0) return false; if (this.mColor != that.mColor) return false; - return this.mDashed == that.mDashed; + return this.mFaded == that.mFaded; } @Override public int hashCode() { - return Objects.hash(mFraction, mColor, mDashed); + return Objects.hash(mFraction, mColor, mFaded); } } @@ -675,11 +634,11 @@ public final class NotificationProgressDrawable extends Drawable { int mChangingConfigurations; float mSegSegGap = 0.0f; float mSegPointGap = 0.0f; - int mStrokeWidth = 0; - int mStrokeColor; - int mFadedStrokeColor; - float mStrokeDashWidth = 0.0f; - float mStrokeDashGap = 0.0f; + float mSegmentHeight; + float mFadedSegmentHeight; + float mSegmentCornerRadius; + int mSegmentColor; + int mFadedSegmentColor; float mPointRadius; float mPointRectInset; float mPointRectCornerRadius; @@ -699,11 +658,11 @@ public final class NotificationProgressDrawable extends Drawable { mChangingConfigurations = orig.mChangingConfigurations; mSegSegGap = orig.mSegSegGap; mSegPointGap = orig.mSegPointGap; - mStrokeWidth = orig.mStrokeWidth; - mStrokeColor = orig.mStrokeColor; - mFadedStrokeColor = orig.mFadedStrokeColor; - mStrokeDashWidth = orig.mStrokeDashWidth; - mStrokeDashGap = orig.mStrokeDashGap; + mSegmentHeight = orig.mSegmentHeight; + mFadedSegmentHeight = orig.mFadedSegmentHeight; + mSegmentCornerRadius = orig.mSegmentCornerRadius; + mSegmentColor = orig.mSegmentColor; + mFadedSegmentColor = orig.mFadedSegmentColor; mPointRadius = orig.mPointRadius; mPointRectInset = orig.mPointRectInset; mPointRectCornerRadius = orig.mPointRectCornerRadius; @@ -721,17 +680,17 @@ public final class NotificationProgressDrawable extends Drawable { } private void applyDensityScaling(int sourceDensity, int targetDensity) { - if (mStrokeWidth > 0) { - mStrokeWidth = scaleFromDensity( - mStrokeWidth, sourceDensity, targetDensity, true); + if (mSegmentHeight > 0) { + mSegmentHeight = scaleFromDensity( + mSegmentHeight, sourceDensity, targetDensity); } - if (mStrokeDashWidth > 0) { - mStrokeDashWidth = scaleFromDensity( - mStrokeDashWidth, sourceDensity, targetDensity); + if (mFadedSegmentHeight > 0) { + mFadedSegmentHeight = scaleFromDensity( + mFadedSegmentHeight, sourceDensity, targetDensity); } - if (mStrokeDashGap > 0) { - mStrokeDashGap = scaleFromDensity( - mStrokeDashGap, sourceDensity, targetDensity); + if (mSegmentCornerRadius > 0) { + mSegmentCornerRadius = scaleFromDensity( + mSegmentCornerRadius, sourceDensity, targetDensity); } if (mPointRadius > 0) { mPointRadius = scaleFromDensity( @@ -788,17 +747,9 @@ public final class NotificationProgressDrawable extends Drawable { } } - public void setStroke(int width, int color, float dashWidth, float dashGap) { - mStrokeWidth = width; - mStrokeDashWidth = dashWidth; - mStrokeDashGap = dashGap; - - setStrokeColor(color); - } - - public void setStrokeColor(int color) { - mStrokeColor = color; - mFadedStrokeColor = getFadedColor(color); + public void setSegmentColor(int color) { + mSegmentColor = color; + mFadedSegmentColor = getFadedColor(color); } public void setPointRectColor(int color) { @@ -808,11 +759,14 @@ public final class NotificationProgressDrawable extends Drawable { } /** - * Get a color with an opacity that's 50% of the input color. + * Get a color with an opacity that's 25% of the input color. */ @ColorInt static int getFadedColor(@ColorInt int color) { - return Color.argb(Color.alpha(color) / 2, Color.red(color), Color.green(color), + return Color.argb( + (int) (Color.alpha(color) * 0.25f + 0.5f), + Color.red(color), + Color.green(color), Color.blue(color)); } @@ -836,15 +790,6 @@ public final class NotificationProgressDrawable extends Drawable { } private void updateLocalState() { - final State state = mState; - - mStrokePaint.setStrokeWidth(state.mStrokeWidth); - mDashedStrokePaint.setStrokeWidth(state.mStrokeWidth); - - if (state.mStrokeDashWidth != 0.0f) { - final DashPathEffect e = new DashPathEffect( - new float[] { state.mStrokeDashWidth, state.mStrokeDashGap }, 0); - mDashedStrokePaint.setPathEffect(e); - } + // NO-OP } } diff --git a/core/java/com/android/internal/widget/NotificationRowIconView.java b/core/java/com/android/internal/widget/NotificationRowIconView.java index 5fc61b00e331..c96e979138dd 100644 --- a/core/java/com/android/internal/widget/NotificationRowIconView.java +++ b/core/java/com/android/internal/widget/NotificationRowIconView.java @@ -19,12 +19,7 @@ package com.android.internal.widget; import android.annotation.Nullable; import android.app.Flags; import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapShader; -import android.graphics.Canvas; -import android.graphics.Paint; import android.graphics.Rect; -import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.util.AttributeSet; @@ -41,7 +36,6 @@ import android.widget.RemoteViews; public class NotificationRowIconView extends CachingIconView { private NotificationIconProvider mIconProvider; - private boolean mApplyCircularCrop = false; private Drawable mAppIcon = null; // Padding, background and colors set on the view prior to being overridden when showing the app @@ -221,84 +215,6 @@ public class NotificationRowIconView extends CachingIconView { } } - @Nullable - @Override - Drawable loadSizeRestrictedIcon(@Nullable Icon icon) { - final Drawable original = super.loadSizeRestrictedIcon(icon); - final Drawable result; - if (mApplyCircularCrop) { - result = makeCircularDrawable(original); - } else { - result = original; - } - - return result; - } - - /** - * Enables circle crop that makes given image circular - */ - @RemotableViewMethod(asyncImpl = "setApplyCircularCropAsync") - public void setApplyCircularCrop(boolean applyCircularCrop) { - mApplyCircularCrop = applyCircularCrop; - } - - /** - * Async version of {@link NotificationRowIconView#setApplyCircularCrop} - */ - public Runnable setApplyCircularCropAsync(boolean applyCircularCrop) { - mApplyCircularCrop = applyCircularCrop; - return () -> { - }; - } - - @Nullable - private Drawable makeCircularDrawable(@Nullable Drawable original) { - if (original == null) { - return original; - } - - final Bitmap source = drawableToBitmap(original); - - int size = Math.min(source.getWidth(), source.getHeight()); - - Bitmap squared = Bitmap.createScaledBitmap(source, size, size, /* filter= */ false); - Bitmap result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); - - final Canvas canvas = new Canvas(result); - final Paint paint = new Paint(); - paint.setShader( - new BitmapShader(squared, BitmapShader.TileMode.CLAMP, - BitmapShader.TileMode.CLAMP)); - paint.setAntiAlias(true); - float radius = size / 2f; - canvas.drawCircle(radius, radius, radius, paint); - return new BitmapDrawable(getResources(), result); - } - - private static Bitmap drawableToBitmap(Drawable drawable) { - if (drawable instanceof BitmapDrawable bitmapDrawable) { - final Bitmap bitmap = bitmapDrawable.getBitmap(); - if (bitmap.getConfig() == Bitmap.Config.HARDWARE) { - return bitmap.copy(Bitmap.Config.ARGB_8888, false); - } else { - return bitmap; - } - } - - int width = drawable.getIntrinsicWidth(); - width = width > 0 ? width : 1; - int height = drawable.getIntrinsicHeight(); - height = height > 0 ? height : 1; - - Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(bitmap); - drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); - drawable.draw(canvas); - - return bitmap; - } - /** * A provider that allows this view to verify whether it should use the app icon instead of the * icon provided to it via setImageIcon, as well as actually fetching the app icon. It should diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp index f9d00edce3fa..5a183925e38e 100644 --- a/core/jni/android_media_AudioRecord.cpp +++ b/core/jni/android_media_AudioRecord.cpp @@ -584,14 +584,23 @@ static jboolean android_media_AudioRecord_setInputDevice( return lpRecorder->setInputDevice(device_id) == NO_ERROR; } -static jint android_media_AudioRecord_getRoutedDeviceId( - JNIEnv *env, jobject thiz) { - +static jintArray android_media_AudioRecord_getRoutedDeviceIds(JNIEnv *env, jobject thiz) { sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz); - if (lpRecorder == 0) { - return 0; + if (lpRecorder == NULL) { + return NULL; + } + DeviceIdVector deviceIds = lpRecorder->getRoutedDeviceIds(); + jintArray result; + result = env->NewIntArray(deviceIds.size()); + if (result == NULL) { + return NULL; + } + jint *values = env->GetIntArrayElements(result, 0); + for (unsigned int i = 0; i < deviceIds.size(); i++) { + values[i++] = static_cast<jint>(deviceIds[i]); } - return (jint)lpRecorder->getRoutedDeviceId(); + env->ReleaseIntArrayElements(result, values, 0); + return result; } // Enable and Disable Callback methods are synchronized on the Java side @@ -821,8 +830,7 @@ static const JNINativeMethod gMethods[] = { // name, signature, funcPtr {"native_start", "(II)I", (void *)android_media_AudioRecord_start}, {"native_stop", "()V", (void *)android_media_AudioRecord_stop}, - {"native_setup", - "(Ljava/lang/Object;Ljava/lang/Object;[IIIII[ILandroid/os/Parcel;JII)I", + {"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;[IIIII[ILandroid/os/Parcel;JII)I", (void *)android_media_AudioRecord_setup}, {"native_finalize", "()V", (void *)android_media_AudioRecord_finalize}, {"native_release", "()V", (void *)android_media_AudioRecord_release}, @@ -846,7 +854,7 @@ static const JNINativeMethod gMethods[] = { {"native_getMetrics", "()Landroid/os/PersistableBundle;", (void *)android_media_AudioRecord_native_getMetrics}, {"native_setInputDevice", "(I)Z", (void *)android_media_AudioRecord_setInputDevice}, - {"native_getRoutedDeviceId", "()I", (void *)android_media_AudioRecord_getRoutedDeviceId}, + {"native_getRoutedDeviceIds", "()[I", (void *)android_media_AudioRecord_getRoutedDeviceIds}, {"native_enableDeviceCallback", "()V", (void *)android_media_AudioRecord_enableDeviceCallback}, {"native_disableDeviceCallback", "()V", diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp index 1557f9ed47a5..5d4d1ce20e5d 100644 --- a/core/jni/android_media_AudioTrack.cpp +++ b/core/jni/android_media_AudioTrack.cpp @@ -1190,15 +1190,23 @@ static jboolean android_media_AudioTrack_setOutputDevice( } return lpTrack->setOutputDevice(device_id) == NO_ERROR; } - -static jint android_media_AudioTrack_getRoutedDeviceId( - JNIEnv *env, jobject thiz) { - +static jintArray android_media_AudioTrack_getRoutedDeviceIds(JNIEnv *env, jobject thiz) { sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); if (lpTrack == NULL) { - return 0; + return NULL; + } + DeviceIdVector deviceIds = lpTrack->getRoutedDeviceIds(); + jintArray result; + result = env->NewIntArray(deviceIds.size()); + if (result == NULL) { + return NULL; + } + jint *values = env->GetIntArrayElements(result, 0); + for (unsigned int i = 0; i < deviceIds.size(); i++) { + values[i++] = static_cast<jint>(deviceIds[i]); } - return (jint)lpTrack->getRoutedDeviceId(); + env->ReleaseIntArrayElements(result, values, 0); + return result; } static void android_media_AudioTrack_enableDeviceCallback( @@ -1503,7 +1511,7 @@ static const JNINativeMethod gMethods[] = { (void *)android_media_AudioTrack_setAuxEffectSendLevel}, {"native_attachAuxEffect", "(I)I", (void *)android_media_AudioTrack_attachAuxEffect}, {"native_setOutputDevice", "(I)Z", (void *)android_media_AudioTrack_setOutputDevice}, - {"native_getRoutedDeviceId", "()I", (void *)android_media_AudioTrack_getRoutedDeviceId}, + {"native_getRoutedDeviceIds", "()[I", (void *)android_media_AudioTrack_getRoutedDeviceIds}, {"native_enableDeviceCallback", "()V", (void *)android_media_AudioTrack_enableDeviceCallback}, {"native_disableDeviceCallback", "()V", diff --git a/core/jni/android_media_DeviceCallback.cpp b/core/jni/android_media_DeviceCallback.cpp index a1a035110caf..ccdf633c842a 100644 --- a/core/jni/android_media_DeviceCallback.cpp +++ b/core/jni/android_media_DeviceCallback.cpp @@ -61,21 +61,20 @@ JNIDeviceCallback::~JNIDeviceCallback() } void JNIDeviceCallback::onAudioDeviceUpdate(audio_io_handle_t audioIo, - audio_port_handle_t deviceId) -{ + const DeviceIdVector& deviceIds) { JNIEnv *env = AndroidRuntime::getJNIEnv(); if (env == NULL) { return; } - ALOGV("%s audioIo %d deviceId %d", __FUNCTION__, audioIo, deviceId); - env->CallStaticVoidMethod(mClass, - mPostEventFromNative, - mObject, - AUDIO_NATIVE_EVENT_ROUTING_CHANGE, deviceId, 0, NULL); + ALOGV("%s audioIo %d deviceIds %s", __FUNCTION__, audioIo, toString(deviceIds).c_str()); + // Java should query the new device ids once it gets the event. + // TODO(b/378505346): Pass the deviceIds to Java to avoid race conditions. + env->CallStaticVoidMethod(mClass, mPostEventFromNative, mObject, + AUDIO_NATIVE_EVENT_ROUTING_CHANGE, 0 /*arg1*/, 0 /*arg2*/, + NULL /*obj*/); if (env->ExceptionCheck()) { ALOGW("An exception occurred while notifying an event."); env->ExceptionClear(); } } - diff --git a/core/jni/android_media_DeviceCallback.h b/core/jni/android_media_DeviceCallback.h index 7ae788eaf058..0c9ccc89ba1a 100644 --- a/core/jni/android_media_DeviceCallback.h +++ b/core/jni/android_media_DeviceCallback.h @@ -31,8 +31,7 @@ public: JNIDeviceCallback(JNIEnv* env, jobject thiz, jobject weak_thiz, jmethodID postEventFromNative); ~JNIDeviceCallback(); - virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo, - audio_port_handle_t deviceId); + virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo, const DeviceIdVector& deviceIds); private: void sendEvent(int event); diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 00464056fd84..7fcbf19d137f 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -5587,7 +5587,8 @@ <permission android:name="android.permission.BIND_VISUAL_QUERY_DETECTION_SERVICE" android:protectionLevel="signature" /> - <!-- Allows an application to subscribe to keyguard locked (i.e., showing) state. + <!-- Allows an application to subscribe to device locked and keyguard locked (i.e., showing) + state. <p>Protection level: signature|role <p>Intended for use by ROLE_ASSISTANT and signature apps only. --> diff --git a/core/res/res/drawable/notification_progress.xml b/core/res/res/drawable/notification_progress.xml index 3a6b60077045..5d272fb00e34 100644 --- a/core/res/res/drawable/notification_progress.xml +++ b/core/res/res/drawable/notification_progress.xml @@ -24,9 +24,9 @@ android:segPointGap="@dimen/notification_progress_segPoint_gap"> <segments android:color="?attr/colorProgressBackgroundNormal" - android:dashGap="@dimen/notification_progress_segments_dash_gap" - android:dashWidth="@dimen/notification_progress_segments_dash_width" - android:width="@dimen/notification_progress_segments_height" /> + android:height="@dimen/notification_progress_segments_height" + android:fadedHeight="@dimen/notification_progress_segments_faded_height" + android:cornerRadius="@dimen/notification_progress_segments_corner_radius"/> <points android:color="?attr/colorProgressBackgroundNormal" android:radius="@dimen/notification_progress_points_radius" diff --git a/core/res/res/layout/notification_template_material_messaging_compact_heads_up.xml b/core/res/res/layout/notification_template_material_messaging_compact_heads_up.xml index 82920bad95cd..149a5a9568f2 100644 --- a/core/res/res/layout/notification_template_material_messaging_compact_heads_up.xml +++ b/core/res/res/layout/notification_template_material_messaging_compact_heads_up.xml @@ -34,12 +34,14 @@ android:maxDrawableWidth="@dimen/notification_icon_circle_size" android:maxDrawableHeight="@dimen/notification_icon_circle_size" /> - <com.android.internal.widget.NotificationRowIconView + <com.android.internal.widget.CachingIconView android:id="@+id/conversation_icon" android:layout_width="@dimen/notification_icon_circle_size" android:layout_height="@dimen/notification_icon_circle_size" android:layout_gravity="center_vertical|start" android:layout_marginStart="@dimen/notification_icon_circle_start" + android:background="@drawable/notification_icon_circle" + android:clipToOutline="true" android:maxDrawableWidth="@dimen/notification_icon_circle_size" android:maxDrawableHeight="@dimen/notification_icon_circle_size" android:scaleType="centerCrop" diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 471b68e393ac..f6590b1360f8 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -7748,14 +7748,14 @@ <!-- Used to config the segments of a NotificationProgressDrawable. --> <!-- @hide internal use only --> <declare-styleable name="NotificationProgressDrawableSegments"> - <!-- Width of the stroke. --> - <attr name="width" /> - <!-- Default color of the stroke. --> + <!-- Height of the solid segments --> + <attr name="height" /> + <!-- Height of the faded segments --> + <attr name="fadedHeight" format="dimension"/> + <!-- Corner radius of the segment rect. --> + <attr name="cornerRadius" format="dimension" /> + <!-- Default color of the segment. --> <attr name="color" /> - <!-- Length of a dash in the stroke for the dashed segments. --> - <attr name="dashWidth" /> - <!-- Gap between dashes in the stroke for the dashed segments. --> - <attr name="dashGap" /> </declare-styleable> <!-- Used to config the points of a NotificationProgressDrawable. --> @@ -7766,7 +7766,7 @@ <!-- Inset of the point icon or rect. --> <attr name="inset" /> <!-- Corner radius of the point rect. --> - <attr name="cornerRadius" format="dimension" /> + <attr name="cornerRadius"/> <!-- Default color of the point rect. --> <attr name="color" /> </declare-styleable> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 513555d0ff5c..375748786817 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -838,13 +838,13 @@ <!-- The gap between segments in the notification progress bar --> <dimen name="notification_progress_segSeg_gap">2dp</dimen> <!-- The gap between a segment and a point in the notification progress bar --> - <dimen name="notification_progress_segPoint_gap">8dp</dimen> - <!-- The dash gap of the notification progress bar segments --> - <dimen name="notification_progress_segments_dash_gap">8dp</dimen> - <!-- The dash width of the notification progress bar segments --> - <dimen name="notification_progress_segments_dash_width">3dp</dimen> + <dimen name="notification_progress_segPoint_gap">4dp</dimen> <!-- The height of the notification progress bar segments --> <dimen name="notification_progress_segments_height">6dp</dimen> + <!-- The height of the notification progress bar faded segments --> + <dimen name="notification_progress_segments_faded_height">2dp</dimen> + <!-- The corner radius of the notification progress bar segments --> + <dimen name="notification_progress_segments_corner_radius">16dp</dimen> <!-- The radius of the notification progress bar points --> <dimen name="notification_progress_points_radius">6dp</dimen> <!-- The corner radius of the notification progress bar points drawn as rects --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 0937eae7e6f0..a2a19a23d431 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3881,9 +3881,9 @@ <java-symbol type="dimen" name="notification_progress_tracker_height" /> <java-symbol type="dimen" name="notification_progress_segSeg_gap" /> <java-symbol type="dimen" name="notification_progress_segPoint_gap" /> - <java-symbol type="dimen" name="notification_progress_segments_dash_gap" /> - <java-symbol type="dimen" name="notification_progress_segments_dash_width" /> <java-symbol type="dimen" name="notification_progress_segments_height" /> + <java-symbol type="dimen" name="notification_progress_segments_faded_height" /> + <java-symbol type="dimen" name="notification_progress_segments_corner_radius" /> <java-symbol type="dimen" name="notification_progress_points_radius" /> <java-symbol type="dimen" name="notification_progress_points_corner_radius" /> <java-symbol type="dimen" name="notification_progress_points_inset" /> diff --git a/core/tests/coretests/src/android/content/pm/parsing/ApkLiteParseUtilsTest.java b/core/tests/coretests/src/android/content/pm/parsing/ApkLiteParseUtilsTest.java index 0db49a72c51d..ecacdb2bde0b 100644 --- a/core/tests/coretests/src/android/content/pm/parsing/ApkLiteParseUtilsTest.java +++ b/core/tests/coretests/src/android/content/pm/parsing/ApkLiteParseUtilsTest.java @@ -33,6 +33,7 @@ import android.content.pm.parsing.result.ParseTypeImpl; import android.os.FileUtils; import android.os.ParcelFileDescriptor; import android.platform.test.annotations.Presubmit; +import android.platform.test.annotations.RequiresFlagsEnabled; import android.util.ArraySet; import android.util.PackageUtils; @@ -61,6 +62,7 @@ import java.util.List; import java.util.Set; @Presubmit +@RequiresFlagsEnabled(android.content.pm.Flags.FLAG_SDK_DEPENDENCY_INSTALLER) public class ApkLiteParseUtilsTest { @Rule diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml index a18a2510f0f7..bfd9c818a96e 100644 --- a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml +++ b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml @@ -23,7 +23,7 @@ android:clipChildren="false" android:clipToPadding="false" android:paddingBottom="@dimen/desktop_mode_handle_menu_pill_elevation" - android:paddingRight="@dimen/desktop_mode_handle_menu_pill_elevation" + android:paddingEnd="@dimen/desktop_mode_handle_menu_pill_elevation" android:orientation="vertical"> <LinearLayout diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt index 54c247bff984..62be2c78d59b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt @@ -238,8 +238,12 @@ class HandleMenu( val taskBounds = taskInfo.getConfiguration().windowConfiguration.bounds updateGlobalMenuPosition(taskBounds, captionX, captionY) if (layoutResId == R.layout.desktop_mode_app_header) { - // Align the handle menu to the left side of the caption. - menuX = marginMenuStart + // Align the handle menu to the start of the header. + menuX = if (context.isRtl()) { + taskBounds.width() - menuWidth - marginMenuStart + } else { + marginMenuStart + } menuY = captionY + marginMenuTop } else { if (DesktopModeFlags.ENABLE_HANDLE_INPUT_FIX.isTrue()) { @@ -261,10 +265,17 @@ class HandleMenu( val nonFreeformX = captionX + (captionWidth / 2) - (menuWidth / 2) when { taskInfo.isFreeform -> { - globalMenuPosition.set( - /* x = */ taskBounds.left + marginMenuStart, - /* y = */ taskBounds.top + captionY + marginMenuTop - ) + if (context.isRtl()) { + globalMenuPosition.set( + /* x= */ taskBounds.right - menuWidth - marginMenuStart, + /* y= */ taskBounds.top + captionY + marginMenuTop + ) + } else { + globalMenuPosition.set( + /* x= */ taskBounds.left + marginMenuStart, + /* y= */ taskBounds.top + captionY + marginMenuTop + ) + } } taskInfo.isFullscreen -> { globalMenuPosition.set( @@ -430,6 +441,9 @@ class HandleMenu( return context.resources.getDimensionPixelSize(resourceId) } + private fun Context.isRtl() = + resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL + fun close() { handleMenuView?.animateCloseMenu { handleMenuViewContainer?.releaseView() diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt index a248303b1c33..fd4328dee0a1 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt @@ -16,16 +16,18 @@ package com.android.wm.shell.flicker.pip +import android.platform.test.annotations.FlakyTest import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit +import android.platform.test.annotations.RequiresDevice +import android.platform.test.annotations.RequiresFlagsDisabled import android.tools.flicker.junit.FlickerParametersRunnerFactory import android.tools.flicker.legacy.FlickerBuilder import android.tools.flicker.legacy.LegacyFlickerTest import android.tools.flicker.subject.exceptions.ExceptionMessageBuilder import android.tools.flicker.subject.exceptions.IncorrectRegionException import android.tools.flicker.subject.layers.LayerSubject -import androidx.test.filters.FlakyTest -import androidx.test.filters.RequiresDevice +import com.android.wm.shell.Flags import com.android.wm.shell.flicker.pip.common.EnterPipTransition import org.junit.Assume import org.junit.FixMethodOrder @@ -35,6 +37,7 @@ import org.junit.runners.MethodSorters import org.junit.runners.Parameterized import kotlin.math.abs + /** * Test entering pip from an app via auto-enter property when navigating to home. * @@ -60,6 +63,7 @@ import kotlin.math.abs @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) open class AutoEnterPipOnGoToHomeTest(flicker: LegacyFlickerTest) : EnterPipTransition(flicker) { override val thisTransition: FlickerBuilder.() -> Unit = { transitions { tapl.goHome() } } diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipWithSourceRectHintTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipWithSourceRectHintTest.kt index df952c925720..d4ad4ef8a401 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipWithSourceRectHintTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipWithSourceRectHintTest.kt @@ -17,10 +17,12 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit +import android.platform.test.annotations.RequiresFlagsDisabled import android.tools.flicker.junit.FlickerParametersRunnerFactory import android.tools.flicker.legacy.FlickerBuilder import android.tools.flicker.legacy.LegacyFlickerTest import android.tools.traces.component.ComponentNameMatcher +import com.android.wm.shell.Flags import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith @@ -52,6 +54,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) class AutoEnterPipWithSourceRectHintTest(flicker: LegacyFlickerTest) : AutoEnterPipOnGoToHomeTest(flicker) { override val defaultEnterPip: FlickerBuilder.() -> Unit = { diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt index 302b8c414979..cc6e4b5a90d5 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt @@ -17,6 +17,7 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit +import android.platform.test.annotations.RequiresFlagsDisabled import android.tools.flicker.junit.FlickerParametersRunnerFactory import android.tools.flicker.legacy.FlickerBuilder import android.tools.flicker.legacy.LegacyFlickerTest @@ -53,6 +54,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) class ClosePipBySwipingDownTest(flicker: LegacyFlickerTest) : ClosePipTransition(flicker) { override val thisTransition: FlickerBuilder.() -> Unit = { transitions { diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt index 77a1edb7039a..53725fa046c6 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt @@ -17,9 +17,11 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit +import android.platform.test.annotations.RequiresFlagsDisabled import android.tools.flicker.junit.FlickerParametersRunnerFactory import android.tools.flicker.legacy.FlickerBuilder import android.tools.flicker.legacy.LegacyFlickerTest +import com.android.wm.shell.Flags import com.android.wm.shell.flicker.pip.common.ClosePipTransition import org.junit.FixMethodOrder import org.junit.Test @@ -52,6 +54,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) class ClosePipWithDismissButtonTest(flicker: LegacyFlickerTest) : ClosePipTransition(flicker) { override val thisTransition: FlickerBuilder.() -> Unit = { transitions { pipApp.closePipWindow(wmHelper) } diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt index 6e32d6412b50..a1551b7924fe 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt @@ -17,9 +17,11 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit +import android.platform.test.annotations.RequiresFlagsDisabled import android.tools.flicker.junit.FlickerParametersRunnerFactory import android.tools.flicker.legacy.FlickerBuilder import android.tools.flicker.legacy.LegacyFlickerTest +import com.android.wm.shell.Flags import com.android.wm.shell.flicker.pip.common.EnterPipTransition import org.junit.Assume import org.junit.FixMethodOrder @@ -43,6 +45,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) class EnterPipOnUserLeaveHintTest(flicker: LegacyFlickerTest) : EnterPipTransition(flicker) { override val thisTransition: FlickerBuilder.() -> Unit = { transitions { tapl.goHome() } } diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt index 9a6cb61cfc66..ea5b3e5b08df 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt @@ -19,6 +19,7 @@ package com.android.wm.shell.flicker.pip import android.app.Activity import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit +import android.platform.test.annotations.RequiresFlagsDisabled import android.tools.Rotation import android.tools.flicker.assertions.FlickerTest import android.tools.flicker.junit.FlickerParametersRunnerFactory @@ -32,6 +33,7 @@ import com.android.server.wm.flicker.entireScreenCovered import com.android.server.wm.flicker.helpers.FixedOrientationAppHelper import com.android.server.wm.flicker.testapp.ActivityOptions.Pip.ACTION_ENTER_PIP import com.android.server.wm.flicker.testapp.ActivityOptions.PortraitOnlyActivity.EXTRA_FIXED_ORIENTATION +import com.android.wm.shell.Flags import com.android.wm.shell.flicker.pip.common.PipTransition import com.android.wm.shell.flicker.pip.common.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_LANDSCAPE import com.android.wm.shell.flicker.pip.common.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_PORTRAIT @@ -68,6 +70,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) class EnterPipToOtherOrientation(flicker: LegacyFlickerTest) : PipTransition(flicker) { private val testApp = FixedOrientationAppHelper(instrumentation) private val startingBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_90) diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt index 6b4751cee3bb..a109c4bba2b3 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt @@ -16,9 +16,11 @@ package com.android.wm.shell.flicker.pip +import android.platform.test.annotations.RequiresFlagsDisabled import android.tools.flicker.junit.FlickerParametersRunnerFactory import android.tools.flicker.legacy.FlickerBuilder import android.tools.flicker.legacy.LegacyFlickerTest +import com.android.wm.shell.Flags import com.android.wm.shell.flicker.pip.common.EnterPipTransition import org.junit.FixMethodOrder import org.junit.runner.RunWith @@ -49,6 +51,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) open class EnterPipViaAppUiButtonTest(flicker: LegacyFlickerTest) : EnterPipTransition(flicker) { override val thisTransition: FlickerBuilder.() -> Unit = { transitions { pipApp.clickEnterPipButton(wmHelper) } diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt index 8d0bc0f5a155..14ec303206ee 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt @@ -16,9 +16,11 @@ package com.android.wm.shell.flicker.pip +import android.platform.test.annotations.RequiresFlagsDisabled import android.tools.flicker.junit.FlickerParametersRunnerFactory import android.tools.flicker.legacy.FlickerBuilder import android.tools.flicker.legacy.LegacyFlickerTest +import com.android.wm.shell.Flags import com.android.wm.shell.flicker.pip.common.ExitPipToAppTransition import org.junit.FixMethodOrder import org.junit.runner.RunWith @@ -51,6 +53,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) class ExitPipToAppViaExpandButtonTest(flicker: LegacyFlickerTest) : ExitPipToAppTransition(flicker) { override val thisTransition: FlickerBuilder.() -> Unit = { diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt index 939f3280d2e6..8a34b5e27fdb 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt @@ -16,9 +16,11 @@ package com.android.wm.shell.flicker.pip +import android.platform.test.annotations.RequiresFlagsDisabled import android.tools.flicker.junit.FlickerParametersRunnerFactory import android.tools.flicker.legacy.FlickerBuilder import android.tools.flicker.legacy.LegacyFlickerTest +import com.android.wm.shell.Flags import com.android.wm.shell.flicker.pip.common.ExitPipToAppTransition import org.junit.FixMethodOrder import org.junit.runner.RunWith @@ -50,6 +52,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) class ExitPipToAppViaIntentTest(flicker: LegacyFlickerTest) : ExitPipToAppTransition(flicker) { override val thisTransition: FlickerBuilder.() -> Unit = { setup { diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt index 258663b5556d..4f189fc6190d 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt @@ -17,12 +17,14 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit +import android.platform.test.annotations.RequiresFlagsDisabled import android.tools.Rotation import android.tools.flicker.junit.FlickerParametersRunnerFactory import android.tools.flicker.legacy.FlickerBuilder import android.tools.flicker.legacy.LegacyFlickerTest import android.tools.flicker.legacy.LegacyFlickerTestFactory import android.tools.traces.component.ComponentNameMatcher +import com.android.wm.shell.Flags import com.android.wm.shell.flicker.pip.common.PipTransition import org.junit.FixMethodOrder import org.junit.Test @@ -54,6 +56,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) class ExpandPipOnDoubleClickTest(flicker: LegacyFlickerTest) : PipTransition(flicker) { override val thisTransition: FlickerBuilder.() -> Unit = { transitions { pipApp.doubleClickPipWindow(wmHelper) } diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt index 1964e3cebc89..4d72b03d0345 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt @@ -17,11 +17,13 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit +import android.platform.test.annotations.RequiresFlagsDisabled import android.tools.Rotation import android.tools.flicker.junit.FlickerParametersRunnerFactory import android.tools.flicker.legacy.FlickerBuilder import android.tools.flicker.legacy.LegacyFlickerTest import android.tools.flicker.legacy.LegacyFlickerTestFactory +import com.android.wm.shell.Flags import com.android.wm.shell.flicker.pip.common.PipTransition import org.junit.FixMethodOrder import org.junit.Test @@ -33,6 +35,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) class ExpandPipOnPinchOpenTest(flicker: LegacyFlickerTest) : PipTransition(flicker) { override val thisTransition: FlickerBuilder.() -> Unit = { transitions { pipApp.pinchOpenPipWindow(wmHelper, 0.25f, 30) } diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenAutoEnterPipOnGoToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenAutoEnterPipOnGoToHomeTest.kt index 5f8ac2af241b..1c40d89aec80 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenAutoEnterPipOnGoToHomeTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenAutoEnterPipOnGoToHomeTest.kt @@ -16,7 +16,10 @@ package com.android.wm.shell.flicker.pip +import android.platform.test.annotations.FlakyTest import android.platform.test.annotations.Presubmit +import android.platform.test.annotations.RequiresDevice +import android.platform.test.annotations.RequiresFlagsDisabled import android.tools.Rotation import android.tools.flicker.junit.FlickerParametersRunnerFactory import android.tools.flicker.legacy.FlickerBuilder @@ -24,10 +27,9 @@ import android.tools.flicker.legacy.LegacyFlickerTest import android.tools.flicker.legacy.LegacyFlickerTestFactory import android.tools.helpers.WindowUtils import android.tools.traces.parsers.toFlickerComponent -import androidx.test.filters.FlakyTest -import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.helpers.SimpleAppHelper import com.android.server.wm.flicker.testapp.ActivityOptions +import com.android.wm.shell.Flags import com.android.wm.shell.flicker.utils.SplitScreenUtils import org.junit.Assume import org.junit.FixMethodOrder @@ -62,6 +64,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) class FromSplitScreenAutoEnterPipOnGoToHomeTest(flicker: LegacyFlickerTest) : AutoEnterPipOnGoToHomeTest(flicker) { private val portraitDisplayBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_0) diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenEnterPipOnUserLeaveHintTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenEnterPipOnUserLeaveHintTest.kt index 48c85a84e556..12e23285ea68 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenEnterPipOnUserLeaveHintTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenEnterPipOnUserLeaveHintTest.kt @@ -16,7 +16,10 @@ package com.android.wm.shell.flicker.pip +import android.platform.test.annotations.FlakyTest import android.platform.test.annotations.Presubmit +import android.platform.test.annotations.RequiresDevice +import android.platform.test.annotations.RequiresFlagsDisabled import android.tools.Rotation import android.tools.flicker.junit.FlickerParametersRunnerFactory import android.tools.flicker.legacy.FlickerBuilder @@ -24,10 +27,9 @@ import android.tools.flicker.legacy.LegacyFlickerTest import android.tools.flicker.legacy.LegacyFlickerTestFactory import android.tools.helpers.WindowUtils import android.tools.traces.parsers.toFlickerComponent -import androidx.test.filters.FlakyTest -import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.helpers.SimpleAppHelper import com.android.server.wm.flicker.testapp.ActivityOptions +import com.android.wm.shell.Flags import com.android.wm.shell.flicker.pip.common.EnterPipTransition import com.android.wm.shell.flicker.utils.SplitScreenUtils import org.junit.Assume @@ -63,6 +65,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) class FromSplitScreenEnterPipOnUserLeaveHintTest(flicker: LegacyFlickerTest) : EnterPipTransition(flicker) { private val portraitDisplayBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_0) diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt index ee62cf59b2f9..d979b428d8b2 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt @@ -17,10 +17,12 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit +import android.platform.test.annotations.RequiresDevice +import android.platform.test.annotations.RequiresFlagsDisabled import android.tools.flicker.junit.FlickerParametersRunnerFactory import android.tools.flicker.legacy.FlickerBuilder import android.tools.flicker.legacy.LegacyFlickerTest -import androidx.test.filters.RequiresDevice +import com.android.wm.shell.Flags import com.android.wm.shell.flicker.pip.common.MovePipShelfHeightTransition import com.android.wm.shell.flicker.utils.Direction import org.junit.FixMethodOrder @@ -56,6 +58,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) class MovePipDownOnShelfHeightChange(flicker: LegacyFlickerTest) : MovePipShelfHeightTransition(flicker) { override val thisTransition: FlickerBuilder.() -> Unit = { diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt index 04fedf4f2550..88d78edae94a 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt @@ -17,6 +17,7 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit +import android.platform.test.annotations.RequiresFlagsDisabled import android.tools.Rotation import android.tools.flicker.assertions.FlickerTest import android.tools.flicker.junit.FlickerParametersRunnerFactory @@ -27,6 +28,7 @@ import android.tools.helpers.WindowUtils import android.tools.traces.component.ComponentNameMatcher import com.android.server.wm.flicker.helpers.ImeAppHelper import com.android.server.wm.flicker.helpers.setRotation +import com.android.wm.shell.Flags import com.android.wm.shell.flicker.pip.common.PipTransition import org.junit.FixMethodOrder import org.junit.Test @@ -41,6 +43,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) class MovePipOnImeVisibilityChangeTest(flicker: LegacyFlickerTest) : PipTransition(flicker) { private val imeApp = ImeAppHelper(instrumentation) diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt index 4d643f7b4408..c533800b37c5 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt @@ -17,10 +17,12 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit +import android.platform.test.annotations.RequiresDevice +import android.platform.test.annotations.RequiresFlagsDisabled import android.tools.flicker.junit.FlickerParametersRunnerFactory import android.tools.flicker.legacy.FlickerBuilder import android.tools.flicker.legacy.LegacyFlickerTest -import androidx.test.filters.RequiresDevice +import com.android.wm.shell.Flags import com.android.wm.shell.flicker.pip.common.MovePipShelfHeightTransition import com.android.wm.shell.flicker.utils.Direction import org.junit.FixMethodOrder @@ -56,6 +58,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) open class MovePipUpOnShelfHeightChangeTest(flicker: LegacyFlickerTest) : MovePipShelfHeightTransition(flicker) { override val thisTransition: FlickerBuilder.() -> Unit = { @@ -65,7 +68,8 @@ open class MovePipUpOnShelfHeightChangeTest(flicker: LegacyFlickerTest) : } /** Checks that the visible region of [pipApp] window always moves up during the animation. */ - @Presubmit @Test fun pipWindowMovesUp() = pipWindowMoves(Direction.UP) + @Presubmit + @Test fun pipWindowMovesUp() = pipWindowMoves(Direction.UP) /** Checks that the visible region of [pipApp] layer always moves up during the animation. */ @Presubmit @Test fun pipLayerMovesUp() = pipLayerMoves(Direction.UP) diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipAspectRatioChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipAspectRatioChangeTest.kt index 429774f890a5..04016a93e53d 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipAspectRatioChangeTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipAspectRatioChangeTest.kt @@ -17,11 +17,13 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit +import android.platform.test.annotations.RequiresFlagsDisabled import android.tools.Rotation import android.tools.flicker.junit.FlickerParametersRunnerFactory import android.tools.flicker.legacy.FlickerBuilder import android.tools.flicker.legacy.LegacyFlickerTest import android.tools.flicker.legacy.LegacyFlickerTestFactory +import com.android.wm.shell.Flags import com.android.wm.shell.flicker.pip.common.PipTransition import org.junit.FixMethodOrder import org.junit.Test @@ -33,6 +35,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) class PipAspectRatioChangeTest(flicker: LegacyFlickerTest) : PipTransition(flicker) { override val thisTransition: FlickerBuilder.() -> Unit = { transitions { pipApp.changeAspectRatio(wmHelper) } diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipDragTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipDragTest.kt index a4df69fc6539..6bcaabc3b680 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipDragTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipDragTest.kt @@ -18,11 +18,13 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit import android.platform.test.annotations.RequiresDevice +import android.platform.test.annotations.RequiresFlagsDisabled import android.tools.flicker.junit.FlickerParametersRunnerFactory import android.tools.flicker.legacy.FlickerBuilder import android.tools.flicker.legacy.LegacyFlickerTest import android.tools.flicker.legacy.LegacyFlickerTestFactory import com.android.server.wm.flicker.testapp.ActivityOptions +import com.android.wm.shell.Flags import com.android.wm.shell.flicker.pip.common.PipTransition import org.junit.FixMethodOrder import org.junit.Test @@ -35,6 +37,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) class PipDragTest(flicker: LegacyFlickerTest) : PipTransition(flicker) { private var isDraggedLeft: Boolean = true diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipDragThenSnapTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipDragThenSnapTest.kt index cbd4a528474a..d82bfdd6dc2f 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipDragThenSnapTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipDragThenSnapTest.kt @@ -17,16 +17,18 @@ package com.android.wm.shell.flicker.pip import android.graphics.Rect +import android.platform.test.annotations.FlakyTest +import android.platform.test.annotations.RequiresDevice +import android.platform.test.annotations.RequiresFlagsDisabled import android.tools.Rotation import android.tools.flicker.junit.FlickerParametersRunnerFactory import android.tools.flicker.legacy.FlickerBuilder import android.tools.flicker.legacy.LegacyFlickerTest import android.tools.flicker.legacy.LegacyFlickerTestFactory import android.tools.flicker.rules.RemoveAllTasksButHomeRule -import androidx.test.filters.FlakyTest -import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.helpers.setRotation import com.android.server.wm.flicker.testapp.ActivityOptions +import com.android.wm.shell.Flags import com.android.wm.shell.flicker.pip.common.PipTransition import org.junit.FixMethodOrder import org.junit.Test @@ -40,6 +42,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) class PipDragThenSnapTest(flicker: LegacyFlickerTest) : PipTransition(flicker) { // represents the direction in which the pip window should be snapping private var willSnapRight: Boolean = true diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt index 16d08e5e9055..dbc97d072f9b 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt @@ -17,13 +17,15 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit +import android.platform.test.annotations.RequiresDevice +import android.platform.test.annotations.RequiresFlagsDisabled import android.tools.Rotation import android.tools.flicker.junit.FlickerParametersRunnerFactory import android.tools.flicker.legacy.FlickerBuilder import android.tools.flicker.legacy.LegacyFlickerTest import android.tools.flicker.legacy.LegacyFlickerTestFactory import android.tools.flicker.subject.exceptions.IncorrectRegionException -import androidx.test.filters.RequiresDevice +import com.android.wm.shell.Flags import com.android.wm.shell.flicker.pip.common.PipTransition import org.junit.FixMethodOrder import org.junit.Test @@ -36,6 +38,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) class PipPinchInTest(flicker: LegacyFlickerTest) : PipTransition(flicker) { override val thisTransition: FlickerBuilder.() -> Unit = { transitions { pipApp.pinchInPipWindow(wmHelper, 0.4f, 30) } diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt index 578a9b536289..9d46ac1d6e00 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt @@ -17,8 +17,11 @@ package com.android.wm.shell.flicker.pip import android.app.Activity +import android.platform.test.annotations.FlakyTest import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit +import android.platform.test.annotations.RequiresDevice +import android.platform.test.annotations.RequiresFlagsDisabled import android.tools.Rotation import android.tools.flicker.assertions.FlickerTest import android.tools.flicker.junit.FlickerParametersRunnerFactory @@ -26,10 +29,9 @@ import android.tools.flicker.legacy.FlickerBuilder import android.tools.flicker.legacy.LegacyFlickerTest import android.tools.flicker.legacy.LegacyFlickerTestFactory import android.tools.helpers.WindowUtils -import androidx.test.filters.FlakyTest -import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.testapp.ActivityOptions import com.android.server.wm.flicker.testapp.ActivityOptions.PortraitOnlyActivity.EXTRA_FIXED_ORIENTATION +import com.android.wm.shell.Flags import com.android.wm.shell.flicker.pip.common.PipTransition import com.android.wm.shell.flicker.pip.common.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_LANDSCAPE import org.junit.Assume @@ -48,6 +50,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) open class SetRequestedOrientationWhilePinned(flicker: LegacyFlickerTest) : PipTransition(flicker) { private val startingBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_0) private val endingBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_90) diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt index c6cf3411835c..e72251fb7a31 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt @@ -17,6 +17,7 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Presubmit +import android.platform.test.annotations.RequiresFlagsDisabled import android.tools.flicker.assertions.FlickerTest import android.tools.flicker.junit.FlickerParametersRunnerFactory import android.tools.flicker.legacy.FlickerBuilder @@ -25,6 +26,7 @@ import android.tools.flicker.legacy.LegacyFlickerTestFactory import android.tools.helpers.WindowUtils import com.android.server.wm.flicker.helpers.SimpleAppHelper import com.android.server.wm.flicker.helpers.setRotation +import com.android.wm.shell.Flags import com.android.wm.shell.flicker.pip.common.PipTransition import org.junit.FixMethodOrder import org.junit.Test @@ -58,6 +60,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) class ShowPipAndRotateDisplay(flicker: LegacyFlickerTest) : PipTransition(flicker) { private val testApp = SimpleAppHelper(instrumentation) private val screenBoundsStart = WindowUtils.getDisplayBounds(flicker.scenario.startRotation) diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/PipTransition.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/PipTransition.kt index bc2bfdbe1df1..c37bf3579e93 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/PipTransition.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/PipTransition.kt @@ -20,6 +20,7 @@ import android.app.Instrumentation import android.content.Intent import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit +import android.platform.test.flag.junit.DeviceFlagsValueProvider import android.tools.Rotation import android.tools.flicker.legacy.FlickerBuilder import android.tools.flicker.legacy.LegacyFlickerTest @@ -31,9 +32,14 @@ import com.android.server.wm.flicker.helpers.setRotation import com.android.server.wm.flicker.testapp.ActivityOptions import com.android.wm.shell.flicker.BaseTest import com.google.common.truth.Truth +import org.junit.Rule import org.junit.Test abstract class PipTransition(flicker: LegacyFlickerTest) : BaseTest(flicker) { + @JvmField + @Rule + val checkFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() + protected val pipApp = PipAppHelper(instrumentation) protected val displayBounds = WindowUtils.getDisplayBounds(flicker.scenario.startRotation) protected val broadcastActionTrigger = BroadcastActionTrigger(instrumentation) diff --git a/media/java/android/media/AudioPlaybackConfiguration.java b/media/java/android/media/AudioPlaybackConfiguration.java index da50f2cd86c4..c085b8985783 100644 --- a/media/java/android/media/AudioPlaybackConfiguration.java +++ b/media/java/android/media/AudioPlaybackConfiguration.java @@ -41,6 +41,7 @@ import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Objects; @@ -59,6 +60,8 @@ public final class AudioPlaybackConfiguration implements Parcelable { public static final int PLAYER_UPID_INVALID = -1; /** @hide */ public static final int PLAYER_DEVICEID_INVALID = 0; + /** @hide */ + public static final int[] PLAYER_DEVICEIDS_INVALID = new int[0]; // information about the implementation /** @@ -335,7 +338,7 @@ public final class AudioPlaybackConfiguration implements Parcelable { private final Object mUpdateablePropLock = new Object(); @GuardedBy("mUpdateablePropLock") - private int mDeviceId; + private @NonNull int[] mDeviceIds = AudioPlaybackConfiguration.PLAYER_DEVICEIDS_INVALID; @GuardedBy("mUpdateablePropLock") private int mSessionId; @GuardedBy("mUpdateablePropLock") @@ -364,7 +367,7 @@ public final class AudioPlaybackConfiguration implements Parcelable { mClientUid = uid; mClientPid = pid; mMutedState = 0; - mDeviceId = PLAYER_DEVICEID_INVALID; + mDeviceIds = AudioPlaybackConfiguration.PLAYER_DEVICEIDS_INVALID; mPlayerState = PLAYER_STATE_IDLE; mPlayerAttr = pic.mAttributes; if ((sPlayerDeathMonitor != null) && (pic.mIPlayer != null)) { @@ -388,10 +391,11 @@ public final class AudioPlaybackConfiguration implements Parcelable { } // sets the fields that are updateable and require synchronization - private void setUpdateableFields(int deviceId, int sessionId, int mutedState, FormatInfo format) + private void setUpdateableFields(int[] deviceIds, int sessionId, int mutedState, + FormatInfo format) { synchronized (mUpdateablePropLock) { - mDeviceId = deviceId; + mDeviceIds = deviceIds; mSessionId = sessionId; mMutedState = mutedState; mFormatInfo = format; @@ -427,7 +431,7 @@ public final class AudioPlaybackConfiguration implements Parcelable { anonymCopy.mClientPid = PLAYER_UPID_INVALID; anonymCopy.mIPlayerShell = null; anonymCopy.setUpdateableFields( - /*deviceId*/ PLAYER_DEVICEID_INVALID, + /*deviceIds*/ new int[0], /*sessionId*/ AudioSystem.AUDIO_SESSION_ALLOCATE, /*mutedState*/ 0, FormatInfo.DEFAULT); @@ -471,14 +475,14 @@ public final class AudioPlaybackConfiguration implements Parcelable { @Deprecated @FlaggedApi(FLAG_ROUTED_DEVICE_IDS) public @Nullable AudioDeviceInfo getAudioDeviceInfo() { - final int deviceId; + final int[] deviceIds; synchronized (mUpdateablePropLock) { - deviceId = mDeviceId; + deviceIds = mDeviceIds; } - if (deviceId == PLAYER_DEVICEID_INVALID) { + if (deviceIds.length == 0) { return null; } - return AudioManager.getDeviceForPortId(deviceId, AudioManager.GET_DEVICES_OUTPUTS); + return AudioManager.getDeviceForPortId(deviceIds[0], AudioManager.GET_DEVICES_OUTPUTS); } /** @@ -491,9 +495,17 @@ public final class AudioPlaybackConfiguration implements Parcelable { @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public @NonNull List<AudioDeviceInfo> getAudioDeviceInfos() { List<AudioDeviceInfo> audioDeviceInfos = new ArrayList<AudioDeviceInfo>(); - AudioDeviceInfo audioDeviceInfo = getAudioDeviceInfo(); - if (audioDeviceInfo != null) { - audioDeviceInfos.add(audioDeviceInfo); + final int[] deviceIds; + synchronized (mUpdateablePropLock) { + deviceIds = mDeviceIds; + } + + for (int i = 0; i < deviceIds.length; i++) { + AudioDeviceInfo audioDeviceInfo = AudioManager.getDeviceForPortId(deviceIds[i], + AudioManager.GET_DEVICES_OUTPUTS); + if (audioDeviceInfo != null) { + audioDeviceInfos.add(audioDeviceInfo); + } } return audioDeviceInfos; } @@ -701,15 +713,15 @@ public final class AudioPlaybackConfiguration implements Parcelable { * @hide * Handle a player state change * @param event - * @param deviceId active device id or {@Code PLAYER_DEVICEID_INVALID} - * <br>Note device id is valid for {@code PLAYER_UPDATE_DEVICE_ID} or - * <br>{@code PLAYER_STATE_STARTED} events, as the device id will be reset to none when - * <br>pausing or stopping playback. It will be set to active device when playback starts or + * @param deviceIds an array of device ids. This can be empty. + * <br>Note device ids are non-empty for {@code PLAYER_UPDATE_DEVICE_ID} or + * <br>{@code PLAYER_STATE_STARTED} events, as the device ids will be emptied when pausing + * <br>or stopping playback. It will be set to active devices when playback starts or * <br>it will be changed when PLAYER_UPDATE_DEVICE_ID is sent. The latter can happen if the - * <br>device changes in the middle of playback. + * <br>devices change in the middle of playback. * @return true if the state changed, false otherwise */ - public boolean handleStateEvent(int event, int deviceId) { + public boolean handleStateEvent(int event, int[] deviceIds) { boolean changed = false; synchronized (mUpdateablePropLock) { @@ -720,8 +732,8 @@ public final class AudioPlaybackConfiguration implements Parcelable { } if (event == PLAYER_STATE_STARTED || event == PLAYER_UPDATE_DEVICE_ID) { - changed = changed || (mDeviceId != deviceId); - mDeviceId = deviceId; + changed = changed || !Arrays.equals(mDeviceIds, deviceIds); + mDeviceIds = deviceIds; } if (changed && (event == PLAYER_STATE_RELEASED) && (mIPlayerShell != null)) { @@ -801,8 +813,8 @@ public final class AudioPlaybackConfiguration implements Parcelable { @Override public int hashCode() { synchronized (mUpdateablePropLock) { - return Objects.hash(mPlayerIId, mDeviceId, mMutedState, mPlayerType, mClientUid, - mClientPid, mSessionId); + return Objects.hash(mPlayerIId, Arrays.toString(mDeviceIds), mMutedState, mPlayerType, + mClientUid, mClientPid, mSessionId); } } @@ -815,7 +827,7 @@ public final class AudioPlaybackConfiguration implements Parcelable { public void writeToParcel(Parcel dest, int flags) { synchronized (mUpdateablePropLock) { dest.writeInt(mPlayerIId); - dest.writeInt(mDeviceId); + dest.writeIntArray(mDeviceIds); dest.writeInt(mMutedState); dest.writeInt(mPlayerType); dest.writeInt(mClientUid); @@ -834,7 +846,10 @@ public final class AudioPlaybackConfiguration implements Parcelable { private AudioPlaybackConfiguration(Parcel in) { mPlayerIId = in.readInt(); - mDeviceId = in.readInt(); + mDeviceIds = new int[in.readInt()]; + for (int i = 0; i < mDeviceIds.length; i++) { + mDeviceIds[i] = in.readInt(); + } mMutedState = in.readInt(); mPlayerType = in.readInt(); mClientUid = in.readInt(); @@ -855,7 +870,7 @@ public final class AudioPlaybackConfiguration implements Parcelable { AudioPlaybackConfiguration that = (AudioPlaybackConfiguration) o; return ((mPlayerIId == that.mPlayerIId) - && (mDeviceId == that.mDeviceId) + && Arrays.equals(mDeviceIds, that.mDeviceIds) && (mMutedState == that.mMutedState) && (mPlayerType == that.mPlayerType) && (mClientUid == that.mClientUid) @@ -868,7 +883,7 @@ public final class AudioPlaybackConfiguration implements Parcelable { StringBuilder apcToString = new StringBuilder(); synchronized (mUpdateablePropLock) { apcToString.append("AudioPlaybackConfiguration piid:").append(mPlayerIId).append( - " deviceId:").append(mDeviceId).append(" type:").append( + " deviceIds:").append(Arrays.toString(mDeviceIds)).append(" type:").append( toLogFriendlyPlayerType(mPlayerType)).append(" u/pid:").append( mClientUid).append( "/").append(mClientPid).append(" state:").append( diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java index 939494152116..cacd59f42ec4 100644 --- a/media/java/android/media/AudioRecord.java +++ b/media/java/android/media/AudioRecord.java @@ -1908,17 +1908,37 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection, } /** + * Internal API of getRoutedDevices(). We should not call flag APIs internally. + */ + private @NonNull List<AudioDeviceInfo> getRoutedDevicesInternal() { + List<AudioDeviceInfo> audioDeviceInfos = new ArrayList<AudioDeviceInfo>(); + final int[] deviceIds = native_getRoutedDeviceIds(); + if (deviceIds == null || deviceIds.length == 0) { + return audioDeviceInfos; + } + + for (int i = 0; i < deviceIds.length; i++) { + AudioDeviceInfo audioDeviceInfo = AudioManager.getDeviceForPortId(deviceIds[i], + AudioManager.GET_DEVICES_INPUTS); + if (audioDeviceInfo != null) { + audioDeviceInfos.add(audioDeviceInfo); + } + } + return audioDeviceInfos; + } + + /** * Returns an {@link AudioDeviceInfo} identifying the current routing of this AudioRecord. * Note: The query is only valid if the AudioRecord is currently recording. If it is not, * <code>getRoutedDevice()</code> will return null. */ @Override public AudioDeviceInfo getRoutedDevice() { - int deviceId = native_getRoutedDeviceId(); - if (deviceId == 0) { + final List<AudioDeviceInfo> audioDeviceInfos = getRoutedDevicesInternal(); + if (audioDeviceInfos.isEmpty()) { return null; } - return AudioManager.getDeviceForPortId(deviceId, AudioManager.GET_DEVICES_INPUTS); + return audioDeviceInfos.get(0); } /** @@ -1930,12 +1950,7 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection, @Override @FlaggedApi(FLAG_ROUTED_DEVICE_IDS) public @NonNull List<AudioDeviceInfo> getRoutedDevices() { - List<AudioDeviceInfo> audioDeviceInfos = new ArrayList<AudioDeviceInfo>(); - AudioDeviceInfo audioDeviceInfo = getRoutedDevice(); - if (audioDeviceInfo != null) { - audioDeviceInfos.add(audioDeviceInfo); - } - return audioDeviceInfos; + return getRoutedDevicesInternal(); } /** @@ -2513,7 +2528,7 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection, int sampleRateInHz, int channelCount, int audioFormat); private native final boolean native_setInputDevice(int deviceId); - private native final int native_getRoutedDeviceId(); + private native int[] native_getRoutedDeviceIds(); private native final void native_enableDeviceCallback(); private native final void native_disableDeviceCallback(); diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index 93a183188793..a5d9adb5cadc 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -3023,7 +3023,7 @@ public class AudioTrack extends PlayerBase } } synchronized(mPlayStateLock) { - baseStart(0); // unknown device at this point + baseStart(new int[0]); // unknown device at this point native_start(); // FIXME see b/179218630 //baseStart(native_getRoutedDeviceId()); @@ -3784,6 +3784,26 @@ public class AudioTrack extends PlayerBase } /** + * Internal API of getRoutedDevices(). We should not call flag APIs internally. + */ + private @NonNull List<AudioDeviceInfo> getRoutedDevicesInternal() { + List<AudioDeviceInfo> audioDeviceInfos = new ArrayList<AudioDeviceInfo>(); + final int[] deviceIds = native_getRoutedDeviceIds(); + if (deviceIds == null || deviceIds.length == 0) { + return audioDeviceInfos; + } + + for (int i = 0; i < deviceIds.length; i++) { + AudioDeviceInfo audioDeviceInfo = AudioManager.getDeviceForPortId(deviceIds[i], + AudioManager.GET_DEVICES_OUTPUTS); + if (audioDeviceInfo != null) { + audioDeviceInfos.add(audioDeviceInfo); + } + } + return audioDeviceInfos; + } + + /** * Returns an {@link AudioDeviceInfo} identifying the current routing of this AudioTrack. * Note: The query is only valid if the AudioTrack is currently playing. If it is not, * <code>getRoutedDevice()</code> will return null. @@ -3792,11 +3812,11 @@ public class AudioTrack extends PlayerBase */ @Override public AudioDeviceInfo getRoutedDevice() { - int deviceId = native_getRoutedDeviceId(); - if (deviceId == 0) { + final List<AudioDeviceInfo> audioDeviceInfos = getRoutedDevicesInternal(); + if (audioDeviceInfos.isEmpty()) { return null; } - return AudioManager.getDeviceForPortId(deviceId, AudioManager.GET_DEVICES_OUTPUTS); + return audioDeviceInfos.get(0); } /** @@ -3808,12 +3828,7 @@ public class AudioTrack extends PlayerBase @Override @FlaggedApi(FLAG_ROUTED_DEVICE_IDS) public @NonNull List<AudioDeviceInfo> getRoutedDevices() { - List<AudioDeviceInfo> audioDeviceInfos = new ArrayList<AudioDeviceInfo>(); - AudioDeviceInfo audioDeviceInfo = getRoutedDevice(); - if (audioDeviceInfo != null) { - audioDeviceInfos.add(audioDeviceInfo); - } - return audioDeviceInfos; + return getRoutedDevicesInternal(); } private void tryToDisableNativeRoutingCallback() { @@ -3973,7 +3988,7 @@ public class AudioTrack extends PlayerBase */ private void broadcastRoutingChange() { AudioManager.resetAudioPortGeneration(); - baseUpdateDeviceId(getRoutedDevice()); + baseUpdateDeviceIds(getRoutedDevicesInternal()); synchronized (mRoutingChangeListeners) { for (NativeRoutingEventHandlerDelegate delegate : mRoutingChangeListeners.values()) { delegate.notifyClient(); @@ -4530,7 +4545,7 @@ public class AudioTrack extends PlayerBase private native final int native_setAuxEffectSendLevel(float level); private native final boolean native_setOutputDevice(int deviceId); - private native final int native_getRoutedDeviceId(); + private native int[] native_getRoutedDeviceIds(); private native final void native_enableDeviceCallback(); private native final void native_disableDeviceCallback(); diff --git a/media/java/android/media/HwAudioSource.java b/media/java/android/media/HwAudioSource.java index 167ab6535843..68a3aa7eb834 100644 --- a/media/java/android/media/HwAudioSource.java +++ b/media/java/android/media/HwAudioSource.java @@ -145,7 +145,14 @@ public class HwAudioSource extends PlayerBase { mAudioAttributes); if (isPlaying()) { // FIXME: b/174876389 clean up device id reporting - baseStart(getDeviceId()); + // Set as deviceIds empty and create an array with element if device id is valid. + int[] deviceIds = AudioPlaybackConfiguration.PLAYER_DEVICEIDS_INVALID; + int deviceId = getDeviceId(); + if (deviceId != 0) { + deviceIds = new int[1]; + deviceIds[0] = deviceId; + } + baseStart(deviceIds); } } diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index 9fd3f5beb25c..08b0dd3fb11c 100644 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -87,7 +87,7 @@ interface IAudioService { oneway void playerAttributes(in int piid, in AudioAttributes attr); - oneway void playerEvent(in int piid, in int event, in int eventId); + oneway void playerEvent(in int piid, in int event, in int[] eventId); oneway void releasePlayer(in int piid); diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index 158bc7fcd482..f1c2a7aec903 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -1415,7 +1415,7 @@ public class MediaPlayer extends PlayerBase } private void startImpl() { - baseStart(0); // unknown device at this point + baseStart(new int[0]); // unknown device at this point stayAwake(true); tryToEnableNativeRoutingCallback(); _start(); @@ -1541,6 +1541,26 @@ public class MediaPlayer extends PlayerBase } /** + * Internal API of getRoutedDevices(). We should not call flag APIs internally. + */ + private @NonNull List<AudioDeviceInfo> getRoutedDevicesInternal() { + List<AudioDeviceInfo> audioDeviceInfos = new ArrayList<AudioDeviceInfo>(); + final int[] deviceIds = native_getRoutedDeviceIds(); + if (deviceIds == null || deviceIds.length == 0) { + return audioDeviceInfos; + } + + for (int i = 0; i < deviceIds.length; i++) { + AudioDeviceInfo audioDeviceInfo = AudioManager.getDeviceForPortId(deviceIds[i], + AudioManager.GET_DEVICES_OUTPUTS); + if (audioDeviceInfo != null) { + audioDeviceInfos.add(audioDeviceInfo); + } + } + return audioDeviceInfos; + } + + /** * Returns an {@link AudioDeviceInfo} identifying the current routing of this MediaPlayer * Note: The query is only valid if the MediaPlayer is currently playing. * If the player is not playing, the returned device can be null or correspond to previously @@ -1550,11 +1570,11 @@ public class MediaPlayer extends PlayerBase */ @Override public AudioDeviceInfo getRoutedDevice() { - int deviceId = native_getRoutedDeviceId(); - if (deviceId == 0) { + final List<AudioDeviceInfo> audioDeviceInfos = getRoutedDevicesInternal(); + if (audioDeviceInfos.isEmpty()) { return null; } - return AudioManager.getDeviceForPortId(deviceId, AudioManager.GET_DEVICES_OUTPUTS); + return audioDeviceInfos.get(0); } /** @@ -1567,12 +1587,7 @@ public class MediaPlayer extends PlayerBase @Override @FlaggedApi(FLAG_ROUTED_DEVICE_IDS) public @NonNull List<AudioDeviceInfo> getRoutedDevices() { - List<AudioDeviceInfo> audioDeviceInfos = new ArrayList<AudioDeviceInfo>(); - AudioDeviceInfo audioDeviceInfo = getRoutedDevice(); - if (audioDeviceInfo != null) { - audioDeviceInfos.add(audioDeviceInfo); - } - return audioDeviceInfos; + return getRoutedDevicesInternal(); } /** @@ -1584,7 +1599,7 @@ public class MediaPlayer extends PlayerBase // Prevent the case where an event is triggered by registering a routing change // listener via the media player. if (mEnableSelfRoutingMonitor) { - baseUpdateDeviceId(getRoutedDevice()); + baseUpdateDeviceIds(getRoutedDevicesInternal()); } for (NativeRoutingEventHandlerDelegate delegate : mRoutingChangeListeners.values()) { @@ -1694,7 +1709,7 @@ public class MediaPlayer extends PlayerBase } private native final boolean native_setOutputDevice(int deviceId); - private native final int native_getRoutedDeviceId(); + private native int[] native_getRoutedDeviceIds(); private native final void native_enableDeviceCallback(boolean enabled); /** diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java index f75bcf3c437d..7af78b81cda5 100644 --- a/media/java/android/media/MediaRecorder.java +++ b/media/java/android/media/MediaRecorder.java @@ -1684,6 +1684,26 @@ public class MediaRecorder implements AudioRouting, } /** + * Internal API of getRoutedDevices(). We should not call flag APIs internally. + */ + private @NonNull List<AudioDeviceInfo> getRoutedDevicesInternal() { + List<AudioDeviceInfo> audioDeviceInfos = new ArrayList<AudioDeviceInfo>(); + final int[] deviceIds = native_getRoutedDeviceIds(); + if (deviceIds == null || deviceIds.length == 0) { + return audioDeviceInfos; + } + + for (int i = 0; i < deviceIds.length; i++) { + AudioDeviceInfo audioDeviceInfo = AudioManager.getDeviceForPortId(deviceIds[i], + AudioManager.GET_DEVICES_INPUTS); + if (audioDeviceInfo != null) { + audioDeviceInfos.add(audioDeviceInfo); + } + } + return audioDeviceInfos; + } + + /** * Returns an {@link AudioDeviceInfo} identifying the current routing of this MediaRecorder * Note: The query is only valid if the MediaRecorder is currently recording. * If the recorder is not recording, the returned device can be null or correspond to previously @@ -1691,11 +1711,11 @@ public class MediaRecorder implements AudioRouting, */ @Override public AudioDeviceInfo getRoutedDevice() { - int deviceId = native_getRoutedDeviceId(); - if (deviceId == 0) { + final List<AudioDeviceInfo> audioDeviceInfos = getRoutedDevicesInternal(); + if (audioDeviceInfos.isEmpty()) { return null; } - return AudioManager.getDeviceForPortId(deviceId, AudioManager.GET_DEVICES_INPUTS); + return audioDeviceInfos.get(0); } /** @@ -1708,12 +1728,7 @@ public class MediaRecorder implements AudioRouting, @Override @FlaggedApi(FLAG_ROUTED_DEVICE_IDS) public @NonNull List<AudioDeviceInfo> getRoutedDevices() { - List<AudioDeviceInfo> audioDeviceInfos = new ArrayList<AudioDeviceInfo>(); - AudioDeviceInfo audioDeviceInfo = getRoutedDevice(); - if (audioDeviceInfo != null) { - audioDeviceInfos.add(audioDeviceInfo); - } - return audioDeviceInfos; + return getRoutedDevicesInternal(); } /* @@ -1773,7 +1788,7 @@ public class MediaRecorder implements AudioRouting, } private native final boolean native_setInputDevice(int deviceId); - private native final int native_getRoutedDeviceId(); + private native int[] native_getRoutedDeviceIds(); private native final void native_enableDeviceCallback(boolean enabled); //-------------------------------------------------------------------------- diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java index 3f44b09124e4..dbf8338ac99f 100644 --- a/media/java/android/media/PlayerBase.java +++ b/media/java/android/media/PlayerBase.java @@ -39,6 +39,8 @@ import com.android.internal.app.IAppOpsCallback; import com.android.internal.app.IAppOpsService; import java.lang.ref.WeakReference; +import java.util.Arrays; +import java.util.List; import java.util.Objects; /** @@ -91,7 +93,7 @@ public abstract class PlayerBase { @GuardedBy("mLock") private float mVolMultiplier = 1.0f; @GuardedBy("mLock") - private int mDeviceId; + private @NonNull int[] mDeviceIds = AudioPlaybackConfiguration.PLAYER_DEVICEIDS_INVALID; /** * Constructor. Must be given audio attributes, as they are required for AppOps. @@ -158,35 +160,36 @@ public abstract class PlayerBase { } } - void baseUpdateDeviceId(@Nullable AudioDeviceInfo deviceInfo) { - int deviceId = 0; - if (deviceInfo != null) { - deviceId = deviceInfo.getId(); + void baseUpdateDeviceIds(@NonNull List<AudioDeviceInfo> deviceInfos) { + int[] deviceIds = new int[deviceInfos.size()]; + for (int i = 0; i < deviceInfos.size(); i++) { + deviceIds[i] = deviceInfos.get(i).getId(); } + int piid; synchronized (mLock) { piid = mPlayerIId; - mDeviceId = deviceId; + mDeviceIds = deviceIds; } try { getService().playerEvent(piid, - AudioPlaybackConfiguration.PLAYER_UPDATE_DEVICE_ID, deviceId); + AudioPlaybackConfiguration.PLAYER_UPDATE_DEVICE_ID, deviceIds); } catch (RemoteException e) { Log.e(TAG, "Error talking to audio service, " - + deviceId + + Arrays.toString(deviceIds) + " device id will not be tracked for piid=" + piid, e); } } - private void updateState(int state, int deviceId) { + private void updateState(int state, @NonNull int[] deviceIds) { final int piid; synchronized (mLock) { mState = state; piid = mPlayerIId; - mDeviceId = deviceId; + mDeviceIds = deviceIds; } try { - getService().playerEvent(piid, state, deviceId); + getService().playerEvent(piid, state, deviceIds); } catch (RemoteException e) { Log.e(TAG, "Error talking to audio service, " + AudioPlaybackConfiguration.toLogFriendlyPlayerState(state) @@ -194,11 +197,12 @@ public abstract class PlayerBase { } } - void baseStart(int deviceId) { + void baseStart(@NonNull int[] deviceIds) { if (DEBUG) { - Log.v(TAG, "baseStart() piid=" + mPlayerIId + " deviceId=" + deviceId); + Log.v(TAG, "baseStart() piid=" + mPlayerIId + " deviceId=" + + Arrays.toString(deviceIds)); } - updateState(AudioPlaybackConfiguration.PLAYER_STATE_STARTED, deviceId); + updateState(AudioPlaybackConfiguration.PLAYER_STATE_STARTED, deviceIds); } void baseSetStartDelayMs(int delayMs) { @@ -215,12 +219,12 @@ public abstract class PlayerBase { void basePause() { if (DEBUG) { Log.v(TAG, "basePause() piid=" + mPlayerIId); } - updateState(AudioPlaybackConfiguration.PLAYER_STATE_PAUSED, 0); + updateState(AudioPlaybackConfiguration.PLAYER_STATE_PAUSED, new int[0]); } void baseStop() { if (DEBUG) { Log.v(TAG, "baseStop() piid=" + mPlayerIId); } - updateState(AudioPlaybackConfiguration.PLAYER_STATE_STOPPED, 0); + updateState(AudioPlaybackConfiguration.PLAYER_STATE_STOPPED, new int[0]); } void baseSetPan(float pan) { diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java index 7b9ff23596d9..f22cc9c08b4c 100644 --- a/media/java/android/media/SoundPool.java +++ b/media/java/android/media/SoundPool.java @@ -317,7 +317,7 @@ public class SoundPool extends PlayerBase { // FIXME: b/174876164 implement device id for soundpool try { Trace.traceBegin(Trace.TRACE_TAG_AUDIO, "SoundPool.play"); - baseStart(0); + baseStart(new int[0]); return _play(soundID, leftVolume, rightVolume, priority, loop, rate, getPlayerIId()); } finally { Trace.traceEnd(Trace.TRACE_TAG_AUDIO); diff --git a/media/java/android/media/tv/extension/pvr/IDeleteRecordedContentsCallback.aidl b/media/java/android/media/tv/extension/pvr/IDeleteRecordedContentsCallback.aidl new file mode 100644 index 000000000000..62f151145472 --- /dev/null +++ b/media/java/android/media/tv/extension/pvr/IDeleteRecordedContentsCallback.aidl @@ -0,0 +1,24 @@ +/* + * 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.media.tv.extension.pvr; + +/** + * @hide + */ +oneway interface IDeleteRecordedContentsCallback { + void onRecordedContentsDeleted(in String[] contentUri, in int[] result); +} diff --git a/media/java/android/media/tv/extension/pvr/IGetInfoRecordedContentsCallback.aidl b/media/java/android/media/tv/extension/pvr/IGetInfoRecordedContentsCallback.aidl new file mode 100644 index 000000000000..64f8fc2188b7 --- /dev/null +++ b/media/java/android/media/tv/extension/pvr/IGetInfoRecordedContentsCallback.aidl @@ -0,0 +1,24 @@ +/* + * 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.media.tv.extension.pvr; + +/** + * @hide + */ +interface IGetInfoRecordedContentsCallback { + void onRecordedContentsGetInfo(int result); +} diff --git a/media/java/android/media/tv/extension/pvr/IRecordedContents.aidl b/media/java/android/media/tv/extension/pvr/IRecordedContents.aidl new file mode 100644 index 000000000000..74a15b8e0b94 --- /dev/null +++ b/media/java/android/media/tv/extension/pvr/IRecordedContents.aidl @@ -0,0 +1,36 @@ +/* + * 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.media.tv.extension.pvr; + +import android.media.tv.extension.pvr.IDeleteRecordedContentsCallback; +import android.media.tv.extension.pvr.IGetInfoRecordedContentsCallback; + + +/** + * @hide + */ +interface IRecordedContents { + // Delete recorded contents by URIs + // using callback to notify the result or any errors during the deletion process. + void deleteRecordedContents(in String[] contentUri, + in IDeleteRecordedContentsCallback callback); + // Get the channel lock status for recorded content identified by the URI provided in sync way. + int getRecordedContentsLockInfoSync(String contentUri); + // Get the channel lock status for recorded content identified by the URI provided in async way. + void getRecordedContentsLockInfoAsync(String contentUri, + in IGetInfoRecordedContentsCallback callback); +} diff --git a/media/java/android/media/tv/extension/signal/IAnalogAudioInfo.aidl b/media/java/android/media/tv/extension/signal/IAnalogAudioInfo.aidl new file mode 100644 index 000000000000..742191ff3c05 --- /dev/null +++ b/media/java/android/media/tv/extension/signal/IAnalogAudioInfo.aidl @@ -0,0 +1,26 @@ +/* + * 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.media.tv.extension.signal; + +import android.os.Bundle; + +/** + * @hide + */ +interface IAnalogAudioInfo { + Bundle getAnalogAudioInfo(String sessionToken); +} diff --git a/media/java/android/media/tv/extension/signal/IAudioSignalInfo.aidl b/media/java/android/media/tv/extension/signal/IAudioSignalInfo.aidl new file mode 100644 index 000000000000..4c953a08364a --- /dev/null +++ b/media/java/android/media/tv/extension/signal/IAudioSignalInfo.aidl @@ -0,0 +1,36 @@ +/* + * 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.media.tv.extension.signal; + +import android.media.tv.extension.signal.IAudioSignalInfoListener; +import android.os.Bundle; + +/** + * @hide + */ +interface IAudioSignalInfo { + // Get audio signal information. + Bundle getAudioSignalInfo(String sessionToken); + // Notify TIS whether user selects audio track via mts button on the remote control. + void notifyMtsSelectTrackFlag(boolean mtsFlag); + // Get the audio track id selected via mts. + String getMtsSelectedTrackId(); + // Register a listener to receive the updated audio signal information. + void addAudioSignalInfoListener(String clientToken, in IAudioSignalInfoListener listener); + // Remove a listener for audio signal information update notifications. + void removeAudioSignalInfoListener(in IAudioSignalInfoListener listener); +} diff --git a/media/java/android/media/tv/extension/signal/IAudioSignalInfoListener.aidl b/media/java/android/media/tv/extension/signal/IAudioSignalInfoListener.aidl new file mode 100644 index 000000000000..adf239ab1b32 --- /dev/null +++ b/media/java/android/media/tv/extension/signal/IAudioSignalInfoListener.aidl @@ -0,0 +1,26 @@ +/* + * 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.media.tv.extension.signal; + +import android.os.Bundle; + +/** + * @hide + */ +oneway interface IAudioSignalInfoListener { + void onAudioSignalInfoChanged(String sessionToken, in Bundle changedSignalInfo); +} diff --git a/media/java/android/media/tv/extension/signal/IHdmiSignalInfoListener.aidl b/media/java/android/media/tv/extension/signal/IHdmiSignalInfoListener.aidl new file mode 100644 index 000000000000..bd468b2e7f34 --- /dev/null +++ b/media/java/android/media/tv/extension/signal/IHdmiSignalInfoListener.aidl @@ -0,0 +1,25 @@ +/* + * 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.media.tv.extension.signal; + +/** + * @hide + */ +oneway interface IHdmiSignalInfoListener { + void onSignalInfoChanged(String sessionToken); + void onLowLatencyModeChanged(int enable); +} diff --git a/media/java/android/media/tv/extension/signal/IHdmiSignalInterface.aidl b/media/java/android/media/tv/extension/signal/IHdmiSignalInterface.aidl new file mode 100644 index 000000000000..39625e3c958d --- /dev/null +++ b/media/java/android/media/tv/extension/signal/IHdmiSignalInterface.aidl @@ -0,0 +1,36 @@ +/* + * 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.media.tv.extension.signal; + +import android.media.tv.extension.signal.IHdmiSignalInfoListener; +import android.os.Bundle; + +/** + * @hide + */ +interface IHdmiSignalInterface { + // Register a listener for Hdmi Signal Info updates. + void addHdmiSignalInfoListener(String inputId, in IHdmiSignalInfoListener listener); + // Remove a listener for Hdmi Signal Info update notifications. + void removeHdmiSignalInfoListener(String inputId, in IHdmiSignalInfoListener listener); + // Obtain HdmiSignalInfo based on the inputId and sessionToken. + Bundle getHdmiSignalInfo(String sessionToken); + // Enable/disable low-latency decoding mode. + void setLowLatency(String sessionToken, int mode); + // Enable/disable force-VRR mode. + void setForceVrr(String sessionToken, int mode); +} diff --git a/media/java/android/media/tv/extension/signal/ITunerFrontendSignalInfoInterface.aidl b/media/java/android/media/tv/extension/signal/ITunerFrontendSignalInfoInterface.aidl new file mode 100644 index 000000000000..7f05e7033aeb --- /dev/null +++ b/media/java/android/media/tv/extension/signal/ITunerFrontendSignalInfoInterface.aidl @@ -0,0 +1,28 @@ +/* + * 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.media.tv.extension.signal; + +import android.media.tv.extension.signal.ITunerFrontendSignalInfoListener; +import android.os.Bundle; + +/** +* @hide +*/ +interface ITunerFrontendSignalInfoInterface { + Bundle getFrontendSignalInfo(String sessionToken); + void setFrontendSignalInfoListener(in ITunerFrontendSignalInfoListener listener); +} diff --git a/media/java/android/media/tv/extension/signal/ITunerFrontendSignalInfoListener.aidl b/media/java/android/media/tv/extension/signal/ITunerFrontendSignalInfoListener.aidl new file mode 100644 index 000000000000..9c22a3570cce --- /dev/null +++ b/media/java/android/media/tv/extension/signal/ITunerFrontendSignalInfoListener.aidl @@ -0,0 +1,24 @@ +/* + * 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.media.tv.extension.signal; + +/** +* @hide +*/ +oneway interface ITunerFrontendSignalInfoListener { + void onFrontendStatusChanged(int frontendStatus); +} diff --git a/media/java/android/media/tv/extension/signal/IVideoSignalInfo.aidl b/media/java/android/media/tv/extension/signal/IVideoSignalInfo.aidl new file mode 100644 index 000000000000..b17142acf2ab --- /dev/null +++ b/media/java/android/media/tv/extension/signal/IVideoSignalInfo.aidl @@ -0,0 +1,30 @@ +/* + * 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.media.tv.extension.signal; + +import android.media.tv.extension.signal.IVideoSignalInfoListener; +import android.os.Bundle; + + +/** + * @hide + */ +interface IVideoSignalInfo { + void addVideoSignalInfoListener(String clientToken, in IVideoSignalInfoListener listener); + void removeVideoSignalInfoListener(in IVideoSignalInfoListener listener); + Bundle getVideoSignalInfo(String sessionToken); +} diff --git a/media/java/android/media/tv/extension/signal/IVideoSignalInfoListener.aidl b/media/java/android/media/tv/extension/signal/IVideoSignalInfoListener.aidl new file mode 100644 index 000000000000..aafc192f32fa --- /dev/null +++ b/media/java/android/media/tv/extension/signal/IVideoSignalInfoListener.aidl @@ -0,0 +1,26 @@ +/* + * 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.media.tv.extension.signal; + +import android.os.Bundle; + +/** + * @hide + */ +oneway interface IVideoSignalInfoListener { + void onVideoSignalInfoChanged(String sessionToken, in Bundle changedSignalInfo); +} diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp index d05ee551c172..a94230014437 100644 --- a/media/jni/android_media_MediaPlayer.cpp +++ b/media/jni/android_media_MediaPlayer.cpp @@ -1362,13 +1362,26 @@ static jboolean android_media_MediaPlayer_setOutputDevice(JNIEnv *env, jobject t return mp->setOutputDevice(device_id) == NO_ERROR; } -static jint android_media_MediaPlayer_getRoutedDeviceId(JNIEnv *env, jobject thiz) +static jintArray android_media_MediaPlayer_getRoutedDeviceIds(JNIEnv *env, jobject thiz) { sp<MediaPlayer> mp = getMediaPlayer(env, thiz); if (mp == NULL) { - return AUDIO_PORT_HANDLE_NONE; + return NULL; + } + DeviceIdVector deviceIds; + // TODO: b/379161379 - Should we throw an exception if the result is not ok? + mp->getRoutedDeviceIds(deviceIds); + jintArray result; + result = env->NewIntArray(deviceIds.size()); + if (result == NULL) { + return NULL; } - return mp->getRoutedDeviceId(); + jint* values = env->GetIntArrayElements(result, 0); + for (unsigned int i = 0; i < deviceIds.size(); i++) { + values[i++] = static_cast<jint>(deviceIds[i]); + } + env->ReleaseIntArrayElements(result, values, 0); + return result; } static void android_media_MediaPlayer_enableDeviceCallback( @@ -1452,7 +1465,8 @@ static const JNINativeMethod gMethods[] = { // AudioRouting {"native_setOutputDevice", "(I)Z", (void *)android_media_MediaPlayer_setOutputDevice}, - {"native_getRoutedDeviceId", "()I", (void *)android_media_MediaPlayer_getRoutedDeviceId}, + {"native_getRoutedDeviceIds", "()[I", + (void *)android_media_MediaPlayer_getRoutedDeviceIds}, {"native_enableDeviceCallback", "(Z)V", (void *)android_media_MediaPlayer_enableDeviceCallback}, }; diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp index 9a6d5d7d730a..643fc8a2d925 100644 --- a/media/jni/android_media_MediaRecorder.cpp +++ b/media/jni/android_media_MediaRecorder.cpp @@ -722,21 +722,31 @@ android_media_MediaRecorder_setInputDevice(JNIEnv *env, jobject thiz, jint devic return true; } -static jint -android_media_MediaRecorder_getRoutedDeviceId(JNIEnv *env, jobject thiz) +static jintArray +android_media_MediaRecorder_getRoutedDeviceIds(JNIEnv *env, jobject thiz) { - ALOGV("android_media_MediaRecorder_getRoutedDeviceId"); + ALOGV("android_media_MediaRecorder_getRoutedDeviceIds"); sp<MediaRecorder> mr = getMediaRecorder(env, thiz); if (mr == NULL) { jniThrowException(env, "java/lang/IllegalStateException", NULL); - return AUDIO_PORT_HANDLE_NONE; + return NULL; } - audio_port_handle_t deviceId; - process_media_recorder_call(env, mr->getRoutedDeviceId(&deviceId), - "java/lang/RuntimeException", "getRoutedDeviceId failed."); - return (jint) deviceId; + DeviceIdVector deviceIds; + process_media_recorder_call(env, mr->getRoutedDeviceIds(deviceIds), + "java/lang/RuntimeException", "getRoutedDeviceIds failed."); + jintArray result; + result = env->NewIntArray(deviceIds.size()); + if (result == NULL) { + return NULL; + } + jint* values = env->GetIntArrayElements(result, 0); + for (unsigned int i = 0; i < deviceIds.size(); i++) { + values[i++] = static_cast<jint>(deviceIds[i]); + } + env->ReleaseIntArrayElements(result, values, 0); + return result; } static void @@ -880,7 +890,8 @@ static const JNINativeMethod gMethods[] = { {"native_getMetrics", "()Landroid/os/PersistableBundle;", (void *)android_media_MediaRecorder_native_getMetrics}, {"native_setInputDevice", "(I)Z", (void *)android_media_MediaRecorder_setInputDevice}, - {"native_getRoutedDeviceId", "()I", (void *)android_media_MediaRecorder_getRoutedDeviceId}, + {"native_getRoutedDeviceIds", "()[I", + (void *)android_media_MediaRecorder_getRoutedDeviceIds}, {"native_enableDeviceCallback", "(Z)V", (void *)android_media_MediaRecorder_enableDeviceCallback}, {"native_getActiveMicrophones", "(Ljava/util/ArrayList;)I", (void *)android_media_MediaRecord_getActiveMicrophones}, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/dagger/NotificationsLogModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/dagger/NotificationsLogModule.kt index 7dd4cdef4d96..d3359d39e959 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/dagger/NotificationsLogModule.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/dagger/NotificationsLogModule.kt @@ -32,6 +32,7 @@ import com.android.systemui.log.dagger.SensitiveNotificationProtectionLog import com.android.systemui.log.dagger.UnseenNotificationLog import com.android.systemui.log.dagger.VisualStabilityLog import com.android.systemui.statusbar.notification.NotifPipelineFlags +import com.android.systemui.statusbar.notification.promoted.PromotedNotificationLog import com.android.systemui.util.Compile import dagger.Module import dagger.Provides @@ -117,6 +118,14 @@ object NotificationsLogModule { return factory.create("NotifSectionLog", 1000, /* maxSize */ false /* systrace */) } + /** Provides a [LogBuffer] for use by promoted notifications. */ + @Provides + @SysUISingleton + @PromotedNotificationLog + fun providesPromotedNotificationLog(factory: LogBufferFactory): LogBuffer { + return factory.create("PromotedNotifLog", 50) + } + /** */ @Provides @SysUISingleton diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationLog.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationLog.kt new file mode 100644 index 000000000000..f9d9c9771e67 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationLog.kt @@ -0,0 +1,25 @@ +/* + * 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.statusbar.notification.promoted + +import javax.inject.Qualifier + +/** A [com.android.systemui.log.LogBuffer] for use by promoted notifications. */ +@Qualifier +@MustBeDocumented +@Retention(AnnotationRetention.RUNTIME) +annotation class PromotedNotificationLog diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index fa228627c255..e57b00944f7c 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -65,6 +65,7 @@ import android.telephony.CellSignalStrengthLte; import android.telephony.CellSignalStrengthNr; import android.telephony.CellSignalStrengthTdscdma; import android.telephony.CellSignalStrengthWcdma; +import android.telephony.CellularIdentifierDisclosure; import android.telephony.DisconnectCause; import android.telephony.LinkCapacityEstimate; import android.telephony.LocationAccessPolicy; @@ -76,6 +77,7 @@ import android.telephony.PreciseCallState; import android.telephony.PreciseDataConnectionState; import android.telephony.PreciseDisconnectCause; import android.telephony.Rlog; +import android.telephony.SecurityAlgorithmUpdate; import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.SubscriptionInfo; @@ -590,7 +592,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { || events.contains(TelephonyCallback.EVENT_ALLOWED_NETWORK_TYPE_LIST_CHANGED) || events.contains(TelephonyCallback.EVENT_EMERGENCY_CALLBACK_MODE_CHANGED) || events.contains(TelephonyCallback - .EVENT_SIMULTANEOUS_CELLULAR_CALLING_SUBSCRIPTIONS_CHANGED); + .EVENT_SIMULTANEOUS_CELLULAR_CALLING_SUBSCRIPTIONS_CHANGED) + || events.contains(TelephonyCallback.EVENT_CELLULAR_IDENTIFIER_DISCLOSED_CHANGED) + || events.contains(TelephonyCallback.EVENT_SECURITY_ALGORITHMS_CHANGED); } private static final int MSG_USER_SWITCHED = 1; @@ -897,7 +901,6 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mIsSatelliteEnabled = new AtomicBoolean(); mWasSatelliteEnabledNotified = new AtomicBoolean(); - for (int i = 0; i < numPhones; i++) { mCallState[i] = TelephonyManager.CALL_STATE_IDLE; mDataActivity[i] = TelephonyManager.DATA_ACTIVITY_NONE; @@ -3825,7 +3828,6 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - /** * Notify external listeners that carrier roaming non-terrestrial network * signal strength changed. @@ -3835,7 +3837,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { public void notifyCarrierRoamingNtnSignalStrengthChanged(int subId, @NonNull NtnSignalStrength ntnSignalStrength) { if (!checkNotifyPermission("notifyCarrierRoamingNtnSignalStrengthChanged")) { - log("nnotifyCarrierRoamingNtnSignalStrengthChanged: caller does not have required " + log("notifyCarrierRoamingNtnSignalStrengthChanged: caller does not have required " + "permissions."); return; } @@ -3863,6 +3865,98 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } + /** + * Notify that the radio security algorithms have changed. + * + * @param phoneId the phone id. + * @param subId the subId. + * @param update the security algorithm update. + */ + public void notifySecurityAlgorithmsChanged(int phoneId, int subId, + SecurityAlgorithmUpdate update) { + if (!Flags.securityAlgorithmsUpdateIndications()) { + log("Not available due to securityAlgorithmsUpdateIndications() flag"); + return; + } + if (!checkNotifyPermission("notifySecurityAlgorithmChanged()")) { + return; + } + + synchronized (mRecords) { + if (validatePhoneId(phoneId)) { + if (update == null) { + loge("SecurityAlgorithmUpdate is null, subId=" + subId + + ", phoneId=" + phoneId); + // Listeners shouldn't be updated for null updates. + return; + } + + for (Record r : mRecords) { + if (r.matchTelephonyCallbackEvent( + TelephonyCallback.EVENT_SECURITY_ALGORITHMS_CHANGED) + && idMatch(r, subId, phoneId)) { + try { + if (VDBG) { + log("notifySecurityAlgorithmsChanged: securityAlgorithmUpdate= " + + update); + } + r.callback.onSecurityAlgorithmsChanged(update); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + } + handleRemoveListLocked(); + } + } + + /** + * Notify of a cellular identifier disclosure. + * + * @param phoneId the phone id. + * @param subId the subId. + * @param disclosure the cellular identifier disclosure. + */ + public void notifyCellularIdentifierDisclosedChanged(int phoneId, int subId, + @NonNull CellularIdentifierDisclosure disclosure) { + if (!Flags.cellularIdentifierDisclosureIndications()) { + log("Not available due to cellularIdentifierDisclosureIndications() flag"); + return; + } + if (!checkNotifyPermission("notifyCellularIdentifierDisclosedChanged()")) { + return; + } + + synchronized (mRecords) { + if (validatePhoneId(phoneId)) { + if (disclosure == null) { + loge("CellularIdentifierDisclosure is null, subId=" + subId + + ", phoneId=" + phoneId); + // Listeners shouldn't be updated for null disclosures. + return; + } + + for (Record r : mRecords) { + if (r.matchTelephonyCallbackEvent( + TelephonyCallback.EVENT_CELLULAR_IDENTIFIER_DISCLOSED_CHANGED) + && idMatch(r, subId, phoneId)) { + try { + if (VDBG) { + log("notifyCellularIdentifierDisclosedChanged: disclosure= " + + disclosure); + } + r.callback.onCellularIdentifierDisclosedChanged(disclosure); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + } + handleRemoveListLocked(); + } + } + @NeverCompile // Avoid size overhead of debugging code. @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 5f716605e8cd..6e6bf80e8c09 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -14166,10 +14166,10 @@ public class AudioService extends IAudioService.Stub * Update player event * @param piid Player id to update * @param event The new player event - * @param eventValue The value associated with this event + * @param eventValues The values associated with this event */ - public void playerEvent(int piid, int event, int eventValue) { - mPlaybackMonitor.playerEvent(piid, event, eventValue, Binder.getCallingUid()); + public void playerEvent(int piid, int event, int[] eventValues) { + mPlaybackMonitor.playerEvent(piid, event, eventValues, Binder.getCallingUid()); } /** diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java index e92b5188652b..a62ac82f27eb 100644 --- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java +++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java @@ -365,10 +365,11 @@ public final class PlaybackActivityMonitor * @param eventValue The value associated with this event * @param binderUid Calling binder uid */ - public void playerEvent(int piid, int event, int eventValue, int binderUid) { + public void playerEvent(int piid, int event, int[] eventValues, int binderUid) { if (DEBUG) { - Log.v(TAG, TextUtils.formatSimple("playerEvent(piid=%d, event=%s, eventValue=%d)", - piid, AudioPlaybackConfiguration.playerStateToString(event), eventValue)); + Log.v(TAG, TextUtils.formatSimple("playerEvent(piid=%d, event=%s, eventValues=%d)", + piid, AudioPlaybackConfiguration.playerStateToString(event), + Arrays.toString(eventValues))); } boolean change; synchronized(mPlayerLock) { @@ -382,13 +383,13 @@ public final class PlaybackActivityMonitor // do not log nor dispatch events for "ignored" players other than the release return; } - sEventLogger.enqueue(new PlayerEvent(piid, event, eventValue)); + sEventLogger.enqueue(new PlayerEvent(piid, event, eventValues)); if (event == AudioPlaybackConfiguration.PLAYER_UPDATE_PORT_ID) { if (portToPiidSimplification()) { - mPiidToPortId.put(piid, eventValue); + mPiidToPortId.put(piid, eventValues[0]); } else { - mPortIdToPiid.put(eventValue, piid); + mPortIdToPiid.put(eventValues[0], piid); } return; } else if (event == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) { @@ -409,7 +410,7 @@ public final class PlaybackActivityMonitor if (checkConfigurationCaller(piid, apc, binderUid)) { //TODO add generation counter to only update to the latest state checkVolumeForPrivilegedAlarm(apc, event); - change = apc.handleStateEvent(event, eventValue); + change = apc.handleStateEvent(event, eventValues); } else { Log.e(TAG, "Error handling event " + event); change = false; @@ -517,7 +518,7 @@ public final class PlaybackActivityMonitor mMutedPlayersAwaitingConnection.remove(Integer.valueOf(piid)); checkVolumeForPrivilegedAlarm(apc, AudioPlaybackConfiguration.PLAYER_STATE_RELEASED); change = apc.handleStateEvent(AudioPlaybackConfiguration.PLAYER_STATE_RELEASED, - AudioPlaybackConfiguration.PLAYER_DEVICEID_INVALID); + AudioPlaybackConfiguration.PLAYER_DEVICEIDS_INVALID); if (portToPiidSimplification()) { mPiidToPortId.delete(piid); @@ -1336,12 +1337,12 @@ public final class PlaybackActivityMonitor // only keeping the player interface ID as it uniquely identifies the player in the event final int mPlayerIId; final int mEvent; - final int mEventValue; + final int[] mEventValues; - PlayerEvent(int piid, int event, int eventValue) { + PlayerEvent(int piid, int event, int[] eventValues) { mPlayerIId = piid; mEvent = event; - mEventValue = eventValue; + mEventValues = eventValues; } @Override @@ -1353,36 +1354,38 @@ public final class PlaybackActivityMonitor switch (mEvent) { case AudioPlaybackConfiguration.PLAYER_UPDATE_PORT_ID: return AudioPlaybackConfiguration.toLogFriendlyPlayerState(mEvent) + " portId:" - + mEventValue + " mapped to player piid:" + mPlayerIId; + + Arrays.toString(mEventValues) + " mapped to player piid:" + + mPlayerIId; case AudioPlaybackConfiguration.PLAYER_UPDATE_DEVICE_ID: - if (mEventValue != 0) { - builder.append(" deviceId:").append(mEventValue); + if ((mEventValues.length > 0) && (mEventValues[0] != 0)) { + builder.append(" deviceIds:").append(Arrays.toString(mEventValues)); } return builder.toString(); case AudioPlaybackConfiguration.PLAYER_UPDATE_MUTED: builder.append(" source:"); - if (mEventValue <= 0) { + int eventValue = mEventValues[0]; + if (eventValue <= 0) { builder.append("none "); } else { - if ((mEventValue & MUTED_BY_MASTER) != 0) { + if ((eventValue & MUTED_BY_MASTER) != 0) { builder.append("masterMute "); } - if ((mEventValue & MUTED_BY_STREAM_VOLUME) != 0) { + if ((eventValue & MUTED_BY_STREAM_VOLUME) != 0) { builder.append("streamVolume "); } - if ((mEventValue & MUTED_BY_STREAM_MUTED) != 0) { + if ((eventValue & MUTED_BY_STREAM_MUTED) != 0) { builder.append("streamMute "); } - if ((mEventValue & MUTED_BY_APP_OPS) != 0) { + if ((eventValue & MUTED_BY_APP_OPS) != 0) { builder.append("appOps "); } - if ((mEventValue & MUTED_BY_CLIENT_VOLUME) != 0) { + if ((eventValue & MUTED_BY_CLIENT_VOLUME) != 0) { builder.append("clientVolume "); } - if ((mEventValue & MUTED_BY_VOLUME_SHAPER) != 0) { + if ((eventValue & MUTED_BY_VOLUME_SHAPER) != 0) { builder.append("volumeShaper "); } - if ((mEventValue & MUTED_BY_PORT_VOLUME) != 0) { + if ((eventValue & MUTED_BY_PORT_VOLUME) != 0) { builder.append("portVolume "); } } @@ -1732,8 +1735,11 @@ public final class PlaybackActivityMonitor synchronized (mPlayerLock) { int piid = msg.arg1; + + int[] eventValues = new int[1]; + eventValues[0] = eventValue; sEventLogger.enqueue( - new PlayerEvent(piid, PLAYER_UPDATE_MUTED, eventValue)); + new PlayerEvent(piid, PLAYER_UPDATE_MUTED, eventValues)); final AudioPlaybackConfiguration apc = mPlayers.get(piid); if (apc == null || !apc.handleMutedEvent(eventValue)) { diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index d9e76966892c..8168c5493304 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -1029,12 +1029,14 @@ final class InstallPackageHelper { if (reconciledPackages == null) { return; } - if (Flags.improveInstallFreeze()) { - prepPerformDexoptIfNeeded(reconciledPackages); - } - if (renameAndUpdatePaths(requests) - && commitInstallPackages(reconciledPackages)) { - success = true; + if (renameAndUpdatePaths(requests)) { + // rename before dexopt because art will encoded the path in the odex/vdex file + if (Flags.improveInstallFreeze()) { + prepPerformDexoptIfNeeded(reconciledPackages); + } + if (commitInstallPackages(reconciledPackages)) { + success = true; + } } } } finally { diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index 2c0942337b1f..286333cb83a9 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -96,7 +96,6 @@ import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IInterface; -import android.os.Looper; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteCallbackList; @@ -2667,6 +2666,7 @@ public class LauncherAppsService extends SystemService { } final String[] packagesNullExtras = packagesWithoutExtras.toArray( new String[packagesWithoutExtras.size()]); + final int n = mListeners.beginBroadcast(); try { for (int i = 0; i < n; i++) { @@ -2852,7 +2852,7 @@ public class LauncherAppsService extends SystemService { class SecureSettingsObserver extends ContentObserver { SecureSettingsObserver() { - super(new Handler(Looper.getMainLooper())); + super(mCallbackHandler); } @Override @@ -2866,32 +2866,29 @@ public class LauncherAppsService extends SystemService { if (privateProfile.getIdentifier() == UserHandle.USER_NULL) { return; } - final int n = mListeners.beginBroadcast(); try { for (int i = 0; i < n; i++) { - final IOnAppsChangedListener listener = - mListeners.getBroadcastItem(i); + final IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); final BroadcastCookie cookie = - (BroadcastCookie) mListeners.getBroadcastCookie( - i); + (BroadcastCookie) mListeners.getBroadcastCookie(i); if (!isEnabledProfileOf(cookie, privateProfile, "onSecureSettingsChange")) { Log.d(TAG, "onSecureSettingsChange: Skipping - profile not enabled" + " or not accessible for package=" + cookie.packageName + ", packageUid=" + cookie.callingUid); - } else { - try { - Log.d(TAG, - "onUserConfigChanged: triggering onUserConfigChanged"); - listener.onUserConfigChanged( - mUserManagerInternal.getLauncherUserInfo( - privateProfile.getIdentifier())); - } catch (RemoteException re) { - Slog.d(TAG, "onUserConfigChanged: Callback failed ", re); - } + continue; + } + try { + Log.d(TAG, "onUserConfigChanged: triggering onUserConfigChanged"); + listener.onUserConfigChanged( + mUserManagerInternal.getLauncherUserInfo( + privateProfile.getIdentifier())); + } catch (RemoteException re) { + Slog.d(TAG, "onUserConfigChanged: Callback failed ", re); } } + } finally { mListeners.finishBroadcast(); } diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index 465ac2f1731d..887e1861f789 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -61,6 +61,7 @@ import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.PersistableBundle; +import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; @@ -84,6 +85,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.content.PackageMonitor; import com.android.internal.infra.AndroidFuture; +import com.android.internal.policy.IDeviceLockedStateListener; import com.android.internal.util.DumpUtils; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockSettingsInternal; @@ -105,6 +107,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Objects; +import java.util.stream.IntStream; /** * Manages trust agents and trust listeners. @@ -253,6 +256,10 @@ public class TrustManagerService extends SystemService { new SparseArray<>(); private final SparseArray<TrustableTimeoutAlarmListener> mIdleTrustableTimeoutAlarmListenerForUser = new SparseArray<>(); + + private final RemoteCallbackList<IDeviceLockedStateListener> + mDeviceLockedStateListeners = new RemoteCallbackList<>(); + private AlarmManager mAlarmManager; private final Object mAlarmLock = new Object(); @@ -1090,6 +1097,7 @@ public class TrustManagerService extends SystemService { if (changed) { notifyTrustAgentsOfDeviceLockState(userId, locked); notifyKeystoreOfDeviceLockState(userId, locked); + notifyDeviceLockedListenersForUser(userId, locked); // Also update the user's profiles who have unified challenge, since they // share the same unlocked state (see {@link #isDeviceLocked(int)}) for (int profileHandle : mUserManager.getEnabledProfileIds(userId)) { @@ -1910,6 +1918,26 @@ public class TrustManagerService extends SystemService { return mIsInSignificantPlace; } + @EnforcePermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE) + @Override + public void registerDeviceLockedStateListener(IDeviceLockedStateListener listener, + int deviceId) { + super.registerDeviceLockedStateListener_enforcePermission(); + if (deviceId != Context.DEVICE_ID_DEFAULT) { + // Virtual devices are considered insecure. + return; + } + mDeviceLockedStateListeners.register(listener, + Integer.valueOf(UserHandle.getUserId(Binder.getCallingUid()))); + } + + @EnforcePermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE) + @Override + public void unregisterDeviceLockedStateListener(IDeviceLockedStateListener listener) { + super.unregisterDeviceLockedStateListener_enforcePermission(); + mDeviceLockedStateListeners.unregister(listener); + } + private void enforceReportPermission() { mContext.enforceCallingOrSelfPermission( Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, "reporting trust events"); @@ -2031,6 +2059,7 @@ public class TrustManagerService extends SystemService { } notifyKeystoreOfDeviceLockState(userId, locked); + notifyDeviceLockedListenersForUser(userId, locked); if (locked) { try { @@ -2497,4 +2526,24 @@ public class TrustManagerService extends SystemService { updateTrust(mUserId, 0 /* flags */); } } + + private void notifyDeviceLockedListenersForUser(int userId, boolean locked) { + int numListeners = mDeviceLockedStateListeners.beginBroadcast(); + try { + IntStream.range(0, numListeners).forEach(i -> { + try { + Integer uid = (Integer) mDeviceLockedStateListeners.getBroadcastCookie(i); + if (userId == uid.intValue()) { + mDeviceLockedStateListeners.getBroadcastItem(i) + .onDeviceLockedStateChanged(locked); + } + } catch (RemoteException re) { + Log.i(TAG, "Service died", re); + } + }); + + } finally { + mDeviceLockedStateListeners.finishBroadcast(); + } + } } diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java index 143d1b72fff9..8562bb23b30f 100644 --- a/services/core/java/com/android/server/wm/TransitionController.java +++ b/services/core/java/com/android/server/wm/TransitionController.java @@ -658,8 +658,8 @@ class TransitionController { } // Always allow WindowState to assign layers since it won't affect transition. return wc.asWindowState() != null || (!isPlaying() - // Don't assign task while collecting. - && !(wc.asTask() != null && isCollecting())); + // Don't assign task or display area layers while collecting. + && !((wc.asTask() != null || wc.asDisplayArea() != null) && isCollecting())); } @WindowConfiguration.WindowingMode diff --git a/services/tests/servicestests/src/com/android/server/accessibility/FlashNotificationsControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/FlashNotificationsControllerTest.java index 0988eeab5913..a55346caeeb1 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/FlashNotificationsControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/FlashNotificationsControllerTest.java @@ -430,7 +430,7 @@ public class FlashNotificationsControllerTest { AudioPlaybackConfiguration config = new AudioPlaybackConfiguration( mock(PlayerBase.PlayerIdCard.class), 0, 0, 0); config.handleStateEvent(AudioPlaybackConfiguration.PLAYER_STATE_STARTED, - AudioPlaybackConfiguration.PLAYER_DEVICEID_INVALID); + AudioPlaybackConfiguration.PLAYER_DEVICEIDS_INVALID); AudioAttributes.Builder builder = new AudioAttributes.Builder(); builder.setUsage(AudioAttributes.USAGE_ALARM); diff --git a/services/tests/servicestests/src/com/android/server/audio/LoudnessCodecHelperTest.java b/services/tests/servicestests/src/com/android/server/audio/LoudnessCodecHelperTest.java index 84c0ab38ca48..0d44021bae09 100644 --- a/services/tests/servicestests/src/com/android/server/audio/LoudnessCodecHelperTest.java +++ b/services/tests/servicestests/src/com/android/server/audio/LoudnessCodecHelperTest.java @@ -314,12 +314,13 @@ public class LoudnessCodecHelperTest { AudioDeviceInfo[] devicesStatic = AudioManager.getDevicesStatic(GET_DEVICES_OUTPUTS); assumeTrue(devIdx < devicesStatic.length); Log.d(TAG, "Out devices number " + devicesStatic.length + ". Picking index " + devIdx); - int deviceId = devicesStatic[devIdx].getId(); + int[] deviceIds = new int[1]; + deviceIds[0] = devicesStatic[devIdx].getId(); PlayerBase.PlayerIdCard idCard = Mockito.mock(PlayerBase.PlayerIdCard.class); AudioPlaybackConfiguration apc = new AudioPlaybackConfiguration(idCard, piid, /*uid=*/1, /*pid=*/myPid()); - apc.handleStateEvent(PLAYER_UPDATE_DEVICE_ID, deviceId); + apc.handleStateEvent(PLAYER_UPDATE_DEVICE_ID, deviceIds); apc.handleSessionIdEvent(sessionId); apc.handleAudioAttributesEvent(new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA) diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java index 51c2ad1d1134..687a1ab4c7aa 100644 --- a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java @@ -200,7 +200,9 @@ public class VirtualAudioControllerTest { AudioPlaybackConfiguration audioPlaybackConfiguration = new AudioPlaybackConfiguration( playerIdCard, /* piid= */ 1000, appUid, /* pid= */ 1000); - audioPlaybackConfiguration.handleStateEvent(PLAYER_STATE_STARTED, /* deviceId= */1); + int[] deviceIds = new int[1]; + deviceIds[0] = 1; + audioPlaybackConfiguration.handleStateEvent(PLAYER_STATE_STARTED, deviceIds); configs.add(audioPlaybackConfiguration); } return configs; diff --git a/telephony/java/android/telephony/CellularIdentifierDisclosure.aidl b/telephony/java/android/telephony/CellularIdentifierDisclosure.aidl new file mode 100644 index 000000000000..1e41d6e2cc31 --- /dev/null +++ b/telephony/java/android/telephony/CellularIdentifierDisclosure.aidl @@ -0,0 +1,20 @@ +/* + * 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. + */ + +/** @hide */ +package android.telephony; + +parcelable CellularIdentifierDisclosure; diff --git a/telephony/java/android/telephony/CellularIdentifierDisclosure.java b/telephony/java/android/telephony/CellularIdentifierDisclosure.java index 7b2db6d59819..0b6a70feac9d 100644 --- a/telephony/java/android/telephony/CellularIdentifierDisclosure.java +++ b/telephony/java/android/telephony/CellularIdentifierDisclosure.java @@ -16,11 +16,16 @@ package android.telephony; +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; +import com.android.internal.telephony.flags.Flags; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; @@ -31,16 +36,88 @@ import java.util.Objects; * * @hide */ +@SystemApi +@FlaggedApi(Flags.FLAG_CELLULAR_IDENTIFIER_DISCLOSURE_INDICATIONS) public final class CellularIdentifierDisclosure implements Parcelable { private static final String TAG = "CellularIdentifierDisclosure"; + /* Non-access stratum protocol messages */ + /** Unknown */ + public static final int NAS_PROTOCOL_MESSAGE_UNKNOWN = 0; + /** ATTACH REQUESTS. Sample reference: TS 24.301 8.2.4 Applies to 2g, 3g, and 4g networks */ + public static final int NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST = 1; + /** IDENTITY RESPONSE. Sample Reference: TS 24.301 8.2.19. + * Applies to 2g, 3g, 4g, and 5g networks */ + public static final int NAS_PROTOCOL_MESSAGE_IDENTITY_RESPONSE = 2; + /** DETACH_REQUEST. Sample Reference: TS 24.301 8.2.11. Applies to 2g, 3g, and 4g networks */ + public static final int NAS_PROTOCOL_MESSAGE_DETACH_REQUEST = 3; + /** TRACKING AREA UPDATE (TAU) REQUEST. Sample Reference: 3GPP TS 24.301 8.2.29. + * Note: that per the spec, only temporary IDs should be sent in the TAU Request, but since the + * EPS Mobile Identity field supports IMSIs, this is included as an extra safety measure to + * combat implementation bugs. Applies to 4g and 5g networks. */ + public static final int NAS_PROTOCOL_MESSAGE_TRACKING_AREA_UPDATE_REQUEST = 4; + /** LOCATION UPDATE REQUEST. Sample Reference: TS 24.008 4.4.3. Applies to 2g and 3g networks */ + public static final int NAS_PROTOCOL_MESSAGE_LOCATION_UPDATE_REQUEST = 5; + /** AUTHENTICATION AND CIPHERING RESPONSE. Reference: 3GPP TS 24.008 4.7.7.1. + * Applies to 2g and 3g networks */ + public static final int NAS_PROTOCOL_MESSAGE_AUTHENTICATION_AND_CIPHERING_RESPONSE = 6; + /** REGISTRATION REQUEST. Reference: 3GPP TS 24.501 8.2.6. Applies to 5g networks */ + public static final int NAS_PROTOCOL_MESSAGE_REGISTRATION_REQUEST = 7; + /** DEREGISTRATION REQUEST. Reference: 3GPP TS 24.501 8.2.12. Applies to 5g networks */ + public static final int NAS_PROTOCOL_MESSAGE_DEREGISTRATION_REQUEST = 8; + /** CONNECTION MANAGEMENT REESTABLISHMENT REQUEST. Reference: 3GPP TS 24.008 9.2.4. + * Applies to 2g and 3g networks */ + public static final int NAS_PROTOCOL_MESSAGE_CM_REESTABLISHMENT_REQUEST = 9; + /** CONNECTION MANAGEMENT SERVICE REQUEST. Reference: 3GPP TS 24.008 9.2.9. + * Applies to 2g and 3g networks */ + public static final int NAS_PROTOCOL_MESSAGE_CM_SERVICE_REQUEST = 10; + /** IMEI DETATCH INDICATION. Reference: 3GPP TS 24.008 9.2.14. + * Applies to 2g and 3g networks. Used for circuit-switched detach. */ + public static final int NAS_PROTOCOL_MESSAGE_IMSI_DETACH_INDICATION = 11; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"NAS_PROTOCOL_MESSAGE_"}, value = {NAS_PROTOCOL_MESSAGE_UNKNOWN, + NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST, NAS_PROTOCOL_MESSAGE_IDENTITY_RESPONSE, + NAS_PROTOCOL_MESSAGE_DETACH_REQUEST, NAS_PROTOCOL_MESSAGE_TRACKING_AREA_UPDATE_REQUEST, + NAS_PROTOCOL_MESSAGE_LOCATION_UPDATE_REQUEST, + NAS_PROTOCOL_MESSAGE_AUTHENTICATION_AND_CIPHERING_RESPONSE, + NAS_PROTOCOL_MESSAGE_REGISTRATION_REQUEST, NAS_PROTOCOL_MESSAGE_DEREGISTRATION_REQUEST, + NAS_PROTOCOL_MESSAGE_CM_REESTABLISHMENT_REQUEST, + NAS_PROTOCOL_MESSAGE_CM_SERVICE_REQUEST, NAS_PROTOCOL_MESSAGE_IMSI_DETACH_INDICATION}) + public @interface NasProtocolMessage { + } + + /* Cellular identifiers */ + /** Unknown */ + public static final int CELLULAR_IDENTIFIER_UNKNOWN = 0; + /** IMSI (International Mobile Subscriber Identity) */ + public static final int CELLULAR_IDENTIFIER_IMSI = 1; + /** IMEI (International Mobile Equipment Identity) */ + public static final int CELLULAR_IDENTIFIER_IMEI = 2; + /** 5G-specific SUCI (Subscription Concealed Identifier) */ + public static final int CELLULAR_IDENTIFIER_SUCI = 3; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"CELLULAR_IDENTIFIER_"}, value = {CELLULAR_IDENTIFIER_UNKNOWN, + CELLULAR_IDENTIFIER_IMSI, CELLULAR_IDENTIFIER_IMEI, CELLULAR_IDENTIFIER_SUCI}) + public @interface CellularIdentifier { + } + private @NasProtocolMessage int mNasProtocolMessage; private @CellularIdentifier int mCellularIdentifier; private String mPlmn; private boolean mIsEmergency; + /** + * Constructor for new CellularIdentifierDisclosure instances. + * + * @hide + */ + @TestApi public CellularIdentifierDisclosure(@NasProtocolMessage int nasProtocolMessage, - @CellularIdentifier int cellularIdentifier, String plmn, boolean isEmergency) { + @CellularIdentifier int cellularIdentifier, @NonNull String plmn, boolean isEmergency) { mNasProtocolMessage = nasProtocolMessage; mCellularIdentifier = cellularIdentifier; mPlmn = plmn; @@ -51,18 +128,30 @@ public final class CellularIdentifierDisclosure implements Parcelable { readFromParcel(in); } + /** + * @return the NAS protocol message associated with the disclosed identifier. + */ public @NasProtocolMessage int getNasProtocolMessage() { return mNasProtocolMessage; } + /** + * @return the identifier disclosed. + */ public @CellularIdentifier int getCellularIdentifier() { return mCellularIdentifier; } - public String getPlmn() { + /** + * @return the PLMN associated with the disclosure. + */ + @NonNull public String getPlmn() { return mPlmn; } + /** + * @return if the disclosure is associated with an emergency call. + */ public boolean isEmergency() { return mIsEmergency; } @@ -73,14 +162,14 @@ public final class CellularIdentifierDisclosure implements Parcelable { } @Override - public void writeToParcel(Parcel out, int flags) { + public void writeToParcel(@NonNull Parcel out, int flags) { out.writeInt(mNasProtocolMessage); out.writeInt(mCellularIdentifier); out.writeBoolean(mIsEmergency); out.writeString8(mPlmn); } - public static final Parcelable.Creator<CellularIdentifierDisclosure> CREATOR = + public static final @NonNull Parcelable.Creator<CellularIdentifierDisclosure> CREATOR = new Parcelable.Creator<CellularIdentifierDisclosure>() { public CellularIdentifierDisclosure createFromParcel(Parcel in) { return new CellularIdentifierDisclosure(in); @@ -120,42 +209,4 @@ public final class CellularIdentifierDisclosure implements Parcelable { mIsEmergency = in.readBoolean(); mPlmn = in.readString8(); } - - public static final int NAS_PROTOCOL_MESSAGE_UNKNOWN = 0; - public static final int NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST = 1; - public static final int NAS_PROTOCOL_MESSAGE_IDENTITY_RESPONSE = 2; - public static final int NAS_PROTOCOL_MESSAGE_DETACH_REQUEST = 3; - public static final int NAS_PROTOCOL_MESSAGE_TRACKING_AREA_UPDATE_REQUEST = 4; - public static final int NAS_PROTOCOL_MESSAGE_LOCATION_UPDATE_REQUEST = 5; - public static final int NAS_PROTOCOL_MESSAGE_AUTHENTICATION_AND_CIPHERING_RESPONSE = 6; - public static final int NAS_PROTOCOL_MESSAGE_REGISTRATION_REQUEST = 7; - public static final int NAS_PROTOCOL_MESSAGE_DEREGISTRATION_REQUEST = 8; - public static final int NAS_PROTOCOL_MESSAGE_CM_REESTABLISHMENT_REQUEST = 9; - public static final int NAS_PROTOCOL_MESSAGE_CM_SERVICE_REQUEST = 10; - public static final int NAS_PROTOCOL_MESSAGE_IMSI_DETACH_INDICATION = 11; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = {"NAS_PROTOCOL_MESSAGE_"}, value = {NAS_PROTOCOL_MESSAGE_UNKNOWN, - NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST, NAS_PROTOCOL_MESSAGE_IDENTITY_RESPONSE, - NAS_PROTOCOL_MESSAGE_DETACH_REQUEST, NAS_PROTOCOL_MESSAGE_TRACKING_AREA_UPDATE_REQUEST, - NAS_PROTOCOL_MESSAGE_LOCATION_UPDATE_REQUEST, - NAS_PROTOCOL_MESSAGE_AUTHENTICATION_AND_CIPHERING_RESPONSE, - NAS_PROTOCOL_MESSAGE_REGISTRATION_REQUEST, NAS_PROTOCOL_MESSAGE_DEREGISTRATION_REQUEST, - NAS_PROTOCOL_MESSAGE_CM_REESTABLISHMENT_REQUEST, - NAS_PROTOCOL_MESSAGE_CM_SERVICE_REQUEST, NAS_PROTOCOL_MESSAGE_IMSI_DETACH_INDICATION}) - public @interface NasProtocolMessage { - } - - public static final int CELLULAR_IDENTIFIER_UNKNOWN = 0; - public static final int CELLULAR_IDENTIFIER_IMSI = 1; - public static final int CELLULAR_IDENTIFIER_IMEI = 2; - public static final int CELLULAR_IDENTIFIER_SUCI = 3; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = {"CELLULAR_IDENTIFIER_"}, value = {CELLULAR_IDENTIFIER_UNKNOWN, - CELLULAR_IDENTIFIER_IMSI, CELLULAR_IDENTIFIER_IMEI, CELLULAR_IDENTIFIER_SUCI}) - public @interface CellularIdentifier { - } } diff --git a/telephony/java/android/telephony/SecurityAlgorithmUpdate.aidl b/telephony/java/android/telephony/SecurityAlgorithmUpdate.aidl new file mode 100644 index 000000000000..bee30bd43df9 --- /dev/null +++ b/telephony/java/android/telephony/SecurityAlgorithmUpdate.aidl @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @hide */ +package android.telephony; + +parcelable SecurityAlgorithmUpdate; diff --git a/telephony/java/android/telephony/SecurityAlgorithmUpdate.java b/telephony/java/android/telephony/SecurityAlgorithmUpdate.java index 57209eb68de8..d635b555276b 100644 --- a/telephony/java/android/telephony/SecurityAlgorithmUpdate.java +++ b/telephony/java/android/telephony/SecurityAlgorithmUpdate.java @@ -16,11 +16,16 @@ package android.telephony; +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; +import com.android.internal.telephony.flags.Flags; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; @@ -31,112 +36,42 @@ import java.util.Objects; * * @hide */ +@SystemApi +@FlaggedApi(Flags.FLAG_SECURITY_ALGORITHMS_UPDATE_INDICATIONS) public final class SecurityAlgorithmUpdate implements Parcelable { private static final String TAG = "SecurityAlgorithmUpdate"; - private @ConnectionEvent int mConnectionEvent; - private @SecurityAlgorithm int mEncryption; - private @SecurityAlgorithm int mIntegrity; - private boolean mIsUnprotectedEmergency; - - public SecurityAlgorithmUpdate(@ConnectionEvent int connectionEvent, - @SecurityAlgorithm int encryption, @SecurityAlgorithm int integrity, - boolean isUnprotectedEmergency) { - mConnectionEvent = connectionEvent; - mEncryption = encryption; - mIntegrity = integrity; - mIsUnprotectedEmergency = isUnprotectedEmergency; - } - - private SecurityAlgorithmUpdate(Parcel in) { - readFromParcel(in); - } - - public @ConnectionEvent int getConnectionEvent() { - return mConnectionEvent; - } - - public @SecurityAlgorithm int getEncryption() { - return mEncryption; - } - - public @SecurityAlgorithm int getIntegrity() { - return mIntegrity; - } - - public boolean isUnprotectedEmergency() { - return mIsUnprotectedEmergency; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeInt(mConnectionEvent); - out.writeInt(mEncryption); - out.writeInt(mIntegrity); - out.writeBoolean(mIsUnprotectedEmergency); - } - - private void readFromParcel(@NonNull Parcel in) { - mConnectionEvent = in.readInt(); - mEncryption = in.readInt(); - mIntegrity = in.readInt(); - mIsUnprotectedEmergency = in.readBoolean(); - } - - public static final Parcelable.Creator<SecurityAlgorithmUpdate> CREATOR = - new Parcelable.Creator<SecurityAlgorithmUpdate>() { - public SecurityAlgorithmUpdate createFromParcel(Parcel in) { - return new SecurityAlgorithmUpdate(in); - } - - public SecurityAlgorithmUpdate[] newArray(int size) { - return new SecurityAlgorithmUpdate[size]; - } - }; - - @Override - public String toString() { - return TAG + ":{ mConnectionEvent = " + mConnectionEvent + " mEncryption = " + mEncryption - + " mIntegrity = " + mIntegrity + " mIsUnprotectedEmergency = " - + mIsUnprotectedEmergency; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof SecurityAlgorithmUpdate)) return false; - SecurityAlgorithmUpdate that = (SecurityAlgorithmUpdate) o; - return mConnectionEvent == that.mConnectionEvent - && mEncryption == that.mEncryption - && mIntegrity == that.mIntegrity - && mIsUnprotectedEmergency == that.mIsUnprotectedEmergency; - } - - @Override - public int hashCode() { - return Objects.hash(mConnectionEvent, mEncryption, mIntegrity, mIsUnprotectedEmergency); - } - + /** 2G GSM circuit switched */ public static final int CONNECTION_EVENT_CS_SIGNALLING_GSM = 0; + /** 2G GPRS packet services */ public static final int CONNECTION_EVENT_PS_SIGNALLING_GPRS = 1; + /** 3G circuit switched*/ public static final int CONNECTION_EVENT_CS_SIGNALLING_3G = 2; + /** 3G packet switched*/ public static final int CONNECTION_EVENT_PS_SIGNALLING_3G = 3; + /** 4G Non-access stratum */ public static final int CONNECTION_EVENT_NAS_SIGNALLING_LTE = 4; + /** 4G Access-stratum */ public static final int CONNECTION_EVENT_AS_SIGNALLING_LTE = 5; + /** VOLTE SIP */ public static final int CONNECTION_EVENT_VOLTE_SIP = 6; + /** VOLTE SIP SOS (emergency) */ public static final int CONNECTION_EVENT_VOLTE_SIP_SOS = 7; + /** VOLTE RTP */ public static final int CONNECTION_EVENT_VOLTE_RTP = 8; + /** VOLTE RTP SOS (emergency) */ public static final int CONNECTION_EVENT_VOLTE_RTP_SOS = 9; + /** 5G Non-access stratum */ public static final int CONNECTION_EVENT_NAS_SIGNALLING_5G = 10; + /** 5G Access stratum */ public static final int CONNECTION_EVENT_AS_SIGNALLING_5G = 11; + /** VoNR SIP */ public static final int CONNECTION_EVENT_VONR_SIP = 12; + /** VoNR SIP SOS (emergency) */ public static final int CONNECTION_EVENT_VONR_SIP_SOS = 13; + /** VoNR RTP */ public static final int CONNECTION_EVENT_VONR_RTP = 14; + /** VoNR RTP SOS (emergency) */ public static final int CONNECTION_EVENT_VONR_RTP_SOS = 15; /** @hide */ @@ -153,48 +88,101 @@ public final class SecurityAlgorithmUpdate implements Parcelable { public @interface ConnectionEvent { } + /* GSM CS services, see 3GPP TS 43.020 for details */ + /** A5/0 - the null cipher */ public static final int SECURITY_ALGORITHM_A50 = 0; + /** A5/1 cipher */ public static final int SECURITY_ALGORITHM_A51 = 1; + /** A5/2 cipher */ public static final int SECURITY_ALGORITHM_A52 = 2; + /** A5/3 cipher */ public static final int SECURITY_ALGORITHM_A53 = 3; + /** A5/4 cipher */ public static final int SECURITY_ALGORITHM_A54 = 4; + /* GPRS PS services (3GPP TS 43.020) */ + /** GEA0 - null cipher */ public static final int SECURITY_ALGORITHM_GEA0 = 14; + /** GEA1 cipher */ public static final int SECURITY_ALGORITHM_GEA1 = 15; + /** GEA2 cipher */ public static final int SECURITY_ALGORITHM_GEA2 = 16; + /** GEA3 cipher */ public static final int SECURITY_ALGORITHM_GEA3 = 17; + /** GEA4 cipher */ public static final int SECURITY_ALGORITHM_GEA4 = 18; + /** GEA5 cipher */ public static final int SECURITY_ALGORITHM_GEA5 = 19; + /* 3G PS/CS services (3GPP TS 33.102) */ + /** UEA0 - null cipher */ public static final int SECURITY_ALGORITHM_UEA0 = 29; + /** UEA1 cipher */ public static final int SECURITY_ALGORITHM_UEA1 = 30; + /** UEA2 cipher */ public static final int SECURITY_ALGORITHM_UEA2 = 31; + /* 4G PS services & 5G NSA (3GPP TS 33.401) */ + /** EEA0 - null cipher */ public static final int SECURITY_ALGORITHM_EEA0 = 41; + /** EEA1 */ public static final int SECURITY_ALGORITHM_EEA1 = 42; + /** EEA2 */ public static final int SECURITY_ALGORITHM_EEA2 = 43; + /** EEA3 */ public static final int SECURITY_ALGORITHM_EEA3 = 44; + /* 5G PS services (3GPP TS 33.401 for 5G NSA and 3GPP TS 33.501 for 5G SA) */ + /** NEA0 - the null cipher */ public static final int SECURITY_ALGORITHM_NEA0 = 55; + /** NEA1 */ public static final int SECURITY_ALGORITHM_NEA1 = 56; + /** NEA2 */ public static final int SECURITY_ALGORITHM_NEA2 = 57; + /** NEA3 */ public static final int SECURITY_ALGORITHM_NEA3 = 58; + /* IMS and SIP layer security (See 3GPP TS 33.203) */ + /** No IPsec config */ public static final int SECURITY_ALGORITHM_SIP_NO_IPSEC_CONFIG = 66; + /** No IMS security, recommended to use SIP_NO_IPSEC_CONFIG and SIP_NULL instead */ public static final int SECURITY_ALGORITHM_IMS_NULL = 67; + /* IPSEC is present */ + /** SIP security is not enabled */ public static final int SECURITY_ALGORITHM_SIP_NULL = 68; + /** AES GCM mode */ public static final int SECURITY_ALGORITHM_AES_GCM = 69; + /** AES GMAC mode */ public static final int SECURITY_ALGORITHM_AES_GMAC = 70; + /** AES CBC mode */ public static final int SECURITY_ALGORITHM_AES_CBC = 71; + /** DES EDE3 CBC mode */ public static final int SECURITY_ALGORITHM_DES_EDE3_CBC = 72; + /** AES EDE3 CBC mode */ public static final int SECURITY_ALGORITHM_AES_EDE3_CBC = 73; + /** HMAC SHA1 96 */ public static final int SECURITY_ALGORITHM_HMAC_SHA1_96 = 74; + /** HMAC MD5 96 */ public static final int SECURITY_ALGORITHM_HMAC_MD5_96 = 75; + /* RTP and SRTP (see 3GPP TS 33.328) */ + /** RTP only, SRTP is not being used */ public static final int SECURITY_ALGORITHM_RTP = 85; + /* When SRTP is available and used */ + /** SRTP with null ciphering */ public static final int SECURITY_ALGORITHM_SRTP_NULL = 86; + /** SRTP with AES counter mode */ public static final int SECURITY_ALGORITHM_SRTP_AES_COUNTER = 87; + /** SRTP with AES F8 mode */ public static final int SECURITY_ALGORITHM_SRTP_AES_F8 = 88; + /** SRTP with HMAC SHA1 */ public static final int SECURITY_ALGORITHM_SRTP_HMAC_SHA1 = 89; + /* Ciphers for ePDG (3GPP TS 33.402) */ + /** ePDG encryption - AES GCM mode */ public static final int SECURITY_ALGORITHM_ENCR_AES_GCM_16 = 99; + /** ePDG encryption - AES GCM CBC mode */ public static final int SECURITY_ALGORITHM_ENCR_AES_CBC = 100; + /** ePDG authentication - HMAC SHA1 256 128 */ public static final int SECURITY_ALGORITHM_AUTH_HMAC_SHA2_256_128 = 101; + /** Unknown */ public static final int SECURITY_ALGORITHM_UNKNOWN = 113; + /** Other */ public static final int SECURITY_ALGORITHM_OTHER = 114; + /** Proprietary algorithms */ public static final int SECURITY_ALGORITHM_ORYX = 124; /** @hide */ @@ -220,4 +208,109 @@ public final class SecurityAlgorithmUpdate implements Parcelable { public @interface SecurityAlgorithm { } + private @ConnectionEvent int mConnectionEvent; + private @SecurityAlgorithm int mEncryption; + private @SecurityAlgorithm int mIntegrity; + private boolean mIsUnprotectedEmergency; + + /** + * Constructor for new SecurityAlgorithmUpdate instances. + * + * @hide + */ + @TestApi + public SecurityAlgorithmUpdate(@ConnectionEvent int connectionEvent, + @SecurityAlgorithm int encryption, @SecurityAlgorithm int integrity, + boolean isUnprotectedEmergency) { + mConnectionEvent = connectionEvent; + mEncryption = encryption; + mIntegrity = integrity; + mIsUnprotectedEmergency = isUnprotectedEmergency; + } + + private SecurityAlgorithmUpdate(Parcel in) { + readFromParcel(in); + } + + /** + * @return the connection event. + */ + public @ConnectionEvent int getConnectionEvent() { + return mConnectionEvent; + } + + /** + * @return the encryption algorithm. + */ + public @SecurityAlgorithm int getEncryption() { + return mEncryption; + } + + /** + * @return the integrity algorithm. + */ + public @SecurityAlgorithm int getIntegrity() { + return mIntegrity; + } + + /** + * @return if the security algorithm update is associated with an unprotected emergency call. + */ + public boolean isUnprotectedEmergency() { + return mIsUnprotectedEmergency; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel out, int flags) { + out.writeInt(mConnectionEvent); + out.writeInt(mEncryption); + out.writeInt(mIntegrity); + out.writeBoolean(mIsUnprotectedEmergency); + } + + private void readFromParcel(@NonNull Parcel in) { + mConnectionEvent = in.readInt(); + mEncryption = in.readInt(); + mIntegrity = in.readInt(); + mIsUnprotectedEmergency = in.readBoolean(); + } + + public static final @NonNull Parcelable.Creator<SecurityAlgorithmUpdate> CREATOR = + new Parcelable.Creator<SecurityAlgorithmUpdate>() { + public SecurityAlgorithmUpdate createFromParcel(Parcel in) { + return new SecurityAlgorithmUpdate(in); + } + + public SecurityAlgorithmUpdate[] newArray(int size) { + return new SecurityAlgorithmUpdate[size]; + } + }; + + @Override + public String toString() { + return TAG + ":{ mConnectionEvent = " + mConnectionEvent + " mEncryption = " + mEncryption + + " mIntegrity = " + mIntegrity + " mIsUnprotectedEmergency = " + + mIsUnprotectedEmergency; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof SecurityAlgorithmUpdate)) return false; + SecurityAlgorithmUpdate that = (SecurityAlgorithmUpdate) o; + return mConnectionEvent == that.mConnectionEvent + && mEncryption == that.mEncryption + && mIntegrity == that.mIntegrity + && mIsUnprotectedEmergency == that.mIsUnprotectedEmergency; + } + + @Override + public int hashCode() { + return Objects.hash(mConnectionEvent, mEncryption, mIntegrity, mIsUnprotectedEmergency); + } } |