diff options
56 files changed, 3682 insertions, 662 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index ff362acec44a..d1906c6eac1a 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -385,6 +385,7 @@ package android { field public static final int calendarViewShown = 16843596; // 0x101034c field public static final int calendarViewStyle = 16843613; // 0x101035d field public static final int canControlMagnification = 16844039; // 0x1010507 + field public static final int canPauseRecording = 16844311; // 0x1010617 field public static final int canPerformGestures = 16844045; // 0x101050d field public static final int canRecord = 16844060; // 0x101051c field @Deprecated public static final int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8 @@ -24265,6 +24266,7 @@ package android.media.tv { } public final class TvInputInfo implements android.os.Parcelable { + method public boolean canPauseRecording(); method public boolean canRecord(); method @Deprecated public android.content.Intent createSettingsIntent(); method public android.content.Intent createSetupIntent(); @@ -24298,6 +24300,7 @@ package android.media.tv { public static final class TvInputInfo.Builder { ctor public TvInputInfo.Builder(android.content.Context, android.content.ComponentName); method public android.media.tv.TvInputInfo build(); + method @NonNull public android.media.tv.TvInputInfo.Builder setCanPauseRecording(boolean); method public android.media.tv.TvInputInfo.Builder setCanRecord(boolean); method public android.media.tv.TvInputInfo.Builder setExtras(android.os.Bundle); method public android.media.tv.TvInputInfo.Builder setTunerCount(int); @@ -24389,7 +24392,9 @@ package android.media.tv { method public void notifyRecordingStopped(android.net.Uri); method public void notifyTuned(android.net.Uri); method public void onAppPrivateCommand(@NonNull String, android.os.Bundle); + method public void onPauseRecording(@NonNull android.os.Bundle); method public abstract void onRelease(); + method public void onResumeRecording(@NonNull android.os.Bundle); method public abstract void onStartRecording(@Nullable android.net.Uri); method public void onStartRecording(@Nullable android.net.Uri, @NonNull android.os.Bundle); method public abstract void onStopRecording(); @@ -24439,7 +24444,11 @@ package android.media.tv { public class TvRecordingClient { ctor public TvRecordingClient(android.content.Context, String, @NonNull android.media.tv.TvRecordingClient.RecordingCallback, android.os.Handler); + method public void pauseRecording(); + method public void pauseRecording(@NonNull android.os.Bundle); method public void release(); + method public void resumeRecording(); + method public void resumeRecording(@NonNull android.os.Bundle); method public void sendAppPrivateCommand(@NonNull String, android.os.Bundle); method public void startRecording(@Nullable android.net.Uri); method public void startRecording(@Nullable android.net.Uri, @NonNull android.os.Bundle); @@ -40486,6 +40495,12 @@ package android.telephony { field public static final int SCAN_TYPE_PERIODIC = 1; // 0x1 } + public final class PhoneCapability implements android.os.Parcelable { + method public int describeContents(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhoneCapability> CREATOR; + } + public class PhoneNumberFormattingTextWatcher implements android.text.TextWatcher { ctor public PhoneNumberFormattingTextWatcher(); ctor public PhoneNumberFormattingTextWatcher(String); @@ -40497,12 +40512,13 @@ package android.telephony { public class PhoneNumberUtils { ctor public PhoneNumberUtils(); method public static void addTtsSpan(android.text.Spannable, int, int); + method public static boolean areSamePhoneNumber(@NonNull String, @NonNull String, @NonNull String); method @Deprecated public static String calledPartyBCDFragmentToString(byte[], int, int); method public static String calledPartyBCDFragmentToString(byte[], int, int, int); method @Deprecated public static String calledPartyBCDToString(byte[], int, int); method public static String calledPartyBCDToString(byte[], int, int, int); - method public static boolean compare(String, String); - method public static boolean compare(android.content.Context, String, String); + method @Deprecated public static boolean compare(String, String); + method @Deprecated public static boolean compare(android.content.Context, String, String); method public static String convertKeypadLettersToDigits(String); method public static android.text.style.TtsSpan createTtsSpan(String); method public static CharSequence createTtsSpannable(CharSequence); @@ -40554,10 +40570,10 @@ package android.telephony { public class PhoneStateListener { ctor public PhoneStateListener(); - ctor public PhoneStateListener(@NonNull java.util.concurrent.Executor); + ctor @Deprecated public PhoneStateListener(@NonNull java.util.concurrent.Executor); method public void onActiveDataSubscriptionIdChanged(int); method public void onBarringInfoChanged(@NonNull android.telephony.BarringInfo); - method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onCallDisconnectCauseChanged(int, int); + method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onCallDisconnectCauseChanged(int, int); method public void onCallForwardingIndicatorChanged(boolean); method public void onCallStateChanged(int, String); method public void onCellInfoChanged(java.util.List<android.telephony.CellInfo>); @@ -40565,36 +40581,140 @@ package android.telephony { method public void onDataActivity(int); method public void onDataConnectionStateChanged(int); method public void onDataConnectionStateChanged(int, int); - method @RequiresPermission("android.permission.READ_PHONE_STATE") public void onDisplayInfoChanged(@NonNull android.telephony.TelephonyDisplayInfo); + method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void onDisplayInfoChanged(@NonNull android.telephony.TelephonyDisplayInfo); method public void onEmergencyNumberListChanged(@NonNull java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>>); - method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo); + method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo); method public void onMessageWaitingIndicatorChanged(boolean); - method @RequiresPermission("android.permission.MODIFY_PHONE_STATE") public void onPreciseDataConnectionStateChanged(@NonNull android.telephony.PreciseDataConnectionState); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onPreciseDataConnectionStateChanged(@NonNull android.telephony.PreciseDataConnectionState); method public void onRegistrationFailed(@NonNull android.telephony.CellIdentity, @NonNull String, int, int, int); method public void onServiceStateChanged(android.telephony.ServiceState); method @Deprecated public void onSignalStrengthChanged(int); method public void onSignalStrengthsChanged(android.telephony.SignalStrength); method public void onUserMobileDataStateChanged(boolean); - field public static final int LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE = 4194304; // 0x400000 - field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_BARRING_INFO = -2147483648; // 0x80000000 - field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_DISCONNECT_CAUSES = 33554432; // 0x2000000 - field public static final int LISTEN_CALL_FORWARDING_INDICATOR = 8; // 0x8 - field public static final int LISTEN_CALL_STATE = 32; // 0x20 - field public static final int LISTEN_CELL_INFO = 1024; // 0x400 - field public static final int LISTEN_CELL_LOCATION = 16; // 0x10 - field public static final int LISTEN_DATA_ACTIVITY = 128; // 0x80 - field public static final int LISTEN_DATA_CONNECTION_STATE = 64; // 0x40 - field public static final int LISTEN_DISPLAY_INFO_CHANGED = 1048576; // 0x100000 - field public static final int LISTEN_EMERGENCY_NUMBER_LIST = 16777216; // 0x1000000 - field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 134217728; // 0x8000000 - field public static final int LISTEN_MESSAGE_WAITING_INDICATOR = 4; // 0x4 + field @Deprecated public static final int LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE = 4194304; // 0x400000 + field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_BARRING_INFO = -2147483648; // 0x80000000 + field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_CALL_DISCONNECT_CAUSES = 33554432; // 0x2000000 + field @Deprecated public static final int LISTEN_CALL_FORWARDING_INDICATOR = 8; // 0x8 + field @Deprecated public static final int LISTEN_CALL_STATE = 32; // 0x20 + field @Deprecated public static final int LISTEN_CELL_INFO = 1024; // 0x400 + field @Deprecated public static final int LISTEN_CELL_LOCATION = 16; // 0x10 + field @Deprecated public static final int LISTEN_DATA_ACTIVITY = 128; // 0x80 + field @Deprecated public static final int LISTEN_DATA_CONNECTION_STATE = 64; // 0x40 + field @Deprecated public static final int LISTEN_DISPLAY_INFO_CHANGED = 1048576; // 0x100000 + field @Deprecated public static final int LISTEN_EMERGENCY_NUMBER_LIST = 16777216; // 0x1000000 + field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 134217728; // 0x8000000 + field @Deprecated public static final int LISTEN_MESSAGE_WAITING_INDICATOR = 4; // 0x4 field public static final int LISTEN_NONE = 0; // 0x0 - field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 4096; // 0x1000 - field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_REGISTRATION_FAILURE = 1073741824; // 0x40000000 - field public static final int LISTEN_SERVICE_STATE = 1; // 0x1 + field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 4096; // 0x1000 + field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_REGISTRATION_FAILURE = 1073741824; // 0x40000000 + field @Deprecated public static final int LISTEN_SERVICE_STATE = 1; // 0x1 field @Deprecated public static final int LISTEN_SIGNAL_STRENGTH = 2; // 0x2 - field public static final int LISTEN_SIGNAL_STRENGTHS = 256; // 0x100 - field public static final int LISTEN_USER_MOBILE_DATA_STATE = 524288; // 0x80000 + field @Deprecated public static final int LISTEN_SIGNAL_STRENGTHS = 256; // 0x100 + field @Deprecated public static final int LISTEN_USER_MOBILE_DATA_STATE = 524288; // 0x80000 + } + + public static interface PhoneStateListener.ActiveDataSubscriptionIdChangedListener { + method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void onActiveDataSubscriptionIdChanged(int); + } + + public static interface PhoneStateListener.AlwaysReportedSignalStrengthChangedListener { + method @RequiresPermission("android.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH") public void onSignalStrengthsChanged(@NonNull android.telephony.SignalStrength); + } + + public static interface PhoneStateListener.BarringInfoChangedListener { + method @RequiresPermission(allOf={android.Manifest.permission.READ_PRECISE_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void onBarringInfoChanged(@NonNull android.telephony.BarringInfo); + } + + public static interface PhoneStateListener.CallDisconnectCauseChangedListener { + method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onCallDisconnectCauseChanged(int, int); + } + + public static interface PhoneStateListener.CallForwardingIndicatorChangedListener { + method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void onCallForwardingIndicatorChanged(boolean); + } + + public static interface PhoneStateListener.CallStateChangedListener { + method @RequiresPermission(android.Manifest.permission.READ_CALL_LOG) public void onCallStateChanged(int, @Nullable String); + } + + public static interface PhoneStateListener.CarrierNetworkChangeListener { + method public void onCarrierNetworkChange(boolean); + } + + public static interface PhoneStateListener.CellInfoChangedListener { + method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void onCellInfoChanged(@NonNull java.util.List<android.telephony.CellInfo>); + } + + public static interface PhoneStateListener.CellLocationChangedListener { + method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void onCellLocationChanged(@NonNull android.telephony.CellLocation); + } + + public static interface PhoneStateListener.DataActivationStateChangedListener { + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onDataActivationStateChanged(int); + } + + public static interface PhoneStateListener.DataActivityListener { + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onDataActivity(int); + } + + public static interface PhoneStateListener.DataConnectionStateChangedListener { + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onDataConnectionStateChanged(int, int); + } + + public static interface PhoneStateListener.DisplayInfoChangedListener { + method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void onDisplayInfoChanged(@NonNull android.telephony.TelephonyDisplayInfo); + } + + public static interface PhoneStateListener.EmergencyNumberListChangedListener { + method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void onEmergencyNumberListChanged(@NonNull java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>>); + } + + public static interface PhoneStateListener.ImsCallDisconnectCauseChangedListener { + method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo); + } + + public static interface PhoneStateListener.MessageWaitingIndicatorChangedListener { + method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void onMessageWaitingIndicatorChanged(boolean); + } + + public static interface PhoneStateListener.PhoneCapabilityChangedListener { + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onPhoneCapabilityChanged(@NonNull android.telephony.PhoneCapability); + } + + public static interface PhoneStateListener.PreciseDataConnectionStateChangedListener { + method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onPreciseDataConnectionStateChanged(@NonNull android.telephony.PreciseDataConnectionState); + } + + public static interface PhoneStateListener.RegistrationFailedListener { + method @RequiresPermission(allOf={android.Manifest.permission.READ_PRECISE_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void onRegistrationFailed(@NonNull android.telephony.CellIdentity, @NonNull String, int, int, int); + } + + public static interface PhoneStateListener.ServiceStateChangedListener { + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onServiceStateChanged(@NonNull android.telephony.ServiceState); + } + + public static interface PhoneStateListener.SignalStrengthsChangedListener { + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onSignalStrengthsChanged(@NonNull android.telephony.SignalStrength); + } + + public static interface PhoneStateListener.UserMobileDataStateChangedListener { + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onUserMobileDataStateChanged(boolean); + } + + public final class PhysicalChannelConfig implements android.os.Parcelable { + method public int describeContents(); + method public int getCellBandwidthDownlink(); + method public int getChannelNumber(); + method public int getConnectionStatus(); + method public int getNetworkType(); + method @IntRange(from=0, to=1007) public int getPhysicalCellId(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field public static final int CHANNEL_NUMBER_UNKNOWN = -1; // 0xffffffff + field public static final int CONNECTION_PRIMARY_SERVING = 1; // 0x1 + field public static final int CONNECTION_SECONDARY_SERVING = 2; // 0x2 + field public static final int CONNECTION_UNKNOWN = -1; // 0xffffffff + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhysicalChannelConfig> CREATOR; + field public static final int PHYSICAL_CELL_ID_UNKNOWN = -1; // 0xffffffff } public final class PreciseDataConnectionState implements android.os.Parcelable { @@ -41131,7 +41251,8 @@ package android.telephony { method public boolean isVoiceCapable(); method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle); method public boolean isWorldPhone(); - method public void listen(android.telephony.PhoneStateListener, int); + method @Deprecated public void listen(android.telephony.PhoneStateListener, int); + method public void registerPhoneStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.PhoneStateListener); method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void requestCellInfoUpdate(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback); method @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback); method public void sendDialerSpecialCode(String); @@ -41154,6 +41275,7 @@ package android.telephony { method @Deprecated public void setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri); method @Deprecated public void setVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle, boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void switchMultiSimConfig(int); + method public void unregisterPhoneStateListener(@NonNull android.telephony.PhoneStateListener); method public void updateAvailableNetworks(@NonNull java.util.List<android.telephony.AvailableNetworkInfo>, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>); field public static final String ACTION_CARRIER_MESSAGING_CLIENT_SERVICE = "android.telephony.action.CARRIER_MESSAGING_CLIENT_SERVICE"; field public static final String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL"; @@ -41175,6 +41297,7 @@ package android.telephony { field public static final int AUTHTYPE_EAP_SIM = 128; // 0x80 field public static final int CALL_COMPOSER_STATUS_OFF = 0; // 0x0 field public static final int CALL_COMPOSER_STATUS_ON = 1; // 0x1 + field public static final int CALL_COMPOSER_STATUS_ON_NO_PICTURES = 2; // 0x2 field public static final int CALL_STATE_IDLE = 0; // 0x0 field public static final int CALL_STATE_OFFHOOK = 2; // 0x2 field public static final int CALL_STATE_RINGING = 1; // 0x1 diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 03e80fc4a7c7..e768ea6ed560 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -9813,17 +9813,87 @@ package android.telephony { method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber, int); method @Deprecated public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber); method public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber, int); - method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState); + method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState); method public void onRadioPowerStateChanged(int); method public void onSrvccStateChanged(int); method public void onVoiceActivationStateChanged(int); - field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 67108864; // 0x4000000 - field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 268435456; // 0x10000000 - field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000 - field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_CALL_STATE = 2048; // 0x800 - field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 8388608; // 0x800000 - field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_SRVCC_STATE_CHANGED = 16384; // 0x4000 - field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_VOICE_ACTIVATION_STATE = 131072; // 0x20000 + field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED = 23; // 0x17 + field @RequiresPermission("android.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH") public static final int EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED = 10; // 0xa + field @RequiresPermission(allOf={android.Manifest.permission.READ_PRECISE_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public static final int EVENT_BARRING_INFO_CHANGED = 32; // 0x20 + field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_CALL_ATTRIBUTES_CHANGED = 27; // 0x1b + field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_CALL_DISCONNECT_CAUSE_CHANGED = 26; // 0x1a + field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_CALL_FORWARDING_INDICATOR_CHANGED = 4; // 0x4 + field @RequiresPermission(android.Manifest.permission.READ_CALL_LOG) public static final int EVENT_CALL_STATE_CHANGED = 6; // 0x6 + field public static final int EVENT_CARRIER_NETWORK_CHANGED = 17; // 0x11 + field @RequiresPermission(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 + field public static final int EVENT_DATA_ACTIVITY_CHANGED = 8; // 0x8 + field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_DATA_CONNECTION_REAL_TIME_INFO_CHANGED = 14; // 0xe + field public static final int EVENT_DATA_CONNECTION_STATE_CHANGED = 7; // 0x7 + field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_DATA_ENABLED_CHANGED = 34; // 0x22 + field public static final int EVENT_DISPLAY_INFO_CHANGED = 21; // 0x15 + field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_EMERGENCY_NUMBER_LIST_CHANGED = 25; // 0x19 + field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED = 28; // 0x1c + field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_MESSAGE_WAITING_INDICATOR_CHANGED = 3; // 0x3 + field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int EVENT_OEM_HOOK_RAW = 15; // 0xf + field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int EVENT_OUTGOING_EMERGENCY_CALL = 29; // 0x1d + field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int EVENT_OUTGOING_EMERGENCY_SMS = 30; // 0x1e + field public static final int EVENT_PHONE_CAPABILITY_CHANGED = 22; // 0x16 + field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED = 33; // 0x21 + field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_PRECISE_CALL_STATE_CHANGED = 12; // 0xc + 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 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 + field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int EVENT_SRVCC_STATE_CHANGED = 16; // 0x10 + field public static final int EVENT_USER_MOBILE_DATA_STATE_CHANGED = 20; // 0x14 + field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int EVENT_VOICE_ACTIVATION_STATE_CHANGED = 18; // 0x12 + field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 67108864; // 0x4000000 + field @Deprecated @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 268435456; // 0x10000000 + field @Deprecated @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000 + field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_PRECISE_CALL_STATE = 2048; // 0x800 + field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 8388608; // 0x800000 + field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_SRVCC_STATE_CHANGED = 16384; // 0x4000 + field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_VOICE_ACTIVATION_STATE = 131072; // 0x20000 + } + + public static interface PhoneStateListener.CallAttributesChangedListener { + method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onCallAttributesChanged(@NonNull android.telephony.CallAttributes); + } + + public static interface PhoneStateListener.DataEnabledChangedListener { + method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onDataEnabledChanged(boolean, int); + } + + public static interface PhoneStateListener.OutgoingEmergencyCallListener { + method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber, int); + } + + public static interface PhoneStateListener.OutgoingEmergencySmsListener { + method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber, int); + } + + public static interface PhoneStateListener.PhysicalChannelConfigChangedListener { + method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onPhysicalChannelConfigChanged(@NonNull java.util.List<android.telephony.PhysicalChannelConfig>); + } + + public static interface PhoneStateListener.PreciseCallStateChangedListener { + method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState); + } + + public static interface PhoneStateListener.RadioPowerStateChangedListener { + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void onRadioPowerStateChanged(int); + } + + public static interface PhoneStateListener.SrvccStateChangedListener { + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void onSrvccStateChanged(int); + } + + public static interface PhoneStateListener.VoiceActivationStateChangedListener { + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void onVoiceActivationStateChanged(int); } public final class PinResult implements android.os.Parcelable { diff --git a/core/java/android/app/search/OWNERS b/core/java/android/app/search/OWNERS new file mode 100644 index 000000000000..92835c2b0626 --- /dev/null +++ b/core/java/android/app/search/OWNERS @@ -0,0 +1,2 @@ +hyunyoungs@google.com +sfufa@google.com diff --git a/core/java/android/content/pm/OWNERS b/core/java/android/content/pm/OWNERS index fd32efccbcec..f0def80505ce 100644 --- a/core/java/android/content/pm/OWNERS +++ b/core/java/android/content/pm/OWNERS @@ -6,5 +6,6 @@ patb@google.com per-file PackageParser.java = chiuwinson@google.com per-file *Shortcut* = file:/core/java/android/content/pm/SHORTCUT_OWNERS +per-file AppSearchPerson.java = file:/core/java/android/content/pm/SHORTCUT_OWNERS per-file *Launcher* = file:/core/java/android/content/pm/LAUNCHER_OWNERS per-file UserInfo* = file:/MULTIUSER_OWNERS diff --git a/core/java/android/net/vcn/VcnTransportInfo.java b/core/java/android/net/vcn/VcnTransportInfo.java new file mode 100644 index 000000000000..4d8cf91621ba --- /dev/null +++ b/core/java/android/net/vcn/VcnTransportInfo.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.vcn; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.net.TransportInfo; +import android.net.wifi.WifiInfo; +import android.os.Parcel; +import android.os.Parcelable; +import android.telephony.SubscriptionManager; + +import java.util.Objects; + +/** + * VcnTransportInfo contains information about the VCN's underlying transports for SysUi. + * + * <p>Presence of this class in the NetworkCapabilities.TransportInfo implies that the network is a + * VCN. + * + * <p>VcnTransportInfo must exist on top of either an underlying Wifi or Cellular Network. If the + * underlying Network is WiFi, the subId will be {@link + * SubscriptionManager#INVALID_SUBSCRIPTION_ID}. If the underlying Network is Cellular, the WifiInfo + * will be {@code null}. + * + * @hide + */ +public class VcnTransportInfo implements TransportInfo, Parcelable { + @Nullable private final WifiInfo mWifiInfo; + private final int mSubId; + + public VcnTransportInfo(@NonNull WifiInfo wifiInfo) { + this(wifiInfo, SubscriptionManager.INVALID_SUBSCRIPTION_ID); + } + + public VcnTransportInfo(int subId) { + this(null /* wifiInfo */, subId); + } + + private VcnTransportInfo(@Nullable WifiInfo wifiInfo, int subId) { + if (wifiInfo == null && subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + throw new IllegalArgumentException( + "VcnTransportInfo requires either non-null WifiInfo or valid subId"); + } + + mWifiInfo = wifiInfo; + mSubId = subId; + } + + /** + * Get the {@link WifiInfo} for this VcnTransportInfo. + * + * <p>If the underlying Network for the associated VCN is Cellular, returns null. + * + * @return the WifiInfo if there is an underlying WiFi connection, else null. + */ + @Nullable + public WifiInfo getWifiInfo() { + return mWifiInfo; + } + + /** + * Get the subId for the VCN Network associated with this VcnTransportInfo. + * + * <p>If the underlying Network for the associated VCN is WiFi, returns {@link + * SubscriptionManager#INVALID_SUBSCRIPTION_ID}. + * + * @return the Subscription ID if a cellular underlying Network is present, else {@link + * android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID}. + */ + public int getSubId() { + return mSubId; + } + + @Override + public int hashCode() { + return Objects.hash(mWifiInfo, mSubId); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof VcnTransportInfo)) return false; + final VcnTransportInfo that = (VcnTransportInfo) o; + + return Objects.equals(mWifiInfo, that.mWifiInfo) && mSubId == that.mSubId; + } + + /** {@inheritDoc} */ + @Override + public int describeContents() { + return 0; + } + + /** {@inheritDoc} */ + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) {} + + /** Implement the Parcelable interface */ + public static final @NonNull Creator<VcnTransportInfo> CREATOR = + new Creator<VcnTransportInfo>() { + public VcnTransportInfo createFromParcel(Parcel in) { + // return null instead of a default VcnTransportInfo to avoid leaking + // information about this being a VCN Network (instead of macro cellular, etc) + return null; + } + + public VcnTransportInfo[] newArray(int size) { + return new VcnTransportInfo[size]; + } + }; +} diff --git a/core/java/android/service/search/OWNERS b/core/java/android/service/search/OWNERS new file mode 100644 index 000000000000..92835c2b0626 --- /dev/null +++ b/core/java/android/service/search/OWNERS @@ -0,0 +1,2 @@ +hyunyoungs@google.com +sfufa@google.com diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java index d6ae434af9d5..03d3755111aa 100644 --- a/core/java/android/telephony/PhoneStateListener.java +++ b/core/java/android/telephony/PhoneStateListener.java @@ -17,7 +17,10 @@ package android.telephony; import android.Manifest; +import android.annotation.CallbackExecutor; +import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.TestApi; @@ -29,9 +32,16 @@ import android.os.Handler; import android.os.HandlerExecutor; import android.os.Looper; import android.telephony.Annotation.CallState; +import android.telephony.Annotation.DataActivityType; +import android.telephony.Annotation.DisconnectCauses; +import android.telephony.Annotation.NetworkType; +import android.telephony.Annotation.PreciseDisconnectCauses; import android.telephony.Annotation.RadioPowerState; import android.telephony.Annotation.SimActivationState; import android.telephony.Annotation.SrvccState; +import android.telephony.NetworkRegistrationInfo.Domain; +import android.telephony.TelephonyManager.DataEnabledReason; +import android.telephony.TelephonyManager.DataState; import android.telephony.emergency.EmergencyNumber; import android.telephony.ims.ImsReasonInfo; @@ -40,6 +50,8 @@ import com.android.internal.telephony.IPhoneStateListener; import dalvik.system.VMRuntime; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; import java.util.List; import java.util.Map; @@ -114,7 +126,9 @@ public class PhoneStateListener { * * @see #onServiceStateChanged * @see ServiceState + * @deprecated Use {@link ServiceStateChangedListener} instead. */ + @Deprecated public static final int LISTEN_SERVICE_STATE = 0x00000001; /** @@ -122,8 +136,7 @@ public class PhoneStateListener { * {@more} * * @see #onSignalStrengthChanged - * - * @deprecated by {@link #LISTEN_SIGNAL_STRENGTHS} + * @deprecated Use {@link SignalStrengthsChangedListener} instead. */ @Deprecated public static final int LISTEN_SIGNAL_STRENGTH = 0x00000002; @@ -139,7 +152,9 @@ public class PhoneStateListener { * voicemail icon. * * @see #onMessageWaitingIndicatorChanged + * @deprecated Use {@link MessageWaitingIndicatorChangedListener} instead. */ + @Deprecated public static final int LISTEN_MESSAGE_WAITING_INDICATOR = 0x00000004; /** @@ -150,7 +165,9 @@ public class PhoneStateListener { * {@link TelephonyManager#hasCarrierPrivileges}). * * @see #onCallForwardingIndicatorChanged + * @deprecated Use {@link CallForwardingIndicatorChangedListener} instead. */ + @Deprecated public static final int LISTEN_CALL_FORWARDING_INDICATOR = 0x00000008; /** @@ -166,7 +183,9 @@ public class PhoneStateListener { * instead. * * @see #onCellLocationChanged + * @deprecated Use {@link CellLocationChangedListener} instead. */ + @Deprecated public static final int LISTEN_CELL_LOCATION = 0x00000010; /** @@ -174,14 +193,18 @@ public class PhoneStateListener { * {@more} * * @see #onCallStateChanged + * @deprecated Use {@link CallStateChangedListener} instead. */ + @Deprecated public static final int LISTEN_CALL_STATE = 0x00000020; /** * Listen for changes to the data connection state (cellular). * * @see #onDataConnectionStateChanged + * @deprecated Use {@link DataConnectionStateChangedListener} instead. */ + @Deprecated public static final int LISTEN_DATA_CONNECTION_STATE = 0x00000040; /** @@ -192,7 +215,9 @@ public class PhoneStateListener { * data-traffic icon. * * @see #onDataActivity + * @deprecated Use {@link DataActivityListener} instead. */ + @Deprecated public static final int LISTEN_DATA_ACTIVITY = 0x00000080; /** @@ -202,7 +227,9 @@ public class PhoneStateListener { * icon. * * @see #onSignalStrengthsChanged + * @deprecated Use {@link SignalStrengthsChangedListener} instead. */ + @Deprecated public static final int LISTEN_SIGNAL_STRENGTHS = 0x00000100; /** @@ -212,7 +239,9 @@ public class PhoneStateListener { * @see #onSignalStrengthsChanged * * @hide + * @deprecated Use {@link AlwaysReportedSignalStrengthChangedListener} instead. */ + @Deprecated @RequiresPermission(android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) public static final int LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH = 0x00000200; @@ -223,7 +252,9 @@ public class PhoneStateListener { * permission. * * @see #onCellInfoChanged + * @deprecated Use {@link CellInfoChangedListener} instead. */ + @Deprecated public static final int LISTEN_CELL_INFO = 0x00000400; /** @@ -235,8 +266,10 @@ public class PhoneStateListener { * (see {@link TelephonyManager#hasCarrierPrivileges}). * * @hide + * @deprecated Use {@link PreciseCallStateChangedListener} instead. */ - @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE)) + @Deprecated + @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) @SystemApi public static final int LISTEN_PRECISE_CALL_STATE = 0x00000800; @@ -248,8 +281,10 @@ public class PhoneStateListener { * (see {@link TelephonyManager#hasCarrierPrivileges}). * * @see #onPreciseDataConnectionStateChanged + * @deprecated Use {@link PreciseDataConnectionStateChangedListener} instead. */ - @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE)) + @Deprecated + @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 0x00001000; /** @@ -259,7 +294,7 @@ public class PhoneStateListener { * READ_PRECISE_PHONE_STATE} * @see #onDataConnectionRealTimeInfoChanged(DataConnectionRealTimeInfo) * - * @deprecated Use {@link TelephonyManager#getModemActivityInfo()} + * @deprecated Use {@link TelephonyManager#requestModemActivityInfo} instead. * @hide */ @Deprecated @@ -272,7 +307,9 @@ public class PhoneStateListener { * * @see #onServiceStateChanged(ServiceState) * @hide + * @deprecated Use {@link SrvccStateChangedListener} instead. */ + @Deprecated @SystemApi @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_SRVCC_STATE_CHANGED = 0x00004000; @@ -290,10 +327,11 @@ public class PhoneStateListener { /** * Listen for carrier network changes indicated by a carrier app. * - * @see #onCarrierNetworkRequest - * @see TelephonyManager#notifyCarrierNetworkChange(boolean) + * @see android.service.carrier.CarrierService#notifyCarrierNetworkChange(boolean) * @hide + * @deprecated Use {@link CarrierNetworkChangeListener} instead. */ + @Deprecated public static final int LISTEN_CARRIER_NETWORK_CHANGE = 0x00010000; /** @@ -312,7 +350,9 @@ public class PhoneStateListener { * * @see #onVoiceActivationStateChanged * @hide + * @deprecated Use {@link VoiceActivationStateChangedListener} instead. */ + @Deprecated @SystemApi @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_VOICE_ACTIVATION_STATE = 0x00020000; @@ -324,20 +364,24 @@ public class PhoneStateListener { * @see TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED * @see TelephonyManager#SIM_ACTIVATION_STATE_RESTRICTED * @see TelephonyManager#SIM_ACTIVATION_STATE_UNKNOWN - * {@more} + * * Example: TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED indicates data service has been * fully activated * * @see #onDataActivationStateChanged * @hide + * @deprecated Use {@link DataActivationStateChangedListener} instead. */ + @Deprecated public static final int LISTEN_DATA_ACTIVATION_STATE = 0x00040000; /** * Listen for changes to the user mobile data state * * @see #onUserMobileDataStateChanged + * @deprecated Use {@link UserMobileDataStateChangedListener} instead. */ + @Deprecated public static final int LISTEN_USER_MOBILE_DATA_STATE = 0x00080000; /** @@ -348,7 +392,9 @@ public class PhoneStateListener { * {@link TelephonyManager#hasCarrierPrivileges}). * * @see #onDisplayInfoChanged + * @deprecated Use {@link DisplayInfoChangedListener} instead. */ + @Deprecated public static final int LISTEN_DISPLAY_INFO_CHANGED = 0x00100000; /** @@ -356,7 +402,9 @@ public class PhoneStateListener { * * @see #onPhoneCapabilityChanged * @hide + * @deprecated Use {@link PhoneCapabilityChangedListener} instead. */ + @Deprecated public static final int LISTEN_PHONE_CAPABILITY_CHANGE = 0x00200000; /** @@ -366,17 +414,19 @@ public class PhoneStateListener { * subscription user selected as default data subscription in DSDS mode. * * @see #onActiveDataSubscriptionIdChanged + * @deprecated Use {@link ActiveDataSubscriptionIdChangedListener} instead. */ + @Deprecated public static final int LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE = 0x00400000; /** * Listen for changes to the radio power state. * - * <p>Requires permission {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} - * * @see #onRadioPowerStateChanged * @hide + * @deprecated Use {@link RadioPowerStateChangedListener} instead. */ + @Deprecated @SystemApi @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 0x00800000; @@ -386,7 +436,10 @@ public class PhoneStateListener { * * <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling * app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}). + * + * @deprecated Use {@link EmergencyNumberListChangedListener} instead. */ + @Deprecated public static final int LISTEN_EMERGENCY_NUMBER_LIST = 0x01000000; /** @@ -397,8 +450,10 @@ public class PhoneStateListener { * or the calling app has carrier privileges * (see {@link TelephonyManager#hasCarrierPrivileges}). * + * @deprecated Use {@link CallDisconnectCauseChangedListener} instead. */ - @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE)) + @Deprecated + @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_CALL_DISCONNECT_CAUSES = 0x02000000; /** @@ -410,9 +465,11 @@ public class PhoneStateListener { * * @see #onCallAttributesChanged * @hide + * @deprecated Use {@link CallAttributesChangedListener} instead. */ + @Deprecated @SystemApi - @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE)) + @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 0x04000000; /** @@ -424,18 +481,20 @@ public class PhoneStateListener { * (see {@link TelephonyManager#hasCarrierPrivileges}). * * @see #onImsCallDisconnectCauseChanged(ImsReasonInfo) + * @deprecated Use {@link ImsCallDisconnectCauseChangedListener} instead. */ - @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE)) + @Deprecated + @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 0x08000000; /** * Listen for the emergency number placed from an outgoing call. * - * <p>Requires permission {@link android.Manifest.permission#READ_ACTIVE_EMERGENCY_SESSION} - * * @see #onOutgoingEmergencyCall * @hide + * @deprecated Use {@link OutgoingEmergencyCallListener} instead. */ + @Deprecated @SystemApi @RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 0x10000000; @@ -443,11 +502,11 @@ public class PhoneStateListener { /** * Listen for the emergency number placed from an outgoing SMS. * - * <p>Requires permission {@link android.Manifest.permission#READ_ACTIVE_EMERGENCY_SESSION} - * * @see #onOutgoingEmergencySms * @hide + * @deprecated Use {@link OutgoingEmergencySmsListener} instead. */ + @Deprecated @SystemApi @RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 0x20000000; @@ -466,7 +525,9 @@ public class PhoneStateListener { * of whether the calling app has carrier privileges. * * @see #onRegistrationFailed + * @deprecated Use {@link RegistrationFailedListener} instead. */ + @Deprecated @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_REGISTRATION_FAILURE = 0x40000000; @@ -480,10 +541,525 @@ public class PhoneStateListener { * of whether the calling app has carrier privileges. * * @see #onBarringInfoChanged + * @deprecated Use {@link BarringInfoChangedListener} instead. */ + @Deprecated @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_BARRING_INFO = 0x80000000; + /** + * Event for changes to the network service state (cellular). + * + * @see ServiceStateChangedListener#onServiceStateChanged + * @see ServiceState + * + * @hide + */ + @SystemApi + public static final int EVENT_SERVICE_STATE_CHANGED = 1; + + /** + * Event for changes to the network signal strength (cellular). + * + * @see SignalStrengthsChangedListener#onSignalStrengthsChanged + * + * @hide + */ + @SystemApi + public static final int EVENT_SIGNAL_STRENGTH_CHANGED = 2; + + /** + * Event for changes to the message-waiting indicator. + * + * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE} or that + * the calling app has carrier privileges (see + * {@link TelephonyManager#hasCarrierPrivileges}). + * <p> + * Example: The status bar uses this to determine when to display the + * voicemail icon. + * + * @see MessageWaitingIndicatorChangedListener#onMessageWaitingIndicatorChanged + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) + public static final int EVENT_MESSAGE_WAITING_INDICATOR_CHANGED = 3; + + /** + * Event for changes to the call-forwarding indicator. + * + * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE} or that + * the calling app has carrier privileges (see + * {@link TelephonyManager#hasCarrierPrivileges}). + * + * @see CallForwardingIndicatorChangedListener#onCallForwardingIndicatorChanged + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) + public static final int EVENT_CALL_FORWARDING_INDICATOR_CHANGED = 4; + + /** + * Event for changes to the device's cell location. Note that + * this will result in frequent callbacks to the listener. + * + * If you need regular location updates but want more control over + * the update interval or location precision, you can set up a listener + * through the {@link android.location.LocationManager location manager} + * instead. + * + * @see CellLocationChangedListener#onCellLocationChanged + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) + public static final int EVENT_CELL_LOCATION_CHANGED = 5; + + /** + * Event for changes to the device call state. + * + * @see CallStateChangedListener#onCallStateChanged + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.READ_CALL_LOG) + public static final int EVENT_CALL_STATE_CHANGED = 6; + + /** + * Event for changes to the data connection state (cellular). + * + * @see DataConnectionStateChangedListener#onDataConnectionStateChanged + * + * @hide + */ + @SystemApi + public static final int EVENT_DATA_CONNECTION_STATE_CHANGED = 7; + + /** + * Event for changes to the direction of data traffic on the data + * connection (cellular). + * + * Example: The status bar uses this to display the appropriate + * data-traffic icon. + * + * @see DataActivityListener#onDataActivity + * + * @hide + */ + @SystemApi + public static final int EVENT_DATA_ACTIVITY_CHANGED = 8; + + /** + * Event for changes to the network signal strengths (cellular). + * <p> + * Example: The status bar uses this to control the signal-strength + * icon. + * + * @see SignalStrengthsChangedListener#onSignalStrengthsChanged + * + * @hide + */ + @SystemApi + public static final int EVENT_SIGNAL_STRENGTHS_CHANGED = 9; + + /** + * Event for changes of the network signal strengths (cellular) always reported from modem, + * even in some situations such as the screen of the device is off. + * + * @see AlwaysReportedSignalStrengthChangedListener#onSignalStrengthsChanged + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) + public static final int EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED = 10; + + /** + * Event for changes to observed cell info. + * + * @see CellInfoChangedListener#onCellInfoChanged + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) + public static final int EVENT_CELL_INFO_CHANGED = 11; + + /** + * Event for {@link android.telephony.Annotation.PreciseCallStates} of ringing, + * background and foreground calls. + * + * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} + * or the calling app has carrier privileges + * (see {@link TelephonyManager#hasCarrierPrivileges}). + * + * @see PreciseCallStateChangedListener#onPreciseCallStateChanged + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) + public static final int EVENT_PRECISE_CALL_STATE_CHANGED = 12; + + /** + * Event for {@link PreciseDataConnectionState} on the data connection (cellular). + * + * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} + * or the calling app has carrier privileges + * (see {@link TelephonyManager#hasCarrierPrivileges}). + * + * @see PreciseDataConnectionStateChangedListener#onPreciseDataConnectionStateChanged + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) + public static final int EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED = 13; + + /** + * Event for real time info for all data connections (cellular)). + * + * @see #onDataConnectionRealTimeInfoChanged(DataConnectionRealTimeInfo) + * + * @deprecated Use {@link TelephonyManager#requestModemActivityInfo} + * @hide + */ + @Deprecated + @SystemApi + @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) + public static final int EVENT_DATA_CONNECTION_REAL_TIME_INFO_CHANGED = 14; + + /** + * Event for OEM hook raw event + * + * @see #onOemHookRawEvent + * + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public static final int EVENT_OEM_HOOK_RAW = 15; + + /** + * Event for changes to the SRVCC state of the active call. + * + * @see SrvccStateChangedListener#onSrvccStateChanged + * + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public static final int EVENT_SRVCC_STATE_CHANGED = 16; + + /** + * Event for carrier network changes indicated by a carrier app. + * + * @see android.service.carrier.CarrierService#notifyCarrierNetworkChange(boolean) + * @see CarrierNetworkChangeListener#onCarrierNetworkChange + * + * @hide + */ + @SystemApi + public static final int EVENT_CARRIER_NETWORK_CHANGED = 17; + + /** + * Event for changes to the sim voice activation state + * + * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATING + * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED + * @see TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED + * @see TelephonyManager#SIM_ACTIVATION_STATE_RESTRICTED + * @see TelephonyManager#SIM_ACTIVATION_STATE_UNKNOWN + * + * Example: TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED indicates voice service has been + * fully activated + * + * @see VoiceActivationStateChangedListener#onVoiceActivationStateChanged + * + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public static final int EVENT_VOICE_ACTIVATION_STATE_CHANGED = 18; + + /** + * Event for changes to the sim data activation state + * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATING + * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED + * @see TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED + * @see TelephonyManager#SIM_ACTIVATION_STATE_RESTRICTED + * @see TelephonyManager#SIM_ACTIVATION_STATE_UNKNOWN + * + * Example: TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED indicates data service has been + * fully activated + * + * @see DataActivationStateChangedListener#onDataActivationStateChanged + * @hide + */ + @SystemApi + public static final int EVENT_DATA_ACTIVATION_STATE_CHANGED = 19; + + /** + * Event for changes to the user mobile data state + * + * @see UserMobileDataStateChangedListener#onUserMobileDataStateChanged + * + * @hide + */ + @SystemApi + public static final int EVENT_USER_MOBILE_DATA_STATE_CHANGED = 20; + + /** + * Event for display info changed event. + * + * @see DisplayInfoChangedListener#onDisplayInfoChanged + * + * @hide + */ + @SystemApi + public static final int EVENT_DISPLAY_INFO_CHANGED = 21; + + /** + * Event for changes to the phone capability. + * + * @see PhoneCapabilityChangedListener#onPhoneCapabilityChanged + * + * @hide + */ + @SystemApi + public static final int EVENT_PHONE_CAPABILITY_CHANGED = 22; + + /** + * Event for changes to active data subscription ID. Active data subscription is + * the current subscription used to setup Cellular Internet data. For example, + * it could be the current active opportunistic subscription in use, or the + * subscription user selected as default data subscription in DSDS mode. + * + * <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling + * app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}). + * + * @see ActiveDataSubscriptionIdChangedListener#onActiveDataSubscriptionIdChanged + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) + public static final int EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED = 23; + + /** + * Event for changes to the radio power state. + * + * @see RadioPowerStateChangedListener#onRadioPowerStateChanged + * + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public static final int EVENT_RADIO_POWER_STATE_CHANGED = 24; + + /** + * Event for changes to emergency number list based on all active subscriptions. + * + * <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling + * app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}). + * + * @see EmergencyNumberListChangedListener#onEmergencyNumberListChanged + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) + public static final int EVENT_EMERGENCY_NUMBER_LIST_CHANGED = 25; + + /** + * Event for call disconnect causes which contains {@link DisconnectCause} and + * {@link PreciseDisconnectCause}. + * + * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} + * or the calling app has carrier privileges + * (see {@link TelephonyManager#hasCarrierPrivileges}). + * + * @see CallDisconnectCauseChangedListener#onCallDisconnectCauseChanged + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) + public static final int EVENT_CALL_DISCONNECT_CAUSE_CHANGED = 26; + + /** + * Event for changes to the call attributes of a currently active call. + * + * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} + * or the calling app has carrier privileges + * (see {@link TelephonyManager#hasCarrierPrivileges}). + * + * @see CallAttributesChangedListener#onCallAttributesChanged + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) + public static final int EVENT_CALL_ATTRIBUTES_CHANGED = 27; + + /** + * Event for IMS call disconnect causes which contains + * {@link android.telephony.ims.ImsReasonInfo} + * + * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} + * or the calling app has carrier privileges + * (see {@link TelephonyManager#hasCarrierPrivileges}). + * + * @see ImsCallDisconnectCauseChangedListener#onImsCallDisconnectCauseChanged(ImsReasonInfo) + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) + public static final int EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED = 28; + + /** + * Event for the emergency number placed from an outgoing call. + * + * @see OutgoingEmergencyCallListener#onOutgoingEmergencyCall + * + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) + public static final int EVENT_OUTGOING_EMERGENCY_CALL = 29; + + /** + * Event for the emergency number placed from an outgoing SMS. + * + * @see OutgoingEmergencySmsListener#onOutgoingEmergencySms + * + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) + public static final int EVENT_OUTGOING_EMERGENCY_SMS = 30; + + /** + * Event for registration failures. + * + * Event for indications that a registration procedure has failed in either the CS or PS + * domain. This indication does not necessarily indicate a change of service state, which should + * be tracked via {@link #EVENT_SERVICE_STATE_CHANGED}. + * + * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} or + * the calling app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}). + * + * <p>Also requires the {@link Manifest.permission#ACCESS_FINE_LOCATION} permission, regardless + * of whether the calling app has carrier privileges. + * + * @see RegistrationFailedListener#onRegistrationFailed + * + * @hide + */ + @SystemApi + @RequiresPermission(allOf = { + Manifest.permission.READ_PRECISE_PHONE_STATE, + Manifest.permission.ACCESS_FINE_LOCATION + }) + public static final int EVENT_REGISTRATION_FAILURE = 31; + + /** + * Event for Barring Information for the current registered / camped cell. + * + * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} or + * the calling app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}). + * + * <p>Also requires the {@link Manifest.permission#ACCESS_FINE_LOCATION} permission, regardless + * of whether the calling app has carrier privileges. + * + * @see BarringInfoChangedListener#onBarringInfoChanged + * + * @hide + */ + @SystemApi + @RequiresPermission(allOf = { + Manifest.permission.READ_PRECISE_PHONE_STATE, + Manifest.permission.ACCESS_FINE_LOCATION + }) + public static final int EVENT_BARRING_INFO_CHANGED = 32; + + /** + * Event for changes to the physical channel configuration. + * + * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} + * or the calling app has carrier privileges + * (see {@link TelephonyManager#hasCarrierPrivileges}). + * + * @see PhysicalChannelConfigChangedListener#onPhysicalChannelConfigChanged + * + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE) + public static final int EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED = 33; + + /** + * Event for changes to the data enabled. + * + * Event for indications that the enabled status of current data has changed. + * + * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} + * or the calling app has carrier privileges + * (see {@link TelephonyManager#hasCarrierPrivileges}). + * + * @see DataEnabledChangedListener#onDataEnabledChanged + * + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE) + public static final int EVENT_DATA_ENABLED_CHANGED = 34; + + /** @hide */ + @IntDef(prefix = { "EVENT_" }, value = { + EVENT_SERVICE_STATE_CHANGED, + EVENT_SIGNAL_STRENGTH_CHANGED, + EVENT_MESSAGE_WAITING_INDICATOR_CHANGED, + EVENT_CALL_FORWARDING_INDICATOR_CHANGED, + EVENT_CELL_LOCATION_CHANGED, + EVENT_CALL_STATE_CHANGED, + EVENT_DATA_CONNECTION_STATE_CHANGED, + EVENT_DATA_ACTIVITY_CHANGED, + EVENT_SIGNAL_STRENGTHS_CHANGED, + EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED, + EVENT_CELL_INFO_CHANGED, + EVENT_PRECISE_CALL_STATE_CHANGED, + EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED, + EVENT_DATA_CONNECTION_REAL_TIME_INFO_CHANGED, + EVENT_OEM_HOOK_RAW, + EVENT_SRVCC_STATE_CHANGED, + EVENT_CARRIER_NETWORK_CHANGED, + EVENT_VOICE_ACTIVATION_STATE_CHANGED, + EVENT_DATA_ACTIVATION_STATE_CHANGED, + EVENT_USER_MOBILE_DATA_STATE_CHANGED, + EVENT_DISPLAY_INFO_CHANGED, + EVENT_PHONE_CAPABILITY_CHANGED, + EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED, + EVENT_RADIO_POWER_STATE_CHANGED, + EVENT_EMERGENCY_NUMBER_LIST_CHANGED, + EVENT_CALL_DISCONNECT_CAUSE_CHANGED, + EVENT_CALL_ATTRIBUTES_CHANGED, + EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED, + EVENT_OUTGOING_EMERGENCY_CALL, + EVENT_OUTGOING_EMERGENCY_SMS, + EVENT_REGISTRATION_FAILURE, + EVENT_BARRING_INFO_CHANGED, + EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED, + EVENT_DATA_ENABLED_CHANGED + }) + @Retention(RetentionPolicy.SOURCE) + public @interface TelephonyEvent {} + /* * Subscription used to listen to the phone state changes * @hide @@ -495,13 +1071,19 @@ public class PhoneStateListener { /** * @hide */ + //TODO: The maxTargetSdk should be S if the build time tool updates it. @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - @UnsupportedAppUsage - public final IPhoneStateListener callback; + @UnsupportedAppUsage( + maxTargetSdk = Build.VERSION_CODES.R, + publicAlternatives = "Use {@code TelephonyManager#registerPhoneStateListener(" + + "Executor, PhoneStateListener)} instead") + public IPhoneStateListener callback; /** * Create a PhoneStateListener for the Phone with the default subscription. - * This class requires Looper.myLooper() not return null. + * If this is created for use with deprecated API + * {@link TelephonyManager#listen(PhoneStateListener, int)}, then this class requires + * Looper.myLooper() not return null. */ public PhoneStateListener() { this(null, Looper.myLooper()); @@ -539,7 +1121,10 @@ public class PhoneStateListener { */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public PhoneStateListener(Integer subId, Looper looper) { - this(subId, new HandlerExecutor(new Handler(looper))); + if (looper != null) { + setExecutor(new HandlerExecutor(new Handler(looper))); + } + mSubId = subId; if (subId != null && VMRuntime.getRuntime().getTargetSdkVersion() >= Build.VERSION_CODES.Q) { throw new IllegalArgumentException("PhoneStateListener with subId: " @@ -554,17 +1139,744 @@ public class PhoneStateListener { * The Executor must not be null. * * @param executor a non-null Executor that will execute callbacks for the PhoneStateListener. + * @deprecated Use + * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)} instead. */ + @Deprecated public PhoneStateListener(@NonNull Executor executor) { - this(null, executor); + setExecutor(executor); + mSubId = null; } - private PhoneStateListener(Integer subId, Executor e) { - if (e == null) { + private @NonNull Executor mExecutor; + + /** + * @hide + */ + public void setExecutor(@NonNull @CallbackExecutor Executor executor) { + if (executor == null) { throw new IllegalArgumentException("PhoneStateListener Executor must be non-null"); } - mSubId = subId; - callback = new IPhoneStateListenerStub(this, e); + mExecutor = executor; + callback = new IPhoneStateListenerStub(this, mExecutor); + } + + /** + * @hide + */ + public boolean isExecutorSet() { + return mExecutor != null; + } + + /** + * Interface for service state listener. + */ + public interface ServiceStateChangedListener { + /** + * Callback invoked when device service state changes on the registered subscription. + * Note, the registration subscription ID comes from {@link TelephonyManager} object + * which registers PhoneStateListener by + * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}. + * If this TelephonyManager object was created with + * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the + * subscription ID. Otherwise, this callback applies to + * {@link SubscriptionManager#getDefaultSubscriptionId()}. + * + * The instance of {@link ServiceState} passed as an argument here will have various + * levels of location information stripped from it depending on the location permissions + * that your app holds. + * Only apps holding the {@link Manifest.permission#ACCESS_FINE_LOCATION} permission will + * receive all the information in {@link ServiceState}. + * + * @see ServiceState#STATE_EMERGENCY_ONLY + * @see ServiceState#STATE_IN_SERVICE + * @see ServiceState#STATE_OUT_OF_SERVICE + * @see ServiceState#STATE_POWER_OFF + */ + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public void onServiceStateChanged(@NonNull ServiceState serviceState); + } + + /** + * Interface for message waiting indicator listener. + */ + public interface MessageWaitingIndicatorChangedListener { + /** + * Callback invoked when the message-waiting indicator changes on the registered + * subscription. + * Note, the registration subscription ID comes from {@link TelephonyManager} object by + * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}. + * If this TelephonyManager object was created with + * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the + * subscription ID. Otherwise, this callback applies to + * {@link SubscriptionManager#getDefaultSubscriptionId()}. + */ + @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) + public void onMessageWaitingIndicatorChanged(boolean mwi); + } + + /** + * Interface for call-forwarding indicator listener. + */ + public interface CallForwardingIndicatorChangedListener { + /** + * Callback invoked when the call-forwarding indicator changes on the registered + * subscription. + * Note, the registration subscription ID comes from {@link TelephonyManager} object + * which registers PhoneStateListener by + * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}. + * If this TelephonyManager object was created with + * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the + * subscription ID. Otherwise, this callback applies to + * {@link SubscriptionManager#getDefaultSubscriptionId()}. + */ + @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) + public void onCallForwardingIndicatorChanged(boolean cfi); + } + + /** + * Interface for device cell location listener. + */ + public interface CellLocationChangedListener { + /** + * Callback invoked when device cell location changes on the registered subscription. + * Note, the registration subscription ID comes from {@link TelephonyManager} object + * which registers PhoneStateListener by + * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}. + * If this TelephonyManager object was created with + * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the + * subscription ID. Otherwise, this callback applies to + * {@link SubscriptionManager#getDefaultSubscriptionId()}. + */ + @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) + public void onCellLocationChanged(@NonNull CellLocation location); + } + + /** + * Interface for call state listener. + */ + public interface CallStateChangedListener { + /** + * Callback invoked when device call state changes. + * <p> + * Reports the state of Telephony (mobile) calls on the device for the registered s + * ubscription. + * <p> + * Note: the registration subscription ID comes from {@link TelephonyManager} object + * which registers PhoneStateListener by + * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}. + * If this TelephonyManager object was created with + * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the + * subscription ID. Otherwise, this callback applies to all subIds. + * <p> + * Note: The state returned here may differ from that returned by + * {@link TelephonyManager#getCallState()}. Receivers of this callback should be aware that + * calling {@link TelephonyManager#getCallState()} from within this callback may return a + * different state than the callback reports. + * + * @param state call state + * @param phoneNumber call phone number. If application does not have + * {@link android.Manifest.permission#READ_CALL_LOG} permission or carrier + * privileges (see {@link TelephonyManager#hasCarrierPrivileges}), an empty string will be + * passed as an argument. + */ + @RequiresPermission(android.Manifest.permission.READ_CALL_LOG) + public void onCallStateChanged(@CallState int state, @Nullable String phoneNumber); + } + + /** + * Interface for data connection state listener. + */ + public interface DataConnectionStateChangedListener { + /** + * Callback invoked when connection state changes on the registered subscription. + * Note, the registration subscription ID comes from {@link TelephonyManager} object + * which registers PhoneStateListener by + * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}. + * If this TelephonyManager object was created with + * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the + * subscription ID. Otherwise, this callback applies to + * {@link SubscriptionManager#getDefaultSubscriptionId()}. + * + * @see TelephonyManager#DATA_DISCONNECTED + * @see TelephonyManager#DATA_CONNECTING + * @see TelephonyManager#DATA_CONNECTED + * @see TelephonyManager#DATA_SUSPENDED + * + * @param state is the current state of data connection. + * @param networkType is the current network type of data connection. + */ + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public void onDataConnectionStateChanged(@DataState int state, + @NetworkType int networkType); + } + + /** + * Interface for data activity state listener. + */ + public interface DataActivityListener { + /** + * Callback invoked when data activity state changes on the registered subscription. + * Note, the registration subscription ID comes from {@link TelephonyManager} object + * which registers PhoneStateListener by + * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}. + * If this TelephonyManager object was created with + * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the + * subscription ID. Otherwise, this callback applies to + * {@link SubscriptionManager#getDefaultSubscriptionId()}. + * + * @see TelephonyManager#DATA_ACTIVITY_NONE + * @see TelephonyManager#DATA_ACTIVITY_IN + * @see TelephonyManager#DATA_ACTIVITY_OUT + * @see TelephonyManager#DATA_ACTIVITY_INOUT + * @see TelephonyManager#DATA_ACTIVITY_DORMANT + */ + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public void onDataActivity(@DataActivityType int direction); + } + + /** + * Interface for network signal strengths listener. + */ + public interface SignalStrengthsChangedListener { + /** + * Callback invoked when network signal strengths changes on the registered subscription. + * Note, the registration subscription ID comes from {@link TelephonyManager} object + * which registers PhoneStateListener by + * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}. + * If this TelephonyManager object was created with + * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the + * subscription ID. Otherwise, this callback applies to + * {@link SubscriptionManager#getDefaultSubscriptionId()}. + */ + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public void onSignalStrengthsChanged(@NonNull SignalStrength signalStrength); + } + + /** + * Interface for network signal strengths listener which always reported from modem. + */ + public interface AlwaysReportedSignalStrengthChangedListener { + /** + * Callback always invoked from modem when network signal strengths changes on the + * registered subscription. + * Note, the registration subscription ID comes from {@link TelephonyManager} object + * which registers PhoneStateListener by + * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}. + * If this TelephonyManager object was created with + * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the + * subscription ID. Otherwise, this callback applies to + * {@link SubscriptionManager#getDefaultSubscriptionId()}. + */ + @RequiresPermission(android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) + public void onSignalStrengthsChanged(@NonNull SignalStrength signalStrength); + } + + /** + * Interface for cell info listener. + */ + public interface CellInfoChangedListener { + /** + * Callback invoked when a observed cell info has changed or new cells have been added + * or removed on the registered subscription. + * Note, the registration subscription ID s from {@link TelephonyManager} object + * which registersPhoneStateListener by + * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}. + * If this TelephonyManager object was created with + * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the + * subscription ID. Otherwise, this callback applies to + * {@link SubscriptionManager#getDefaultSubscriptionId()}. + * + * @param cellInfo is the list of currently visible cells. + */ + @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) + public void onCellInfoChanged(@NonNull List<CellInfo> cellInfo); + } + + /** + * Interface for precise device call state listener. + * + * @hide + */ + @SystemApi + public interface PreciseCallStateChangedListener { + /** + * Callback invoked when precise device call state changes on the registered subscription. + * Note, the registration subscription ID comes from {@link TelephonyManager} object + * which registers PhoneStateListener by + * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}. + * If this TelephonyManager object was created with + * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the + * subscription ID. Otherwise, this callback applies to + * {@link SubscriptionManager#getDefaultSubscriptionId()}. + * + * @param callState {@link PreciseCallState} + */ + @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) + public void onPreciseCallStateChanged(@NonNull PreciseCallState callState); + } + + /** + * Interface for call disconnect cause listener. + */ + public interface CallDisconnectCauseChangedListener { + /** + * Callback invoked when call disconnect cause changes on the registered subscription. + * Note, the registration subscription ID comes from {@link TelephonyManager} object + * which registers PhoneStateListener by + * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}. + * If this TelephonyManager object was created with + * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the + * subscription ID. Otherwise, this callback applies to + * {@link SubscriptionManager#getDefaultSubscriptionId()}. + * + * @param disconnectCause {@link DisconnectCause}. + * @param preciseDisconnectCause {@link PreciseDisconnectCause}. + */ + @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) + public void onCallDisconnectCauseChanged(@DisconnectCauses int disconnectCause, + @PreciseDisconnectCauses int preciseDisconnectCause); + } + + /** + * Interface for IMS call disconnect cause listener. + */ + public interface ImsCallDisconnectCauseChangedListener { + /** + * Callback invoked when IMS call disconnect cause changes on the registered subscription. + * Note, the registration subscription ID comes from {@link TelephonyManager} object + * which registers PhoneStateListener by + * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}. + * If this TelephonyManager object was created with + * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the + * subscription ID. Otherwise, this callback applies to + * {@link SubscriptionManager#getDefaultSubscriptionId()}. + * + * @param imsReasonInfo {@link ImsReasonInfo} contains details on why IMS call failed. + * + */ + @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) + public void onImsCallDisconnectCauseChanged(@NonNull ImsReasonInfo imsReasonInfo); + } + + /** + * Interface for precise data connection state listener. + */ + public interface PreciseDataConnectionStateChangedListener { + /** + * Callback providing update about the default/internet data connection on the registered + * subscription. + * + * Note, the registration subscription ID comes from {@link TelephonyManager} object + * which registers PhoneStateListener by + * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}. + * If this TelephonyManager object was created with + * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the + * subscription ID. Otherwise, this callback applies to + * {@link SubscriptionManager#getDefaultSubscriptionId()}. + * + * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} + * or the calling app has carrier privileges + * (see {@link TelephonyManager#hasCarrierPrivileges}). + * + * @param dataConnectionState {@link PreciseDataConnectionState} + */ + @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) + public void onPreciseDataConnectionStateChanged( + @NonNull PreciseDataConnectionState dataConnectionState); + } + + /** + * Interface for Single Radio Voice Call Continuity listener. + * + * @hide + */ + @SystemApi + public interface SrvccStateChangedListener { + /** + * Callback invoked when there has been a change in the Single Radio Voice Call Continuity + * (SRVCC) state for the currently active call on the registered subscription. + * + * Note, the registration subscription ID comes from {@link TelephonyManager} object + * which registers PhoneStateListener by + * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}. + * If this TelephonyManager object was created with + * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the + * subscription ID. Otherwise, this callback applies to + * {@link SubscriptionManager#getDefaultSubscriptionId()}. + */ + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public void onSrvccStateChanged(@SrvccState int srvccState); + } + + /** + * Interface for SIM voice activation state listener. + * + * @hide + */ + @SystemApi + public interface VoiceActivationStateChangedListener { + /** + * Callback invoked when the SIM voice activation state has changed on the registered + * subscription. + * Note, the registration subscription ID comes from {@link TelephonyManager} object + * which registers PhoneStateListener by + * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}. + * If this TelephonyManager object was created with + * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the + * subscription ID. Otherwise, this callback applies to + * {@link SubscriptionManager#getDefaultSubscriptionId()}. + * + * @param state is the current SIM voice activation state + */ + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public void onVoiceActivationStateChanged(@SimActivationState int state); + + } + + /** + * Interface for SIM data activation state listener. + */ + public interface DataActivationStateChangedListener { + /** + * Callback invoked when the SIM data activation state has changed on the registered + * subscription. + * Note, the registration subscription ID comes from {@link TelephonyManager} object + * which registers PhoneStateListener by + * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}. + * If this TelephonyManager object was created with + * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the + * subscription ID. Otherwise, this callback applies to + * {@link SubscriptionManager#getDefaultSubscriptionId()}. + * + * @param state is the current SIM data activation state + */ + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public void onDataActivationStateChanged(@SimActivationState int state); + } + + /** + * Interface for user mobile data state listener. + */ + public interface UserMobileDataStateChangedListener { + /** + * Callback invoked when the user mobile data state has changed on the registered + * subscription. + * Note, the registration subscription ID comes from {@link TelephonyManager} object + * which registers PhoneStateListener by + * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}. + * If this TelephonyManager object was created with + * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the + * subscription ID. Otherwise, this callback applies to + * {@link SubscriptionManager#getDefaultSubscriptionId()}. + * + * @param enabled indicates whether the current user mobile data state is enabled or + * disabled. + */ + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public void onUserMobileDataStateChanged(boolean enabled); + } + + /** + * Interface for display info listener. + */ + public interface DisplayInfoChangedListener { + /** + * Callback invoked when the display info has changed on the registered subscription. + * <p> The {@link TelephonyDisplayInfo} contains status information shown to the user + * based on carrier policy. + * + * @param telephonyDisplayInfo The display information. + */ + @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) + public void onDisplayInfoChanged(@NonNull TelephonyDisplayInfo telephonyDisplayInfo); + } + + /** + * Interface for the current emergency number list listener. + */ + public interface EmergencyNumberListChangedListener { + /** + * Callback invoked when the current emergency number list has changed on the registered + * subscription. + * + * Note, the registered subscription is associated with {@link TelephonyManager} object + * on which + * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)} + * was called. + * If this TelephonyManager object was created with + * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the + * given subscription ID. Otherwise, this callback applies to + * {@link SubscriptionManager#getDefaultSubscriptionId()}. + * + * @param emergencyNumberList Map associating all active subscriptions on the device with + * the list of emergency numbers originating from that + * subscription. + * If there are no active subscriptions, the map will contain a + * single entry with + * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} as + * the key and a list of emergency numbers as the value. If no + * emergency number information is available, the value will be + * empty. + */ + @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) + public void onEmergencyNumberListChanged( + @NonNull Map<Integer, List<EmergencyNumber>> emergencyNumberList); + } + + /** + * Interface for outgoing emergency call listener. + * + * @hide + */ + @SystemApi + public interface OutgoingEmergencyCallListener { + /** + * Callback invoked when an outgoing call is placed to an emergency number. + * + * This method will be called when an emergency call is placed on any subscription + * (including the no-SIM case), regardless of which subscription this listener was + * registered on. + * + * The default implementation of this method calls + * {@link #onOutgoingEmergencyCall(EmergencyNumber)} for backwards compatibility purposes. + * Do not call {@code super(...)} from within your implementation unless you want + * {@link #onOutgoingEmergencyCall(EmergencyNumber)} to be called as well. + * + * @param placedEmergencyNumber The {@link EmergencyNumber} the emergency call was + * placed to. + * @param subscriptionId The subscription ID used to place the emergency call. If the + * emergency call was placed without a valid subscription + * (e.g. when there are no SIM cards in the device), this will be + * equal to {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}. + */ + @RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) + public void onOutgoingEmergencyCall(@NonNull EmergencyNumber placedEmergencyNumber, + int subscriptionId); + } + + /** + * Interface for outgoing emergency sms listener. + * + * @hide + */ + @SystemApi + public interface OutgoingEmergencySmsListener { + /** + * Smsback invoked when an outgoing sms is sent to an emergency number. + * + * This method will be called when an emergency sms is sent on any subscription, + * regardless of which subscription this listener was registered on. + * + * The default implementation of this method calls + * {@link #onOutgoingEmergencySms(EmergencyNumber)} for backwards compatibility purposes. Do + * not call {@code super(...)} from within your implementation unless you want + * {@link #onOutgoingEmergencySms(EmergencyNumber)} to be called as well. + * + * @param sentEmergencyNumber The {@link EmergencyNumber} the emergency sms was sent to. + * @param subscriptionId The subscription ID used to send the emergency sms. + */ + @RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) + public void onOutgoingEmergencySms(@NonNull EmergencyNumber sentEmergencyNumber, + int subscriptionId); + } + + /** + * Interface for phone capability listener. + * + */ + public interface PhoneCapabilityChangedListener { + /** + * Callback invoked when phone capability changes. + * Note, this callback triggers regardless of registered subscription. + * + * @param capability the new phone capability + */ + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public void onPhoneCapabilityChanged(@NonNull PhoneCapability capability); + } + + /** + * Interface for active data subscription ID listener. + */ + public interface ActiveDataSubscriptionIdChangedListener { + /** + * Callback invoked when active data subscription ID changes. + * Note, this callback triggers regardless of registered subscription. + * + * @param subId current subscription used to setup Cellular Internet data. + * For example, it could be the current active opportunistic subscription + * in use, or the subscription user selected as default data subscription in + * DSDS mode. + */ + @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) + public void onActiveDataSubscriptionIdChanged(int subId); + } + + /** + * Interface for modem radio power state listener. + * + * @hide + */ + @SystemApi + public interface RadioPowerStateChangedListener { + /** + * Callback invoked when modem radio power state changes on the registered subscription. + * Note, the registration subscription ID comes from {@link TelephonyManager} object + * which registers PhoneStateListener by + * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}. + * If this TelephonyManager object was created with + * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the + * subscription ID. Otherwise, this callback applies to + * {@link SubscriptionManager#getDefaultSubscriptionId()}. + * + * @param state the modem radio power state + */ + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public void onRadioPowerStateChanged(@RadioPowerState int state); + } + + /** + * Interface for carrier network listener. + */ + public interface CarrierNetworkChangeListener { + /** + * Callback invoked when telephony has received notice from a carrier + * app that a network action that could result in connectivity loss + * has been requested by an app using + * {@link android.service.carrier.CarrierService#notifyCarrierNetworkChange(boolean)} + * + * This is optional and is only used to allow the system to provide alternative UI while + * telephony is performing an action that may result in intentional, temporary network + * lack of connectivity. + * + * Note, this callback is pinned to the registered subscription and will be invoked when + * the notifying carrier app has carrier privilege rule on the registered + * subscription. {@link android.telephony.TelephonyManager#hasCarrierPrivileges} + * + * @param active If the carrier network change is or shortly will be active, + * {@code true} indicate that showing alternative UI, {@code false} otherwise. + */ + public void onCarrierNetworkChange(boolean active); + } + + /** + * Interface for registration failures listener. + */ + public interface RegistrationFailedListener { + /** + * Report that Registration or a Location/Routing/Tracking Area update has failed. + * + * <p>Indicate whenever a registration procedure, including a location, routing, or tracking + * area update fails. This includes procedures that do not necessarily result in a change of + * the modem's registration status. If the modem's registration status changes, that is + * reflected in the onNetworkStateChanged() and subsequent + * get{Voice/Data}RegistrationState(). + * + * <p>Because registration failures are ephemeral, this callback is not sticky. + * Registrants will not receive the most recent past value when registering. + * + * @param cellIdentity the CellIdentity, which must include the globally unique identifier + * for the cell (for example, all components of the CGI or ECGI). + * @param chosenPlmn a 5 or 6 digit alphanumeric PLMN (MCC|MNC) among those broadcast by the + * cell that was chosen for the failed registration attempt. + * @param domain DOMAIN_CS, DOMAIN_PS or both in case of a combined procedure. + * @param causeCode the primary failure cause code of the procedure. + * For GSM/UMTS (MM), values are in TS 24.008 Sec 10.5.95 + * For GSM/UMTS (GMM), values are in TS 24.008 Sec 10.5.147 + * For LTE (EMM), cause codes are TS 24.301 Sec 9.9.3.9 + * For NR (5GMM), cause codes are TS 24.501 Sec 9.11.3.2 + * Integer.MAX_VALUE if this value is unused. + * @param additionalCauseCode the cause code of any secondary/combined procedure + * if appropriate. For UMTS, if a combined attach succeeds for + * PS only, then the GMM cause code shall be included as an + * additionalCauseCode. For LTE (ESM), cause codes are in + * TS 24.301 9.9.4.4. Integer.MAX_VALUE if this value is unused. + */ + @RequiresPermission(allOf = { + Manifest.permission.READ_PRECISE_PHONE_STATE, + Manifest.permission.ACCESS_FINE_LOCATION + }) + public void onRegistrationFailed(@NonNull CellIdentity cellIdentity, + @NonNull String chosenPlmn, @Domain int domain, + int causeCode, int additionalCauseCode); + } + + /** + * Interface for call attributes listener. + * + * @hide + */ + @SystemApi + public interface CallAttributesChangedListener { + /** + * Callback invoked when the call attributes changes on the registered subscription. + * Note, the registration subscription ID comes from {@link TelephonyManager} object + * which registers PhoneStateListener by + * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}. + * If this TelephonyManager object was created with + * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the + * subscription ID. Otherwise, this callback applies to + * {@link SubscriptionManager#getDefaultSubscriptionId()}. + * + * @param callAttributes the call attributes + */ + @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE) + void onCallAttributesChanged(@NonNull CallAttributes callAttributes); + } + + /** + * Interface for barring information listener. + */ + public interface BarringInfoChangedListener { + /** + * Report updated barring information for the current camped/registered cell. + * + * <p>Barring info is provided for all services applicable to the current camped/registered + * cell, for the registered PLMN and current access class/access category. + * + * @param barringInfo for all services on the current cell. + * @see android.telephony.BarringInfo + */ + @RequiresPermission(allOf = { + Manifest.permission.READ_PRECISE_PHONE_STATE, + Manifest.permission.ACCESS_FINE_LOCATION + }) + public void onBarringInfoChanged(@NonNull BarringInfo barringInfo); + } + + /** + * Interface for current physical channel configuration listener. + * @hide + */ + @SystemApi + public interface PhysicalChannelConfigChangedListener { + /** + * Callback invoked when the current physical channel configuration has changed + * + * @param configs List of the current {@link PhysicalChannelConfig}s + */ + @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE) + public void onPhysicalChannelConfigChanged(@NonNull List<PhysicalChannelConfig> configs); + } + + /** + * Interface for data enabled listener. + * + * @hide + */ + @SystemApi + public interface DataEnabledChangedListener { + /** + * Callback invoked when the data enabled changes. + * + * @param enabled {@code true} if data is enabled, otherwise disabled. + * @param reason Reason for data enabled/disabled. + * See {@link TelephonyManager.DataEnabledReason}. + */ + @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE) + public void onDataEnabledChanged(boolean enabled, + @DataEnabledReason int reason); } /** @@ -658,8 +1970,7 @@ public class PhoneStateListener { * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}. * If this TelephonyManager object was created with * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the - * subId. Otherwise, this callback applies to - * {@link SubscriptionManager#getDefaultSubscriptionId()}. + * subId. Otherwise, this callback applies to all subIds. * <p> * Note: The state returned here may differ from that returned by * {@link TelephonyManager#getCallState()}. Receivers of this callback should be aware that @@ -698,6 +2009,7 @@ public class PhoneStateListener { * same as above, but with the network type. Both called. */ public void onDataConnectionStateChanged(int state, int networkType) { + // default implementation empty } /** @@ -745,6 +2057,7 @@ public class PhoneStateListener { * @param cellInfo is the list of currently visible cells. */ public void onCellInfoChanged(List<CellInfo> cellInfo) { + // default implementation empty } /** @@ -758,7 +2071,7 @@ public class PhoneStateListener { * @param callState {@link PreciseCallState} * @hide */ - @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE)) + @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) @SystemApi public void onPreciseCallStateChanged(@NonNull PreciseCallState callState) { // default implementation empty @@ -777,9 +2090,9 @@ public class PhoneStateListener { * @param preciseDisconnectCause {@link PreciseDisconnectCause}. * */ - @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE)) - public void onCallDisconnectCauseChanged(@Annotation.DisconnectCauses int disconnectCause, - int preciseDisconnectCause) { + @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) + public void onCallDisconnectCauseChanged(@DisconnectCauses int disconnectCause, + @PreciseDisconnectCauses int preciseDisconnectCause) { // default implementation empty } @@ -795,7 +2108,7 @@ public class PhoneStateListener { * @param imsReasonInfo {@link ImsReasonInfo} contains details on why IMS call failed. * */ - @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE)) + @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onImsCallDisconnectCauseChanged(@NonNull ImsReasonInfo imsReasonInfo) { // default implementation empty } @@ -817,7 +2130,7 @@ public class PhoneStateListener { * * @param dataConnectionState {@link PreciseDataConnectionState} */ - @RequiresPermission((android.Manifest.permission.MODIFY_PHONE_STATE)) + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onPreciseDataConnectionStateChanged( @NonNull PreciseDataConnectionState dataConnectionState) { // default implementation empty @@ -855,6 +2168,7 @@ public class PhoneStateListener { */ @SystemApi public void onSrvccStateChanged(@SrvccState int srvccState) { + // default implementation empty } @@ -873,6 +2187,7 @@ public class PhoneStateListener { */ @SystemApi public void onVoiceActivationStateChanged(@SimActivationState int state) { + // default implementation empty } /** @@ -889,6 +2204,7 @@ public class PhoneStateListener { * @hide */ public void onDataActivationStateChanged(@SimActivationState int state) { + // default implementation empty } /** @@ -916,7 +2232,7 @@ public class PhoneStateListener { * * @param telephonyDisplayInfo The display information. */ - @RequiresPermission((android.Manifest.permission.READ_PHONE_STATE)) + @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void onDisplayInfoChanged(@NonNull TelephonyDisplayInfo telephonyDisplayInfo) { // default implementation empty } @@ -1030,7 +2346,8 @@ public class PhoneStateListener { /** * Callback invoked when OEM hook raw event is received on the registered subscription. * Note, the registration subId comes from {@link TelephonyManager} object which registers - * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}. + * PhoneStateListener by + * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}. * If this TelephonyManager object was created with * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the * subId. Otherwise, this callback applies to @@ -1052,7 +2369,7 @@ public class PhoneStateListener { * @param capability the new phone capability * @hide */ - public void onPhoneCapabilityChanged(PhoneCapability capability) { + public void onPhoneCapabilityChanged(@NonNull PhoneCapability capability) { // default implementation empty } @@ -1096,7 +2413,8 @@ public class PhoneStateListener { * subId. Otherwise, this callback applies to * {@link SubscriptionManager#getDefaultSubscriptionId()}. * - * @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE} + * Requires permission {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} + * * @param state the modem radio power state * @hide */ @@ -1453,18 +2771,16 @@ public class PhoneStateListener { Binder.withCleanCallingIdentity( () -> mExecutor.execute( () -> psl.onImsCallDisconnectCauseChanged(disconnectCause))); - } public void onRegistrationFailed(@NonNull CellIdentity cellIdentity, - @NonNull String chosenPlmn, int domain, - int causeCode, int additionalCauseCode) { + @NonNull String chosenPlmn, int domain, int causeCode, int additionalCauseCode) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity( () -> mExecutor.execute(() -> psl.onRegistrationFailed( - cellIdentity, chosenPlmn, domain, causeCode, additionalCauseCode))); + cellIdentity, chosenPlmn, domain, causeCode, additionalCauseCode))); // default implementation empty } @@ -1475,8 +2791,27 @@ public class PhoneStateListener { Binder.withCleanCallingIdentity( () -> mExecutor.execute(() -> psl.onBarringInfoChanged(barringInfo))); } - } + public void onPhysicalChannelConfigChanged(List<PhysicalChannelConfig> configs) { + PhysicalChannelConfigChangedListener listener = + (PhysicalChannelConfigChangedListener) mPhoneStateListenerWeakRef.get(); + if (listener == null) return; + + Binder.withCleanCallingIdentity( + () -> mExecutor.execute(() -> listener.onPhysicalChannelConfigChanged( + configs))); + } + + public void onDataEnabledChanged(boolean enabled, @DataEnabledReason int reason) { + DataEnabledChangedListener listener = + (DataEnabledChangedListener) mPhoneStateListenerWeakRef.get(); + if (listener == null) return; + + Binder.withCleanCallingIdentity( + () -> mExecutor.execute(() -> listener.onDataEnabledChanged( + enabled, reason))); + } + } private void log(String s) { Rlog.d(LOG_TAG, s); diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java index 3673ae7f7a37..a9548b0a42b4 100644 --- a/core/java/android/telephony/TelephonyRegistryManager.java +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -15,6 +15,7 @@ */ package android.telephony; +import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -24,6 +25,9 @@ import android.compat.annotation.EnabledAfter; import android.content.Context; import android.os.Binder; import android.os.Build; +import android.os.Handler; +import android.os.HandlerExecutor; +import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; import android.telephony.Annotation.CallState; @@ -37,6 +41,7 @@ import android.telephony.Annotation.SimActivationState; import android.telephony.Annotation.SrvccState; import android.telephony.emergency.EmergencyNumber; import android.telephony.ims.ImsReasonInfo; +import android.util.ArraySet; import android.util.Log; import com.android.internal.telephony.IOnSubscriptionsChangedListener; @@ -45,6 +50,7 @@ import com.android.internal.telephony.ITelephonyRegistry; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.Executor; /** @@ -206,7 +212,7 @@ public class TelephonyRegistryManager { } /** - * To check the SDK version for {@link #listenForSubscriber}. + * To check the SDK version for {@link #listenWithEventList}. */ @ChangeId @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.P) @@ -218,23 +224,23 @@ public class TelephonyRegistryManager { * @param pkg Package name * @param featureId Feature ID * @param listener Listener providing callback - * @param events Events + * @param events List events * @param notifyNow Whether to notify instantly */ - public void listenForSubscriber(int subId, @NonNull String pkg, @NonNull String featureId, - @NonNull PhoneStateListener listener, int events, boolean notifyNow) { + public void listenWithEventList(int subId, @NonNull String pkg, @NonNull String featureId, + @NonNull PhoneStateListener listener, @NonNull int[] events, boolean notifyNow) { try { // subId from PhoneStateListener is deprecated Q on forward, use the subId from // TelephonyManager instance. Keep using subId from PhoneStateListener for pre-Q. if (Compatibility.isChangeEnabled(LISTEN_CODE_CHANGE)) { // Since mSubId in PhoneStateListener is deprecated from Q on forward, this is // the only place to set mSubId and its for "informational" only. - listener.mSubId = (events == PhoneStateListener.LISTEN_NONE) + listener.mSubId = (events.length == 0) ? SubscriptionManager.INVALID_SUBSCRIPTION_ID : subId; } else if (listener.mSubId != null) { subId = listener.mSubId; } - sRegistry.listenForSubscriber( + sRegistry.listenWithEventList( subId, pkg, featureId, listener.callback, events, notifyNow); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -765,4 +771,366 @@ public class TelephonyRegistryManager { } } + /** + * Notify {@link PhysicalChannelConfig} has changed for a specific subscription. + * + * @param subId the subId + * @param configs a list of {@link PhysicalChannelConfig}, the configs of physical channel. + */ + public void notifyPhysicalChannelConfigForSubscriber( + int subId, List<PhysicalChannelConfig> configs) { + try { + sRegistry.notifyPhysicalChannelConfigForSubscriber(subId, configs); + } catch (RemoteException ex) { + // system server crash + } + } + + /** + * Notify that the data enabled has changed. + * + * @param enabled True if data is enabled, otherwise disabled. + * @param reason Reason for data enabled/disabled. See {@code REASON_*} in + * {@link TelephonyManager}. + */ + public void notifyDataEnabled(boolean enabled, @TelephonyManager.DataEnabledReason int reason) { + try { + sRegistry.notifyDataEnabled(enabled, reason); + } catch (RemoteException ex) { + // system server crash + } + } + + public @NonNull Set<Integer> getEventsFromListener(@NonNull PhoneStateListener listener) { + + Set<Integer> eventList = new ArraySet<>(); + + if (listener instanceof PhoneStateListener.ServiceStateChangedListener) { + eventList.add(PhoneStateListener.EVENT_SERVICE_STATE_CHANGED); + } + + if (listener instanceof PhoneStateListener.MessageWaitingIndicatorChangedListener) { + eventList.add(PhoneStateListener.EVENT_MESSAGE_WAITING_INDICATOR_CHANGED); + } + + if (listener instanceof PhoneStateListener.CallForwardingIndicatorChangedListener) { + eventList.add(PhoneStateListener.EVENT_CALL_FORWARDING_INDICATOR_CHANGED); + } + + if (listener instanceof PhoneStateListener.CellLocationChangedListener) { + eventList.add(PhoneStateListener.EVENT_CELL_LOCATION_CHANGED); + } + + if (listener instanceof PhoneStateListener.CallStateChangedListener) { + eventList.add(PhoneStateListener.EVENT_CALL_STATE_CHANGED); + } + + if (listener instanceof PhoneStateListener.DataConnectionStateChangedListener) { + eventList.add(PhoneStateListener.EVENT_DATA_CONNECTION_STATE_CHANGED); + } + + if (listener instanceof PhoneStateListener.DataActivityListener) { + eventList.add(PhoneStateListener.EVENT_DATA_ACTIVITY_CHANGED); + } + + if (listener instanceof PhoneStateListener.SignalStrengthsChangedListener) { + eventList.add(PhoneStateListener.EVENT_SIGNAL_STRENGTHS_CHANGED); + } + + if (listener instanceof PhoneStateListener.AlwaysReportedSignalStrengthChangedListener) { + eventList.add(PhoneStateListener.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED); + } + + if (listener instanceof PhoneStateListener.CellInfoChangedListener) { + eventList.add(PhoneStateListener.EVENT_CELL_INFO_CHANGED); + } + + if (listener instanceof PhoneStateListener.PreciseCallStateChangedListener) { + eventList.add(PhoneStateListener.EVENT_PRECISE_CALL_STATE_CHANGED); + } + + if (listener instanceof PhoneStateListener.CallDisconnectCauseChangedListener) { + eventList.add(PhoneStateListener.EVENT_CALL_DISCONNECT_CAUSE_CHANGED); + } + + if (listener instanceof PhoneStateListener.ImsCallDisconnectCauseChangedListener) { + eventList.add(PhoneStateListener.EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED); + } + + if (listener instanceof PhoneStateListener.PreciseDataConnectionStateChangedListener) { + eventList.add(PhoneStateListener.EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED); + } + + if (listener instanceof PhoneStateListener.SrvccStateChangedListener) { + eventList.add(PhoneStateListener.EVENT_SRVCC_STATE_CHANGED); + } + + if (listener instanceof PhoneStateListener.VoiceActivationStateChangedListener) { + eventList.add(PhoneStateListener.EVENT_VOICE_ACTIVATION_STATE_CHANGED); + } + + if (listener instanceof PhoneStateListener.DataActivationStateChangedListener) { + eventList.add(PhoneStateListener.EVENT_DATA_ACTIVATION_STATE_CHANGED); + } + + if (listener instanceof PhoneStateListener.UserMobileDataStateChangedListener) { + eventList.add(PhoneStateListener.EVENT_USER_MOBILE_DATA_STATE_CHANGED); + } + + if (listener instanceof PhoneStateListener.DisplayInfoChangedListener) { + eventList.add(PhoneStateListener.EVENT_DISPLAY_INFO_CHANGED); + } + + if (listener instanceof PhoneStateListener.EmergencyNumberListChangedListener) { + eventList.add(PhoneStateListener.EVENT_EMERGENCY_NUMBER_LIST_CHANGED); + } + + if (listener instanceof PhoneStateListener.OutgoingEmergencyCallListener) { + eventList.add(PhoneStateListener.EVENT_OUTGOING_EMERGENCY_CALL); + } + + if (listener instanceof PhoneStateListener.OutgoingEmergencySmsListener) { + eventList.add(PhoneStateListener.EVENT_OUTGOING_EMERGENCY_SMS); + } + + if (listener instanceof PhoneStateListener.PhoneCapabilityChangedListener) { + eventList.add(PhoneStateListener.EVENT_PHONE_CAPABILITY_CHANGED); + } + + if (listener instanceof PhoneStateListener.ActiveDataSubscriptionIdChangedListener) { + eventList.add(PhoneStateListener.EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED); + } + + if (listener instanceof PhoneStateListener.RadioPowerStateChangedListener) { + eventList.add(PhoneStateListener.EVENT_RADIO_POWER_STATE_CHANGED); + } + + if (listener instanceof PhoneStateListener.CarrierNetworkChangeListener) { + eventList.add(PhoneStateListener.EVENT_CARRIER_NETWORK_CHANGED); + } + + if (listener instanceof PhoneStateListener.RegistrationFailedListener) { + eventList.add(PhoneStateListener.EVENT_REGISTRATION_FAILURE); + } + + if (listener instanceof PhoneStateListener.CallAttributesChangedListener) { + eventList.add(PhoneStateListener.EVENT_CALL_ATTRIBUTES_CHANGED); + } + + if (listener instanceof PhoneStateListener.BarringInfoChangedListener) { + eventList.add(PhoneStateListener.EVENT_BARRING_INFO_CHANGED); + } + + if (listener instanceof PhoneStateListener.PhysicalChannelConfigChangedListener) { + eventList.add(PhoneStateListener.EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED); + } + + if (listener instanceof PhoneStateListener.DataEnabledChangedListener) { + eventList.add(PhoneStateListener.EVENT_DATA_ENABLED_CHANGED); + } + + return eventList; + } + + private @NonNull Set<Integer> getEventsFromBitmask(int eventMask) { + + Set<Integer> eventList = new ArraySet<>(); + + if ((eventMask & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) { + eventList.add(PhoneStateListener.EVENT_SERVICE_STATE_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) { + eventList.add(PhoneStateListener.EVENT_SIGNAL_STRENGTH_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) { + eventList.add(PhoneStateListener.EVENT_MESSAGE_WAITING_INDICATOR_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) { + eventList.add(PhoneStateListener.EVENT_CALL_FORWARDING_INDICATOR_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) { + eventList.add(PhoneStateListener.EVENT_CELL_LOCATION_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_CALL_STATE) != 0) { + eventList.add(PhoneStateListener.EVENT_CALL_STATE_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) { + eventList.add(PhoneStateListener.EVENT_DATA_CONNECTION_STATE_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) { + eventList.add(PhoneStateListener.EVENT_DATA_ACTIVITY_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) { + eventList.add(PhoneStateListener.EVENT_SIGNAL_STRENGTHS_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) != 0) { + eventList.add(PhoneStateListener.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_CELL_INFO) != 0) { + eventList.add(PhoneStateListener.EVENT_CELL_INFO_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) { + eventList.add(PhoneStateListener.EVENT_PRECISE_CALL_STATE_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) { + eventList.add(PhoneStateListener.EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_DATA_CONNECTION_REAL_TIME_INFO) != 0) { + eventList.add(PhoneStateListener.EVENT_DATA_CONNECTION_REAL_TIME_INFO_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT) != 0) { + eventList.add(PhoneStateListener.EVENT_OEM_HOOK_RAW); + } + + if ((eventMask & PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED) != 0) { + eventList.add(PhoneStateListener.EVENT_SRVCC_STATE_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE) != 0) { + eventList.add(PhoneStateListener.EVENT_CARRIER_NETWORK_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_VOICE_ACTIVATION_STATE) != 0) { + eventList.add(PhoneStateListener.EVENT_VOICE_ACTIVATION_STATE_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_DATA_ACTIVATION_STATE) != 0) { + eventList.add(PhoneStateListener.EVENT_DATA_ACTIVATION_STATE_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_USER_MOBILE_DATA_STATE) != 0) { + eventList.add(PhoneStateListener.EVENT_USER_MOBILE_DATA_STATE_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED) != 0) { + eventList.add(PhoneStateListener.EVENT_DISPLAY_INFO_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE) != 0) { + eventList.add(PhoneStateListener.EVENT_PHONE_CAPABILITY_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE) != 0) { + eventList.add(PhoneStateListener.EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED) != 0) { + eventList.add(PhoneStateListener.EVENT_RADIO_POWER_STATE_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST) != 0) { + eventList.add(PhoneStateListener.EVENT_EMERGENCY_NUMBER_LIST_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES) != 0) { + eventList.add(PhoneStateListener.EVENT_CALL_DISCONNECT_CAUSE_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED) != 0) { + eventList.add(PhoneStateListener.EVENT_CALL_ATTRIBUTES_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES) != 0) { + eventList.add(PhoneStateListener.EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED); + } + + if ((eventMask & PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL) != 0) { + eventList.add(PhoneStateListener.EVENT_OUTGOING_EMERGENCY_CALL); + } + + if ((eventMask & PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_SMS) != 0) { + eventList.add(PhoneStateListener.EVENT_OUTGOING_EMERGENCY_SMS); + } + + if ((eventMask & PhoneStateListener.LISTEN_REGISTRATION_FAILURE) != 0) { + eventList.add(PhoneStateListener.EVENT_REGISTRATION_FAILURE); + } + + if ((eventMask & PhoneStateListener.LISTEN_BARRING_INFO) != 0) { + eventList.add(PhoneStateListener.EVENT_BARRING_INFO_CHANGED); + } + return eventList; + + } + + /** + * Registers a listener object to receive notification of changes + * in specified telephony states. + * <p> + * To register a listener, pass a {@link PhoneStateListener} which implements + * interfaces of events. For example, + * FakeServiceStateChangedListener extends {@link PhoneStateListener} implements + * {@link PhoneStateListener.ServiceStateChangedListener}. + * + * At registration, and when a specified telephony state changes, the telephony manager invokes + * the appropriate callback method on the listener object and passes the current (updated) + * values. + * <p> + * + * If this TelephonyManager object has been created with + * {@link TelephonyManager#createForSubscriptionId}, applies to the given subId. + * Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}. + * To listen events for multiple subIds, pass a separate listener object to + * each TelephonyManager object created with {@link TelephonyManager#createForSubscriptionId}. + * + * Note: if you call this method while in the middle of a binder transaction, you <b>must</b> + * call {@link android.os.Binder#clearCallingIdentity()} before calling this method. A + * {@link SecurityException} will be thrown otherwise. + * + * This API should be used sparingly -- large numbers of listeners will cause system + * instability. If a process has registered too many listeners without unregistering them, it + * may encounter an {@link IllegalStateException} when trying to register more listeners. + * + * @param listener The {@link PhoneStateListener} object to register. + */ + public void registerPhoneStateListener(@NonNull @CallbackExecutor Executor executor, int subId, + String pkgName, String attributionTag, @NonNull PhoneStateListener listener, + boolean notifyNow) { + listener.setExecutor(executor); + registerPhoneStateListener(subId, pkgName, attributionTag, listener, + getEventsFromListener(listener), notifyNow); + } + + public void registerPhoneStateListenerWithEvents(int subId, String pkgName, + String attributionTag, @NonNull PhoneStateListener listener, int events, + boolean notifyNow) { + registerPhoneStateListener( + subId, pkgName, attributionTag, listener, getEventsFromBitmask(events), notifyNow); + } + + private void registerPhoneStateListener(int subId, + String pkgName, String attributionTag, @NonNull PhoneStateListener listener, + @NonNull Set<Integer> events, boolean notifyNow) { + if (listener == null) { + throw new IllegalStateException("telephony service is null."); + } + + listenWithEventList(subId, pkgName, attributionTag, listener, + events.stream().mapToInt(i -> i).toArray(), notifyNow); + } + + /** + * Unregister an existing {@link PhoneStateListener}. + * + * @param listener The {@link PhoneStateListener} object to unregister. + */ + public void unregisterPhoneStateListener(int subId, String pkgName, String attributionTag, + @NonNull PhoneStateListener listener, + boolean notifyNow) { + listenWithEventList(subId, pkgName, attributionTag, listener, new int[0], notifyNow); + } } diff --git a/core/java/android/view/textclassifier/OWNERS b/core/java/android/view/textclassifier/OWNERS index ac80d9f4cdd0..4bcdeea472e3 100644 --- a/core/java/android/view/textclassifier/OWNERS +++ b/core/java/android/view/textclassifier/OWNERS @@ -6,3 +6,5 @@ svetoslavganov@android.com svetoslavganov@google.com augale@google.com joannechung@google.com +tonymak@google.com +licha@google.com diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl index d2dc7c283ff7..854fb17e692b 100644 --- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl +++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl @@ -23,6 +23,7 @@ import android.telephony.CellInfo; import android.telephony.DataConnectionRealTimeInfo; import android.telephony.TelephonyDisplayInfo; import android.telephony.PhoneCapability; +import android.telephony.PhysicalChannelConfig; import android.telephony.PreciseCallState; import android.telephony.PreciseDataConnectionState; import android.telephony.ServiceState; @@ -68,4 +69,6 @@ oneway interface IPhoneStateListener { void onRegistrationFailed(in CellIdentity cellIdentity, String chosenPlmn, int domain, int causeCode, int additionalCauseCode); void onBarringInfoChanged(in BarringInfo barringInfo); + void onPhysicalChannelConfigChanged(in List<PhysicalChannelConfig> configs); + void onDataEnabledChanged(boolean enabled, int reason); } diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl index 5f2dcc3d22e1..2a73dacbc94a 100644 --- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -41,16 +41,8 @@ interface ITelephonyRegistry { IOnSubscriptionsChangedListener callback); void removeOnSubscriptionsChangedListener(String pkg, IOnSubscriptionsChangedListener callback); - /** - * @deprecated Use {@link #listenWithFeature(String, String, IPhoneStateListener, int, - * boolean) instead - */ - @UnsupportedAppUsage - void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow); - void listenWithFeature(String pkg, String featureId, IPhoneStateListener callback, int events, - boolean notifyNow); - void listenForSubscriber(in int subId, String pkg, String featureId, - IPhoneStateListener callback, int events, boolean notifyNow); + void listenWithEventList(in int subId, String pkg, String featureId, + IPhoneStateListener callback, in int[] events, boolean notifyNow); @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) void notifyCallStateForAllSubs(int state, String incomingNumber); void notifyCallState(in int phoneId, in int subId, int state, String incomingNumber); @@ -99,4 +91,7 @@ interface ITelephonyRegistry { void notifyRegistrationFailed(int slotIndex, int subId, in CellIdentity cellIdentity, String chosenPlmn, int domain, int causeCode, int additionalCauseCode); void notifyBarringInfoChanged(int slotIndex, int subId, in BarringInfo barringInfo); + void notifyPhysicalChannelConfigForSubscriber(in int subId, + in List<PhysicalChannelConfig> configs); + void notifyDataEnabled(boolean enabled, int reason); } diff --git a/core/java/com/android/internal/widget/OWNERS b/core/java/com/android/internal/widget/OWNERS index cca39ea3287d..ae566c3988cd 100644 --- a/core/java/com/android/internal/widget/OWNERS +++ b/core/java/com/android/internal/widget/OWNERS @@ -1 +1,7 @@ per-file PointerLocationView.java = michaelwr@google.com, svv@google.com + +# LockSettings related +per-file *LockPattern* = file:/services/core/java/com/android/server/locksettings/OWNERS +per-file *LockScreen* = file:/services/core/java/com/android/server/locksettings/OWNERS +per-file *Lockscreen* = file:/services/core/java/com/android/server/locksettings/OWNERS +per-file *LockSettings* = file:/services/core/java/com/android/server/locksettings/OWNERS diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index 22dd765f2526..dc98aafb129e 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -1810,7 +1810,7 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, heap_tagging_level = M_HEAP_TAGGING_LEVEL_NONE; break; } - android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &heap_tagging_level, sizeof(heap_tagging_level)); + mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, heap_tagging_level); // Now that we've used the flag, clear it so that we don't pass unknown flags to the ART runtime. runtime_flags &= ~RuntimeFlags::MEMORY_TAG_LEVEL_MASK; diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 2f1bcdc76afb..4b3d82a04b8b 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -8968,6 +8968,11 @@ changed at runtime by calling {@link android.media.tv.TvInputManager#updateTvInputInfo(android.media.tv.TvInputInfo)}. --> <attr name="tunerCount" format="integer" /> + <!-- Attribute whether the TV input service can pause recording programs. + This value can be changed at runtime by calling + {@link android.media.tv.TvInputManager#updateTvInputInfo(android.media.tv.TvInputInfo)} + . --> + <attr name="canPauseRecording" format="boolean" /> </declare-styleable> <!-- Attributes that can be used with <code>rating-system-definition</code> tags inside of the diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index e00aff1af37b..a0be0681bd38 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -3043,6 +3043,7 @@ =============================================================== --> <public-group type="attr" first-id="0x01010617"> + <public name="canPauseRecording" /> <!-- attribute definitions go here --> </public-group> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 1143467425af..8ac00dceea9e 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -110,7 +110,7 @@ <!-- Displayed as the title for a success/failure report enabling/disabling caller ID. --> <string name="ClipMmi">Incoming Caller ID</string> <!-- Displayed as the title for a success/failure report enabling/disabling caller ID. --> - <string name="ClirMmi">Outgoing Caller ID</string> + <string name="ClirMmi">Hide Outgoing Caller ID</string> <!-- Displayed as the title for a success/failure report enabling/disabling connected line ID. --> <string name="ColpMmi">Connected Line ID</string> <!-- Displayed as the title for a success/failure report enabling/disabling connected line ID restriction. --> diff --git a/core/tests/coretests/src/android/content/OWNERS b/core/tests/coretests/src/android/content/OWNERS index 912db1e835dc..696aa11618ff 100644 --- a/core/tests/coretests/src/android/content/OWNERS +++ b/core/tests/coretests/src/android/content/OWNERS @@ -1,3 +1,4 @@ per-file ContextTest.java = file:/services/core/java/com/android/server/wm/OWNERS per-file *Shortcut* = file:/core/java/android/content/pm/SHORTCUT_OWNERS +per-file AppSearchPersonTest.java = file:/core/java/android/content/pm/SHORTCUT_OWNERS per-file *Launcher* = file:/core/java/android/content/pm/LAUNCHER_OWNERS diff --git a/core/tests/coretests/src/android/view/autofill/OWNERS b/core/tests/coretests/src/android/view/autofill/OWNERS new file mode 100644 index 000000000000..9a30e826a24f --- /dev/null +++ b/core/tests/coretests/src/android/view/autofill/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 351486 + +include /core/java/android/view/autofill/OWNERS diff --git a/core/tests/coretests/src/android/view/contentcapture/OWNERS b/core/tests/coretests/src/android/view/contentcapture/OWNERS new file mode 100644 index 000000000000..24561c59bba6 --- /dev/null +++ b/core/tests/coretests/src/android/view/contentcapture/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 544200 + +include /core/java/android/view/contentcapture/OWNERS diff --git a/core/tests/coretests/src/android/view/textclassifier/OWNERS b/core/tests/coretests/src/android/view/textclassifier/OWNERS new file mode 100644 index 000000000000..46b3cb8824a0 --- /dev/null +++ b/core/tests/coretests/src/android/view/textclassifier/OWNERS @@ -0,0 +1 @@ +include /core/java/android/service/textclassifier/OWNERS diff --git a/keystore/java/android/security/keystore2/KeyStoreCryptoOperationChunkedStreamer.java b/keystore/java/android/security/keystore2/KeyStoreCryptoOperationChunkedStreamer.java index 6c733ba712d5..33e8dede9f5c 100644 --- a/keystore/java/android/security/keystore2/KeyStoreCryptoOperationChunkedStreamer.java +++ b/keystore/java/android/security/keystore2/KeyStoreCryptoOperationChunkedStreamer.java @@ -139,7 +139,9 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS int inputConsumed = ArrayUtils.copy(input, inputOffset, mChunk, mChunkLength, inputLength); inputLength -= inputConsumed; - inputOffset += inputOffset; + inputOffset += inputConsumed; + mChunkLength += inputConsumed; + if (mChunkLength < mChunkSizeMax) return output; byte[] o = mKeyStoreStream.update(mChunk); if (o != null) { output = ArrayUtils.concat(output, o); diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl index 1fbb67260895..5d7fdff70f5c 100644 --- a/media/java/android/media/tv/ITvInputManager.aidl +++ b/media/java/android/media/tv/ITvInputManager.aidl @@ -91,6 +91,8 @@ interface ITvInputManager { // For the recording session void startRecording(in IBinder sessionToken, in Uri programUri, in Bundle params, int userId); void stopRecording(in IBinder sessionToken, int userId); + void pauseRecording(in IBinder sessionToken, in Bundle params, int userId); + void resumeRecording(in IBinder sessionToken, in Bundle params, int userId); // For TV input hardware binding List<TvInputHardwareInfo> getHardwareList(); diff --git a/media/java/android/media/tv/ITvInputSession.aidl b/media/java/android/media/tv/ITvInputSession.aidl index 24b87d50b33e..158cf211d9f0 100644 --- a/media/java/android/media/tv/ITvInputSession.aidl +++ b/media/java/android/media/tv/ITvInputSession.aidl @@ -58,4 +58,6 @@ oneway interface ITvInputSession { // For the recording session void startRecording(in Uri programUri, in Bundle params); void stopRecording(); + void pauseRecording(in Bundle params); + void resumeRecording(in Bundle params); } diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java index e89d33d70d5c..abccf8da9cfc 100644 --- a/media/java/android/media/tv/ITvInputSessionWrapper.java +++ b/media/java/android/media/tv/ITvInputSessionWrapper.java @@ -68,6 +68,8 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand private static final int DO_TIME_SHIFT_ENABLE_POSITION_TRACKING = 19; private static final int DO_START_RECORDING = 20; private static final int DO_STOP_RECORDING = 21; + private static final int DO_PAUSE_RECORDING = 22; + private static final int DO_RESUME_RECORDING = 23; private final boolean mIsRecordingSession; private final HandlerCaller mCaller; @@ -224,6 +226,14 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand mTvInputRecordingSessionImpl.stopRecording(); break; } + case DO_PAUSE_RECORDING: { + mTvInputRecordingSessionImpl.pauseRecording((Bundle) msg.obj); + break; + } + case DO_RESUME_RECORDING: { + mTvInputRecordingSessionImpl.resumeRecording((Bundle) msg.obj); + break; + } default: { Log.w(TAG, "Unhandled message code: " + msg.what); break; @@ -363,6 +373,16 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_STOP_RECORDING)); } + @Override + public void pauseRecording(@Nullable Bundle params) { + mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_PAUSE_RECORDING, params)); + } + + @Override + public void resumeRecording(@Nullable Bundle params) { + mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_RESUME_RECORDING, params)); + } + private final class TvInputEventReceiver extends InputEventReceiver { public TvInputEventReceiver(InputChannel inputChannel, Looper looper) { super(inputChannel, looper); diff --git a/media/java/android/media/tv/TvInputHardwareInfo.java b/media/java/android/media/tv/TvInputHardwareInfo.java index b12f7c551288..1249e0d3cb0f 100644 --- a/media/java/android/media/tv/TvInputHardwareInfo.java +++ b/media/java/android/media/tv/TvInputHardwareInfo.java @@ -188,6 +188,17 @@ public final class TvInputHardwareInfo implements Parcelable { mCableConnectionStatus = source.readInt(); } + /** @hide */ + public Builder toBuilder() { + return new Builder() + .deviceId(mDeviceId) + .type(mType) + .audioType(mAudioType) + .audioAddress(mAudioAddress) + .hdmiPortId(mHdmiPortId) + .cableConnectionStatus(mCableConnectionStatus); + } + public static final class Builder { private Integer mDeviceId = null; private Integer mType = null; diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java index 195ad5bc10f9..54cb2bff5566 100644 --- a/media/java/android/media/tv/TvInputInfo.java +++ b/media/java/android/media/tv/TvInputInfo.java @@ -143,6 +143,7 @@ public final class TvInputInfo implements Parcelable { // Attributes from XML meta data. private final String mSetupActivity; private final boolean mCanRecord; + private final boolean mCanPauseRecording; private final int mTunerCount; // Attributes specific to HDMI @@ -264,8 +265,8 @@ public final class TvInputInfo implements Parcelable { private TvInputInfo(ResolveInfo service, String id, int type, boolean isHardwareInput, CharSequence label, int labelResId, Icon icon, Icon iconStandby, Icon iconDisconnected, - String setupActivity, boolean canRecord, int tunerCount, HdmiDeviceInfo hdmiDeviceInfo, - boolean isConnectedToHdmiSwitch, + String setupActivity, boolean canRecord, boolean canPauseRecording, int tunerCount, + HdmiDeviceInfo hdmiDeviceInfo, boolean isConnectedToHdmiSwitch, @HdmiAddressRelativePosition int hdmiConnectionRelativePosition, String parentId, Bundle extras) { mService = service; @@ -279,6 +280,7 @@ public final class TvInputInfo implements Parcelable { mIconDisconnected = iconDisconnected; mSetupActivity = setupActivity; mCanRecord = canRecord; + mCanPauseRecording = canPauseRecording; mTunerCount = tunerCount; mHdmiDeviceInfo = hdmiDeviceInfo; mIsConnectedToHdmiSwitch = isConnectedToHdmiSwitch; @@ -386,6 +388,14 @@ public final class TvInputInfo implements Parcelable { } /** + * Returns {@code true} if this TV input can pause recording TV programs, + * {@code false} otherwise. + */ + public boolean canPauseRecording() { + return mCanPauseRecording; + } + + /** * Returns domain-specific extras associated with this TV input. */ public Bundle getExtras() { @@ -571,6 +581,7 @@ public final class TvInputInfo implements Parcelable { && Objects.equals(mIconDisconnected, obj.mIconDisconnected) && TextUtils.equals(mSetupActivity, obj.mSetupActivity) && mCanRecord == obj.mCanRecord + && mCanPauseRecording == obj.mCanPauseRecording && mTunerCount == obj.mTunerCount && Objects.equals(mHdmiDeviceInfo, obj.mHdmiDeviceInfo) && mIsConnectedToHdmiSwitch == obj.mIsConnectedToHdmiSwitch @@ -606,6 +617,7 @@ public final class TvInputInfo implements Parcelable { dest.writeParcelable(mIconDisconnected, flags); dest.writeString(mSetupActivity); dest.writeByte(mCanRecord ? (byte) 1 : 0); + dest.writeByte(mCanPauseRecording ? (byte) 1 : 0); dest.writeInt(mTunerCount); dest.writeParcelable(mHdmiDeviceInfo, flags); dest.writeByte(mIsConnectedToHdmiSwitch ? (byte) 1 : 0); @@ -648,6 +660,7 @@ public final class TvInputInfo implements Parcelable { mIconDisconnected = in.readParcelable(null); mSetupActivity = in.readString(); mCanRecord = in.readByte() == 1; + mCanPauseRecording = in.readByte() == 1; mTunerCount = in.readInt(); mHdmiDeviceInfo = in.readParcelable(null); mIsConnectedToHdmiSwitch = in.readByte() == 1; @@ -695,6 +708,7 @@ public final class TvInputInfo implements Parcelable { private Icon mIconDisconnected; private String mSetupActivity; private Boolean mCanRecord; + private Boolean mCanPauseRecording; private Integer mTunerCount; private TvInputHardwareInfo mTvInputHardwareInfo; private HdmiDeviceInfo mHdmiDeviceInfo; @@ -879,6 +893,18 @@ public final class TvInputInfo implements Parcelable { } /** + * Sets whether this TV input can pause recording TV programs or not. + * + * @param canPauseRecording Whether this TV input can pause recording TV programs. + * @return This Builder object to allow for chaining of calls to builder methods. + */ + @NonNull + public Builder setCanPauseRecording(boolean canPauseRecording) { + this.mCanPauseRecording = canPauseRecording; + return this; + } + + /** * Sets domain-specific extras associated with this TV input. * * @param extras Domain-specific extras associated with this TV input. Keys <em>must</em> be @@ -927,7 +953,9 @@ public final class TvInputInfo implements Parcelable { parseServiceMetadata(type); return new TvInputInfo(mResolveInfo, id, type, isHardwareInput, mLabel, mLabelResId, mIcon, mIconStandby, mIconDisconnected, mSetupActivity, - mCanRecord == null ? false : mCanRecord, mTunerCount == null ? 0 : mTunerCount, + mCanRecord == null ? false : mCanRecord, + mCanPauseRecording == null ? false : mCanPauseRecording, + mTunerCount == null ? 0 : mTunerCount, mHdmiDeviceInfo, isConnectedToHdmiSwitch, hdmiConnectionRelativePosition, mParentId, mExtras); } @@ -997,6 +1025,12 @@ public final class TvInputInfo implements Parcelable { mTunerCount = sa.getInt( com.android.internal.R.styleable.TvInputService_tunerCount, 1); } + if (mCanPauseRecording == null) { + mCanPauseRecording = sa.getBoolean( + com.android.internal.R.styleable.TvInputService_canPauseRecording, + false); + } + sa.recycle(); } catch (IOException | XmlPullParserException e) { throw new IllegalStateException("Failed reading meta-data for " + si.packageName, e); diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java index 98a01a4cb449..6341dc263efd 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -2476,6 +2476,40 @@ public final class TvInputManager { } /** + * Pauses TV program recording in the current recording session. + * + * @param params A set of extra parameters which might be handled with this event. + */ + void pauseRecording(@NonNull Bundle params) { + if (mToken == null) { + Log.w(TAG, "The session has been already released"); + return; + } + try { + mService.pauseRecording(mToken, params, mUserId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Resumes TV program recording in the current recording session. + * + * @param params A set of extra parameters which might be handled with this event. + */ + void resumeRecording(@NonNull Bundle params) { + if (mToken == null) { + Log.w(TAG, "The session has been already released"); + return; + } + try { + mService.resumeRecording(mToken, params, mUserId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Calls {@link TvInputService.Session#appPrivateCommand(String, Bundle) * TvInputService.Session.appPrivateCommand()} on the current TvView. * diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java index abbf4780bcc1..0fe9d504b951 100755 --- a/media/java/android/media/tv/TvInputService.java +++ b/media/java/android/media/tv/TvInputService.java @@ -1852,6 +1852,28 @@ public abstract class TvInputService extends Service { /** + * Called when the application requests to pause TV program recording. Recording must pause + * immediately when this method is called. + * + * If the pause request cannot be fulfilled, the session must call + * {@link #notifyError(int)}. + * + * @param params Domain-specific data for recording request. + */ + public void onPauseRecording(@NonNull Bundle params) { } + + /** + * Called when the application requests to resume TV program recording. Recording must + * resume immediately when this method is called. + * + * If the resume request cannot be fulfilled, the session must call + * {@link #notifyError(int)}. + * + * @param params Domain-specific data for recording request. + */ + public void onResumeRecording(@NonNull Bundle params) { } + + /** * Called when the application requests to release all the resources held by this recording * session. */ @@ -1903,6 +1925,22 @@ public abstract class TvInputService extends Service { } /** + * Calls {@link #onPauseRecording(Bundle)}. + * + */ + void pauseRecording(@NonNull Bundle params) { + onPauseRecording(params); + } + + /** + * Calls {@link #onResumeRecording(Bundle)}. + * + */ + void resumeRecording(@NonNull Bundle params) { + onResumeRecording(params); + } + + /** * Calls {@link #onAppPrivateCommand(String, Bundle)}. */ void appPrivateCommand(String action, Bundle data) { diff --git a/media/java/android/media/tv/TvRecordingClient.java b/media/java/android/media/tv/TvRecordingClient.java index 23fadac8a72b..180e2bd6845b 100644 --- a/media/java/android/media/tv/TvRecordingClient.java +++ b/media/java/android/media/tv/TvRecordingClient.java @@ -30,6 +30,7 @@ import android.util.Log; import android.util.Pair; import java.util.ArrayDeque; +import java.util.Objects; import java.util.Queue; /** @@ -49,6 +50,8 @@ public class TvRecordingClient { private boolean mIsRecordingStarted; private boolean mIsTuned; + private boolean mIsPaused; + private boolean mIsRecordingStopping; private final Queue<Pair<String, Bundle>> mPendingAppPrivateCommands = new ArrayDeque<>(); /** @@ -113,17 +116,22 @@ public class TvRecordingClient { if (TextUtils.isEmpty(inputId)) { throw new IllegalArgumentException("inputId cannot be null or an empty string"); } - if (mIsRecordingStarted) { + if (mIsRecordingStarted && !mIsPaused) { throw new IllegalStateException("tune failed - recording already started"); } if (mSessionCallback != null && TextUtils.equals(mSessionCallback.mInputId, inputId)) { if (mSession != null) { + mSessionCallback.mChannelUri = channelUri; mSession.tune(channelUri, params); } else { mSessionCallback.mChannelUri = channelUri; mSessionCallback.mConnectionParams = params; } + mIsTuned = false; } else { + if (mIsPaused) { + throw new IllegalStateException("tune failed - inputId is changed during pause"); + } resetInternal(); mSessionCallback = new MySessionCallback(inputId, channelUri, params); if (mTvInputManager != null) { @@ -148,6 +156,8 @@ public class TvRecordingClient { mSession.release(); mIsTuned = false; mIsRecordingStarted = false; + mIsPaused = false; + mIsRecordingStopping = false; mSession = null; } } @@ -169,7 +179,8 @@ public class TvRecordingClient { * * @param programUri The URI for the TV program to record, built by * {@link TvContract#buildProgramUri(long)}. Can be {@code null}. - * @throws IllegalStateException If {@link #tune} request hasn't been handled yet. + * @throws IllegalStateException If {@link #tune} request hasn't been handled yet or during + * pause. */ public void startRecording(@Nullable Uri programUri) { startRecording(programUri, Bundle.EMPTY); @@ -195,11 +206,16 @@ public class TvRecordingClient { * @param params Domain-specific data for this request. Keys <em>must</em> be a scoped * name, i.e. prefixed with a package name you own, so that different developers will * not create conflicting keys. - * @throws IllegalStateException If {@link #tune} request hasn't been handled yet. + * @throws IllegalStateException If {@link #tune} request hasn't been handled yet or during + * pause. */ public void startRecording(@Nullable Uri programUri, @NonNull Bundle params) { - if (!mIsTuned) { - throw new IllegalStateException("startRecording failed - not yet tuned"); + if (mIsRecordingStopping || !mIsTuned || mIsPaused) { + throw new IllegalStateException("startRecording failed -" + + "recording not yet stopped or not yet tuned or paused"); + } + if (mIsRecordingStarted) { + Log.w(TAG, "startRecording failed - recording already started"); } if (mSession != null) { mSession.startRecording(programUri, params); @@ -225,6 +241,103 @@ public class TvRecordingClient { } if (mSession != null) { mSession.stopRecording(); + if (mIsRecordingStarted) { + mIsRecordingStopping = true; + } + } + } + + /** + * Pause TV program recording in the current recording session. Recording is expected to pause + * immediately when this method is called. If recording has not yet started in the current + * recording session, this method does nothing. + * + * <p>In pause status, the application can tune during recording. To continue recording, + * please call {@link TvRecordingClient#resumeRecording()} to resume instead of + * {@link TvRecordingClient#startRecording(Uri)}. Application can stop + * the recording with {@link TvRecordingClient#stopRecording()} in recording pause status. + * + * <p>If the pause request cannot be fulfilled, the recording session will respond by calling + * {@link RecordingCallback#onError(int)}. + */ + public void pauseRecording() { + pauseRecording(Bundle.EMPTY); + } + + /** + * Pause TV program recording in the current recording session. Recording is expected to pause + * immediately when this method is called. If recording has not yet started in the current + * recording session, this method does nothing. + * + * <p>In pause status, the application can tune during recording. To continue recording, + * please call {@link TvRecordingClient#resumeRecording()} to resume instead of + * {@link TvRecordingClient#startRecording(Uri)}. Application can stop + * the recording with {@link TvRecordingClient#stopRecording()} in recording pause status. + * + * <p>If the pause request cannot be fulfilled, the recording session will respond by calling + * {@link RecordingCallback#onError(int)}. + * + * @param params Domain-specific data for this request. + */ + public void pauseRecording(@NonNull Bundle params) { + if (!mIsRecordingStarted || mIsRecordingStopping) { + throw new IllegalStateException( + "pauseRecording failed - recording not yet started or stopping"); + } + TvInputInfo info = mTvInputManager.getTvInputInfo(mSessionCallback.mInputId); + if (info == null || !info.canPauseRecording()) { + throw new UnsupportedOperationException( + "pauseRecording failed - operation not supported"); + } + if (mIsPaused) { + Log.w(TAG, "pauseRecording failed - recording already paused"); + } + if (mSession != null) { + mSession.pauseRecording(params); + mIsPaused = true; + } + } + + /** + * Resume TV program recording only in recording pause status in the current recording session. + * Recording is expected to resume immediately when this method is called. If recording has not + * yet paused in the current recording session, this method does nothing. + * + * <p>When record is resumed, the recording is continue and can not re-tune. Application can + * stop the recording with {@link TvRecordingClient#stopRecording()} after record resumed. + * + * <p>If the pause request cannot be fulfilled, the recording session will respond by calling + * {@link RecordingCallback#onError(int)}. + */ + public void resumeRecording() { + resumeRecording(Bundle.EMPTY); + } + + /** + * Resume TV program recording only in recording pause status in the current recording session. + * Recording is expected to resume immediately when this method is called. If recording has not + * yet paused in the current recording session, this method does nothing. + * + * <p>When record is resumed, the recording is continues and can not re-tune. Application can + * stop the recording with {@link TvRecordingClient#stopRecording()} after record resumed. + * + * <p>If the resume request cannot be fulfilled, the recording session will respond by calling + * {@link RecordingCallback#onError(int)}. + * + * @param params Domain-specific data for this request. + */ + public void resumeRecording(@NonNull Bundle params) { + if (!mIsRecordingStarted || mIsRecordingStopping || !mIsTuned) { + throw new IllegalStateException( + "resumeRecording failed - recording not yet started or stopping or " + + "not yet tuned"); + } + if (!mIsPaused) { + Log.w(TAG, "resumeRecording failed - recording not yet paused"); + } + if (mSession != null) { + mSession.resumeRecording(params); + mIsPaused = false; } } @@ -367,6 +480,10 @@ public class TvRecordingClient { Log.w(TAG, "onTuned - session not created"); return; } + if (mIsTuned || !Objects.equals(mChannelUri, channelUri)) { + Log.w(TAG, "onTuned - already tuned or not yet tuned to last channel"); + return; + } mIsTuned = true; mCallback.onTuned(channelUri); } @@ -382,6 +499,8 @@ public class TvRecordingClient { } mIsTuned = false; mIsRecordingStarted = false; + mIsPaused = false; + mIsRecordingStopping = false; mSessionCallback = null; mSession = null; if (mCallback != null) { @@ -398,7 +517,13 @@ public class TvRecordingClient { Log.w(TAG, "onRecordingStopped - session not created"); return; } + if (!mIsRecordingStarted) { + Log.w(TAG, "onRecordingStopped - recording not yet started"); + return; + } mIsRecordingStarted = false; + mIsPaused = false; + mIsRecordingStopping = false; mCallback.onRecordingStopped(recordedProgramUri); } diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml index c63cf06cf75c..2b5e9cdc017d 100644 --- a/packages/SettingsLib/res/values/arrays.xml +++ b/packages/SettingsLib/res/values/arrays.xml @@ -291,7 +291,7 @@ <item>256K</item> <item>1M</item> <item>4M</item> - <item>16M</item> + <item>8M</item> </string-array> <!-- Titles for logd limit size lowram selection preference. [CHAR LIMIT=14] --> @@ -309,7 +309,7 @@ <item>262144</item> <item>1048576</item> <item>4194304</item> - <item>16777216</item> + <item>8388608</item> </string-array> <!-- Summaries for logd limit size selection preference. [CHAR LIMIT=50]--> @@ -319,7 +319,7 @@ <item>256K per log buffer</item> <item>1M per log buffer</item> <item>4M per log buffer</item> - <item>16M per log buffer</item> + <item>8M per log buffer</item> </string-array> <!-- Values for logpersist state selection preference. --> diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 741a6803a1e3..4b6862c6d186 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -156,6 +156,7 @@ <uses-permission android:name="android.permission.MANAGE_CONTENT_SUGGESTIONS" /> <uses-permission android:name="android.permission.MANAGE_APP_PREDICTIONS" /> <uses-permission android:name="android.permission.MANAGE_SEARCH_UI" /> + <uses-permission android:name="android.permission.MANAGE_SMARTSPACE" /> <uses-permission android:name="android.permission.NETWORK_SETTINGS" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.SET_TIME" /> @@ -345,6 +346,9 @@ <uses-permission android:name="android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS" /> <uses-permission android:name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS" /> + <!-- Permission required for CTS test - CtsSensorPrivacyTestCases --> + <uses-permission android:name="android.permission.MANAGE_SENSOR_PRIVACY" /> + <application android:label="@string/app_label" android:theme="@android:style/Theme.DeviceDefault.DayNight" android:defaultToDeviceProtectedStorage="true" diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java index 309d4b04ebbf..c5a35eaf3e6c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java @@ -29,7 +29,6 @@ import android.net.ConnectivityManager; import android.net.ConnectivityManager.NetworkCallback; import android.net.IConnectivityManager; import android.net.Network; -import android.net.NetworkCapabilities; import android.net.NetworkRequest; import android.os.Handler; import android.os.RemoteException; @@ -66,12 +65,8 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi private static final String TAG = "SecurityController"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); - private static final NetworkRequest REQUEST = new NetworkRequest.Builder() - .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) - .setUids(null) - .build(); + private static final NetworkRequest REQUEST = + new NetworkRequest.Builder().clearCapabilities().build(); private static final int NO_NETWORK = -1; private static final String VPN_BRANDED_META_DATA = "com.android.systemui.IS_BRANDED"; diff --git a/packages/services/CameraExtensionsProxy/OWNERS b/packages/services/CameraExtensionsProxy/OWNERS new file mode 100644 index 000000000000..f48a95c5b3a3 --- /dev/null +++ b/packages/services/CameraExtensionsProxy/OWNERS @@ -0,0 +1 @@ +include platform/frameworks/av:/camera/OWNERS diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 5f6e8df30f8d..5560f8137e4c 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -64,6 +64,7 @@ import android.telephony.DisconnectCause; import android.telephony.LocationAccessPolicy; import android.telephony.PhoneCapability; import android.telephony.PhoneStateListener; +import android.telephony.PhysicalChannelConfig; import android.telephony.PreciseCallState; import android.telephony.PreciseDataConnectionState; import android.telephony.PreciseDisconnectCause; @@ -78,6 +79,7 @@ import android.telephony.data.ApnSetting; import android.telephony.emergency.EmergencyNumber; import android.telephony.ims.ImsReasonInfo; import android.util.ArrayMap; +import android.util.ArraySet; import android.util.LocalLog; import android.util.Pair; @@ -99,10 +101,13 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; /** * Since phone process can be restarted, this class provides a centralized place @@ -142,14 +147,14 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { int callerUid; int callerPid; - int events; + Set<Integer> eventList; int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; int phoneId = SubscriptionManager.INVALID_SIM_SLOT_INDEX; - boolean matchPhoneStateListenerEvent(int events) { - return (callback != null) && ((events & this.events) != 0); + boolean matchPhoneStateListenerEvent(int event) { + return (callback != null) && (this.eventList.contains(event)); } boolean matchOnSubscriptionsChangedListener() { @@ -177,7 +182,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { + onSubscriptionsChangedListenerCallback + " onOpportunisticSubscriptionsChangedListenererCallback=" + onOpportunisticSubscriptionsChangedListenerCallback + " subId=" + subId - + " phoneId=" + phoneId + " events=" + Integer.toHexString(events) + "}"; + + " phoneId=" + phoneId + " events=" + eventList + "}"; } } @@ -306,6 +311,12 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { private final LocalLog mListenLog = new LocalLog(200); + private List<PhysicalChannelConfig> mPhysicalChannelConfigs; + + private boolean mIsDataEnabled = false; + + private int mDataEnabledReason; + /** * Per-phone map of precise data connection state. The key of the map is the pair of transport * type and APN setting. This is the cache to prevent redundant callbacks to the listeners. @@ -315,39 +326,62 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { private List<Map<Pair<Integer, ApnSetting>, PreciseDataConnectionState>> mPreciseDataConnectionStates; - // Starting in Q, almost all cellular location requires FINE location enforcement. - // Prior to Q, cellular was available with COARSE location enforcement. Bits in this - // list will be checked for COARSE on apps targeting P or earlier and FINE on Q or later. - static final int ENFORCE_LOCATION_PERMISSION_MASK = - PhoneStateListener.LISTEN_CELL_LOCATION - | PhoneStateListener.LISTEN_CELL_INFO - | PhoneStateListener.LISTEN_REGISTRATION_FAILURE - | PhoneStateListener.LISTEN_BARRING_INFO; - - static final int ENFORCE_PHONE_STATE_PERMISSION_MASK = - PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR - | PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR - | PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST - | PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED; - - static final int ENFORCE_PRECISE_PHONE_STATE_PERMISSION_MASK = - PhoneStateListener.LISTEN_PRECISE_CALL_STATE - | PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE - | PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES - | PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED - | PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES - | PhoneStateListener.LISTEN_REGISTRATION_FAILURE - | PhoneStateListener.LISTEN_BARRING_INFO; - - static final int READ_ACTIVE_EMERGENCY_SESSION_PERMISSION_MASK = - PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL - | PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_SMS; - - static final int READ_PRIVILEGED_PHONE_STATE_PERMISSION_MASK = - PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT - | PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED - | PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED - | PhoneStateListener.LISTEN_VOICE_ACTIVATION_STATE; + private static final Set<Integer> REQUIRE_PRECISE_PHONE_STATE_PERMISSION; + static { + REQUIRE_PRECISE_PHONE_STATE_PERMISSION = new HashSet<Integer>(); + REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add( + PhoneStateListener.EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED); + REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add( + PhoneStateListener.EVENT_DATA_CONNECTION_REAL_TIME_INFO_CHANGED); + REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add( + PhoneStateListener.EVENT_PRECISE_CALL_STATE_CHANGED); + REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add( + PhoneStateListener.EVENT_CALL_DISCONNECT_CAUSE_CHANGED); + REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add( + PhoneStateListener.EVENT_CALL_ATTRIBUTES_CHANGED); + REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add( + PhoneStateListener.EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED); + REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(PhoneStateListener.EVENT_REGISTRATION_FAILURE); + REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(PhoneStateListener.EVENT_BARRING_INFO_CHANGED); + REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add( + PhoneStateListener.EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED); + REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add( + PhoneStateListener.EVENT_DATA_ENABLED_CHANGED); + } + + private boolean isLocationPermissionRequired(Set<Integer> events) { + return events.contains(PhoneStateListener.EVENT_CELL_LOCATION_CHANGED) + || events.contains(PhoneStateListener.EVENT_CELL_INFO_CHANGED) + || events.contains(PhoneStateListener.EVENT_REGISTRATION_FAILURE) + || events.contains(PhoneStateListener.EVENT_BARRING_INFO_CHANGED); + } + + private boolean isPhoneStatePermissionRequired(Set<Integer> events) { + return events.contains(PhoneStateListener.EVENT_CALL_FORWARDING_INDICATOR_CHANGED) + || events.contains(PhoneStateListener.EVENT_MESSAGE_WAITING_INDICATOR_CHANGED) + || events.contains(PhoneStateListener.EVENT_EMERGENCY_NUMBER_LIST_CHANGED) + || events.contains(PhoneStateListener.EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED); + } + + private boolean isPrecisePhoneStatePermissionRequired(Set<Integer> events) { + for (Integer requireEvent : REQUIRE_PRECISE_PHONE_STATE_PERMISSION) { + if (events.contains(requireEvent)) { + return true; + } + } + return false; + } + + private boolean isActiveEmergencySessionPermissionRequired(Set<Integer> events) { + return events.contains(PhoneStateListener.EVENT_OUTGOING_EMERGENCY_CALL) + || events.contains(PhoneStateListener.EVENT_OUTGOING_EMERGENCY_SMS); + } + + private boolean isPrivilegedPhoneStatePermissionRequired(Set<Integer> events) { + return events.contains(PhoneStateListener.EVENT_SRVCC_STATE_CHANGED) + || events.contains(PhoneStateListener.EVENT_VOICE_ACTIVATION_STATE_CHANGED) + || events.contains(PhoneStateListener.EVENT_RADIO_POWER_STATE_CHANGED); + } private static final int MSG_USER_SWITCHED = 1; private static final int MSG_UPDATE_DEFAULT_SUB = 2; @@ -495,6 +529,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { cutListToSize(mImsReasonInfo, mNumPhones); cutListToSize(mPreciseDataConnectionStates, mNumPhones); cutListToSize(mBarringInfo, mNumPhones); + cutListToSize(mPhysicalChannelConfigs, mNumPhones); return; } @@ -528,6 +563,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mPreciseDataConnectionStates.add(new ArrayMap<>()); mBarringInfo.add(i, new BarringInfo()); mTelephonyDisplayInfos[i] = null; + mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig.Builder().build()); } } @@ -588,6 +624,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mOutgoingSmsEmergencyNumber = new EmergencyNumber[numPhones]; mBarringInfo = new ArrayList<>(); mTelephonyDisplayInfos = new TelephonyDisplayInfo[numPhones]; + mPhysicalChannelConfigs = new ArrayList<>(); for (int i = 0; i < numPhones; i++) { mCallState[i] = TelephonyManager.CALL_STATE_IDLE; mDataActivity[i] = TelephonyManager.DATA_ACTIVITY_NONE; @@ -617,6 +654,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mPreciseDataConnectionStates.add(new ArrayMap<>()); mBarringInfo.add(i, new BarringInfo()); mTelephonyDisplayInfos[i] = null; + mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig.Builder().build()); } mAppOps = mContext.getSystemService(AppOpsManager.class); @@ -659,7 +697,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { r.callingFeatureId = callingFeatureId; r.callerUid = Binder.getCallingUid(); r.callerPid = Binder.getCallingPid(); - r.events = 0; + r.eventList = new ArraySet<>(); if (DBG) { log("listen oscl: Register r=" + r); } @@ -713,7 +751,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { r.callingFeatureId = callingFeatureId; r.callerUid = Binder.getCallingUid(); r.callerPid = Binder.getCallingPid(); - r.events = 0; + r.eventList = new ArraySet<>(); if (DBG) { log("listen ooscl: Register r=" + r); } @@ -786,323 +824,337 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - @Deprecated @Override - public void listen(String callingPackage, IPhoneStateListener callback, int events, - boolean notifyNow) { - listenWithFeature(callingPackage, null, callback, events, notifyNow); - } - - @Override - public void listenWithFeature(String callingPackage, String callingFeatureId, - IPhoneStateListener callback, int events, boolean notifyNow) { - listenForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, callingPackage, - callingFeatureId, callback, events, notifyNow); - } - - @Override - public void listenForSubscriber(int subId, String callingPackage, String callingFeatureId, - IPhoneStateListener callback, int events, boolean notifyNow) { - listen(callingPackage, callingFeatureId, callback, events, notifyNow, subId); + public void listenWithEventList(int subId, String callingPackage, String callingFeatureId, + IPhoneStateListener callback, int[] events, boolean notifyNow) { + Set<Integer> eventList = Arrays.stream(events).boxed().collect(Collectors.toSet()); + listen(callingPackage, callingFeatureId, callback, eventList, notifyNow, subId); } private void listen(String callingPackage, @Nullable String callingFeatureId, - IPhoneStateListener callback, int events, boolean notifyNow, int subId) { + IPhoneStateListener callback, Set<Integer> events, boolean notifyNow, int subId) { int callerUserId = UserHandle.getCallingUserId(); mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); String str = "listen: E pkg=" + pii(callingPackage) + " uid=" + Binder.getCallingUid() - + " events=0x" + Integer.toHexString(events) + " notifyNow=" + notifyNow + " subId=" - + subId + " myUserId=" + UserHandle.myUserId() + " callerUserId=" + callerUserId; + + " events=" + events + " notifyNow=" + notifyNow + + " subId=" + subId + " myUserId=" + UserHandle.myUserId() + + " callerUserId=" + callerUserId; mListenLog.log(str); if (VDBG) { log(str); } - if (events != PhoneStateListener.LISTEN_NONE) { - // Checks permission and throws SecurityException for disallowed operations. For pre-M - // apps whose runtime permission has been revoked, we return immediately to skip sending - // events to the app without crashing it. - if (!checkListenerPermission(events, subId, callingPackage, callingFeatureId, - "listen")) { - return; + if (events.isEmpty()) { + if (DBG) { + log("listen: Unregister"); } + events.clear(); + remove(callback.asBinder()); + return; + } - int phoneId = getPhoneIdFromSubId(subId); - synchronized (mRecords) { - // register - IBinder b = callback.asBinder(); - boolean doesLimitApply = - Binder.getCallingUid() != Process.SYSTEM_UID - && Binder.getCallingUid() != Process.PHONE_UID - && Binder.getCallingUid() != Process.myUid(); - Record r = add(b, Binder.getCallingUid(), Binder.getCallingPid(), doesLimitApply); + // Checks permission and throws SecurityException for disallowed operations. For pre-M + // apps whose runtime permission has been revoked, we return immediately to skip sending + // events to the app without crashing it. + if (!checkListenerPermission(events, subId, callingPackage, callingFeatureId, + "listen")) { + return; + } - if (r == null) { - return; - } + int phoneId = getPhoneIdFromSubId(subId); + synchronized (mRecords) { + // register + IBinder b = callback.asBinder(); + boolean doesLimitApply = + Binder.getCallingUid() != Process.SYSTEM_UID + && Binder.getCallingUid() != Process.PHONE_UID + && Binder.getCallingUid() != Process.myUid(); + Record r = add(b, Binder.getCallingUid(), Binder.getCallingPid(), doesLimitApply); - r.context = mContext; - r.callback = callback; - r.callingPackage = callingPackage; - r.callingFeatureId = callingFeatureId; - r.callerUid = Binder.getCallingUid(); - r.callerPid = Binder.getCallingPid(); - // Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID, - // force all illegal subId to SubscriptionManager.DEFAULT_SUB_ID - if (!SubscriptionManager.isValidSubscriptionId(subId)) { - r.subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; - } else {//APP specify subID - r.subId = subId; - } - r.phoneId = phoneId; - r.events = events; - if (DBG) { - log("listen: Register r=" + r + " r.subId=" + r.subId + " phoneId=" + phoneId); - } - if (notifyNow && validatePhoneId(phoneId)) { - if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) { - try { - if (VDBG) log("listen: call onSSC state=" + mServiceState[phoneId]); - ServiceState rawSs = new ServiceState(mServiceState[phoneId]); - if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) { - r.callback.onServiceStateChanged(rawSs); - } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) { - r.callback.onServiceStateChanged( - rawSs.createLocationInfoSanitizedCopy(false)); - } else { - r.callback.onServiceStateChanged( - rawSs.createLocationInfoSanitizedCopy(true)); - } - } catch (RemoteException ex) { - remove(r.binder); + if (r == null) { + return; + } + + r.context = mContext; + r.callback = callback; + r.callingPackage = callingPackage; + r.callingFeatureId = callingFeatureId; + r.callerUid = Binder.getCallingUid(); + r.callerPid = Binder.getCallingPid(); + // Legacy applications pass SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, + // force all illegal subId to SubscriptionManager.DEFAULT_SUBSCRIPTION_ID + if (!SubscriptionManager.isValidSubscriptionId(subId)) { + r.subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; + } else {//APP specify subID + r.subId = subId; + } + r.phoneId = phoneId; + r.eventList = events; + if (DBG) { + log("listen: Register r=" + r + " r.subId=" + r.subId + " phoneId=" + phoneId); + } + if (notifyNow && validatePhoneId(phoneId)) { + if (events.contains(PhoneStateListener.EVENT_SERVICE_STATE_CHANGED)) { + try { + if (VDBG) log("listen: call onSSC state=" + mServiceState[phoneId]); + ServiceState rawSs = new ServiceState(mServiceState[phoneId]); + if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) { + r.callback.onServiceStateChanged(rawSs); + } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) { + r.callback.onServiceStateChanged( + rawSs.createLocationInfoSanitizedCopy(false)); + } else { + r.callback.onServiceStateChanged( + rawSs.createLocationInfoSanitizedCopy(true)); } + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) { - try { - if (mSignalStrength[phoneId] != null) { - int gsmSignalStrength = mSignalStrength[phoneId] - .getGsmSignalStrength(); - r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1 - : gsmSignalStrength)); - } - } catch (RemoteException ex) { - remove(r.binder); + } + if (events.contains(PhoneStateListener.EVENT_SIGNAL_STRENGTH_CHANGED)) { + try { + if (mSignalStrength[phoneId] != null) { + int gsmSignalStrength = mSignalStrength[phoneId] + .getGsmSignalStrength(); + r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1 + : gsmSignalStrength)); } + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) { - try { - r.callback.onMessageWaitingIndicatorChanged( - mMessageWaiting[phoneId]); - } catch (RemoteException ex) { - remove(r.binder); - } + } + if (events.contains( + PhoneStateListener.EVENT_MESSAGE_WAITING_INDICATOR_CHANGED)) { + try { + r.callback.onMessageWaitingIndicatorChanged( + mMessageWaiting[phoneId]); + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) { - try { - r.callback.onCallForwardingIndicatorChanged( - mCallForwarding[phoneId]); - } catch (RemoteException ex) { - remove(r.binder); - } + } + if (events.contains( + PhoneStateListener.EVENT_CALL_FORWARDING_INDICATOR_CHANGED)) { + try { + r.callback.onCallForwardingIndicatorChanged( + mCallForwarding[phoneId]); + } catch (RemoteException ex) { + remove(r.binder); } - if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) { - try { - if (DBG_LOC) log("listen: mCellIdentity = " + mCellIdentity[phoneId]); - if (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE) - && checkFineLocationAccess(r, Build.VERSION_CODES.Q)) { - // null will be translated to empty CellLocation object in client. - r.callback.onCellLocationChanged(mCellIdentity[phoneId]); - } - } catch (RemoteException ex) { - remove(r.binder); + } + if (validateEventAndUserLocked( + r, PhoneStateListener.EVENT_CELL_LOCATION_CHANGED)) { + try { + if (DBG_LOC) log("listen: mCellIdentity = " + mCellIdentity[phoneId]); + if (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE) + && checkFineLocationAccess(r, Build.VERSION_CODES.Q)) { + // null will be translated to empty CellLocation object in client. + r.callback.onCellLocationChanged(mCellIdentity[phoneId]); } + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener.LISTEN_CALL_STATE) != 0) { - try { - r.callback.onCallStateChanged(mCallState[phoneId], - getCallIncomingNumber(r, phoneId)); - } catch (RemoteException ex) { - remove(r.binder); - } + } + if (events.contains(PhoneStateListener.EVENT_CALL_STATE_CHANGED)) { + try { + r.callback.onCallStateChanged(mCallState[phoneId], + getCallIncomingNumber(r, phoneId)); + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) { - try { - r.callback.onDataConnectionStateChanged(mDataConnectionState[phoneId], + } + if (events.contains(PhoneStateListener.EVENT_DATA_CONNECTION_STATE_CHANGED)) { + try { + r.callback.onDataConnectionStateChanged(mDataConnectionState[phoneId], mDataConnectionNetworkType[phoneId]); - } catch (RemoteException ex) { - remove(r.binder); - } + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) { - try { - r.callback.onDataActivity(mDataActivity[phoneId]); - } catch (RemoteException ex) { - remove(r.binder); - } + } + if (events.contains(PhoneStateListener.EVENT_DATA_ACTIVITY_CHANGED)) { + try { + r.callback.onDataActivity(mDataActivity[phoneId]); + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) { - try { - if (mSignalStrength[phoneId] != null) { - r.callback.onSignalStrengthsChanged(mSignalStrength[phoneId]); - } - } catch (RemoteException ex) { - remove(r.binder); + } + if (events.contains(PhoneStateListener.EVENT_SIGNAL_STRENGTHS_CHANGED)) { + try { + if (mSignalStrength[phoneId] != null) { + r.callback.onSignalStrengthsChanged(mSignalStrength[phoneId]); } + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) - != 0) { - updateReportSignalStrengthDecision(r.subId); - try { - if (mSignalStrength[phoneId] != null) { - r.callback.onSignalStrengthsChanged(mSignalStrength[phoneId]); - } - } catch (RemoteException ex) { - remove(r.binder); + } + if (events.contains( + PhoneStateListener.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED)) { + updateReportSignalStrengthDecision(r.subId); + try { + if (mSignalStrength[phoneId] != null) { + r.callback.onSignalStrengthsChanged(mSignalStrength[phoneId]); } + } catch (RemoteException ex) { + remove(r.binder); } - if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) { - try { - if (DBG_LOC) log("listen: mCellInfo[" + phoneId + "] = " - + mCellInfo.get(phoneId)); - if (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE) - && checkFineLocationAccess(r, Build.VERSION_CODES.Q)) { - r.callback.onCellInfoChanged(mCellInfo.get(phoneId)); - } - } catch (RemoteException ex) { - remove(r.binder); + } + if (validateEventAndUserLocked( + r, PhoneStateListener.EVENT_CELL_INFO_CHANGED)) { + try { + if (DBG_LOC) log("listen: mCellInfo[" + phoneId + "] = " + + mCellInfo.get(phoneId)); + if (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE) + && checkFineLocationAccess(r, Build.VERSION_CODES.Q)) { + r.callback.onCellInfoChanged(mCellInfo.get(phoneId)); } + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) { - try { - r.callback.onPreciseCallStateChanged(mPreciseCallState[phoneId]); - } catch (RemoteException ex) { - remove(r.binder); - } + } + if (events.contains(PhoneStateListener.EVENT_PRECISE_CALL_STATE_CHANGED)) { + try { + r.callback.onPreciseCallStateChanged(mPreciseCallState[phoneId]); + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES) != 0) { - try { - r.callback.onCallDisconnectCauseChanged(mCallDisconnectCause[phoneId], - mCallPreciseDisconnectCause[phoneId]); - } catch (RemoteException ex) { - remove(r.binder); - } + } + if (events.contains(PhoneStateListener.EVENT_CALL_DISCONNECT_CAUSE_CHANGED)) { + try { + r.callback.onCallDisconnectCauseChanged(mCallDisconnectCause[phoneId], + mCallPreciseDisconnectCause[phoneId]); + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES) != 0) { - try { - r.callback.onImsCallDisconnectCauseChanged(mImsReasonInfo.get(phoneId)); - } catch (RemoteException ex) { - remove(r.binder); - } + } + if (events.contains(PhoneStateListener.EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED)) { + try { + r.callback.onImsCallDisconnectCauseChanged(mImsReasonInfo.get(phoneId)); + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) { - try { - for (PreciseDataConnectionState pdcs - : mPreciseDataConnectionStates.get(phoneId).values()) { - r.callback.onPreciseDataConnectionStateChanged(pdcs); - } - } catch (RemoteException ex) { - remove(r.binder); + } + if (events.contains( + PhoneStateListener.EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED)) { + try { + for (PreciseDataConnectionState pdcs + : mPreciseDataConnectionStates.get(phoneId).values()) { + r.callback.onPreciseDataConnectionStateChanged(pdcs); } + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE) != 0) { - try { - r.callback.onCarrierNetworkChange(mCarrierNetworkChangeState); - } catch (RemoteException ex) { - remove(r.binder); - } + } + if (events.contains(PhoneStateListener.EVENT_CARRIER_NETWORK_CHANGED)) { + try { + r.callback.onCarrierNetworkChange(mCarrierNetworkChangeState); + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener.LISTEN_VOICE_ACTIVATION_STATE) !=0) { - try { - r.callback.onVoiceActivationStateChanged( - mVoiceActivationState[phoneId]); - } catch (RemoteException ex) { - remove(r.binder); - } + } + if (events.contains(PhoneStateListener.EVENT_VOICE_ACTIVATION_STATE_CHANGED)) { + try { + r.callback.onVoiceActivationStateChanged( + mVoiceActivationState[phoneId]); + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener.LISTEN_DATA_ACTIVATION_STATE) !=0) { - try { - r.callback.onDataActivationStateChanged(mDataActivationState[phoneId]); - } catch (RemoteException ex) { - remove(r.binder); - } + } + if (events.contains(PhoneStateListener.EVENT_DATA_ACTIVATION_STATE_CHANGED)) { + try { + r.callback.onDataActivationStateChanged(mDataActivationState[phoneId]); + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener.LISTEN_USER_MOBILE_DATA_STATE) != 0) { - try { - r.callback.onUserMobileDataStateChanged(mUserMobileDataState[phoneId]); - } catch (RemoteException ex) { - remove(r.binder); - } + } + if (events.contains(PhoneStateListener.EVENT_USER_MOBILE_DATA_STATE_CHANGED)) { + try { + r.callback.onUserMobileDataStateChanged(mUserMobileDataState[phoneId]); + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED) != 0) { - try { - if (mTelephonyDisplayInfos[phoneId] != null) { - r.callback.onDisplayInfoChanged(mTelephonyDisplayInfos[phoneId]); - } - } catch (RemoteException ex) { - remove(r.binder); + } + if (events.contains(PhoneStateListener.EVENT_DISPLAY_INFO_CHANGED)) { + try { + if (mTelephonyDisplayInfos[phoneId] != null) { + r.callback.onDisplayInfoChanged(mTelephonyDisplayInfos[phoneId]); } + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST) != 0) { - try { - r.callback.onEmergencyNumberListChanged(mEmergencyNumberList); - } catch (RemoteException ex) { - remove(r.binder); - } + } + if (events.contains(PhoneStateListener.EVENT_EMERGENCY_NUMBER_LIST_CHANGED)) { + try { + r.callback.onEmergencyNumberListChanged(mEmergencyNumberList); + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE) != 0) { - try { - r.callback.onPhoneCapabilityChanged(mPhoneCapability); - } catch (RemoteException ex) { - remove(r.binder); - } + } + if (events.contains(PhoneStateListener.EVENT_PHONE_CAPABILITY_CHANGED)) { + try { + r.callback.onPhoneCapabilityChanged(mPhoneCapability); + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener - .LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE) != 0) { - try { - r.callback.onActiveDataSubIdChanged(mActiveDataSubId); - } catch (RemoteException ex) { - remove(r.binder); - } + } + if (events.contains( + PhoneStateListener.EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED)) { + try { + r.callback.onActiveDataSubIdChanged(mActiveDataSubId); + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED) != 0) { - try { - r.callback.onRadioPowerStateChanged(mRadioPowerState); - } catch (RemoteException ex) { - remove(r.binder); - } + } + if (events.contains(PhoneStateListener.EVENT_RADIO_POWER_STATE_CHANGED)) { + try { + r.callback.onRadioPowerStateChanged(mRadioPowerState); + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED) != 0) { - try { - r.callback.onSrvccStateChanged(mSrvccState[phoneId]); - } catch (RemoteException ex) { - remove(r.binder); - } + } + if (events.contains(PhoneStateListener.EVENT_SRVCC_STATE_CHANGED)) { + try { + r.callback.onSrvccStateChanged(mSrvccState[phoneId]); + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED) != 0) { - try { - r.callback.onCallAttributesChanged(mCallAttributes[phoneId]); - } catch (RemoteException ex) { - remove(r.binder); - } + } + if (events.contains(PhoneStateListener.EVENT_CALL_ATTRIBUTES_CHANGED)) { + try { + r.callback.onCallAttributesChanged(mCallAttributes[phoneId]); + } catch (RemoteException ex) { + remove(r.binder); } - if ((events & PhoneStateListener.LISTEN_BARRING_INFO) != 0) { - BarringInfo barringInfo = mBarringInfo.get(phoneId); - BarringInfo biNoLocation = barringInfo != null - ? barringInfo.createLocationInfoSanitizedCopy() : null; - if (VDBG) log("listen: call onBarringInfoChanged=" + barringInfo); - try { - r.callback.onBarringInfoChanged( - checkFineLocationAccess(r, Build.VERSION_CODES.BASE) - ? barringInfo : biNoLocation); - } catch (RemoteException ex) { - remove(r.binder); - } + } + if (events.contains(PhoneStateListener.EVENT_BARRING_INFO_CHANGED)) { + BarringInfo barringInfo = mBarringInfo.get(phoneId); + BarringInfo biNoLocation = barringInfo != null + ? barringInfo.createLocationInfoSanitizedCopy() : null; + if (VDBG) log("listen: call onBarringInfoChanged=" + barringInfo); + try { + r.callback.onBarringInfoChanged( + checkFineLocationAccess(r, Build.VERSION_CODES.BASE) + ? barringInfo : biNoLocation); + } catch (RemoteException ex) { + remove(r.binder); + } + } + if (events.contains( + PhoneStateListener.EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED)) { + try { + r.callback.onPhysicalChannelConfigChanged( + mPhysicalChannelConfigs); + } catch (RemoteException ex) { + remove(r.binder); + } + } + if (events.contains( + PhoneStateListener.EVENT_DATA_ENABLED_CHANGED)) { + try { + r.callback.onDataEnabledChanged(mIsDataEnabled, mDataEnabledReason); + } catch (RemoteException ex) { + remove(r.binder); } } } - } else { - if(DBG) log("listen: Unregister"); - remove(callback.asBinder()); } } @@ -1114,7 +1166,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { // If any of the system clients wants to always listen to signal strength, // we need to set it on. if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)) { + PhoneStateListener.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED)) { telephonyManager.createForSubscriptionId(subscriptionId) .setAlwaysReportSignalStrength(true); return; @@ -1215,7 +1267,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { // strength is removed from registry records, we need to check if // the signal strength decision needs to update on its slot. if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)) { + PhoneStateListener.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED)) { updateReportSignalStrengthDecision(r.subId); } return; @@ -1235,8 +1287,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { synchronized (mRecords) { for (Record r : mRecords) { - if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_CALL_STATE) && - (r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) { + if (r.matchPhoneStateListenerEvent(PhoneStateListener.EVENT_CALL_STATE_CHANGED) + && (r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) { try { // Ensure the listener has read call log permission; if they do not return // an empty phone number. @@ -1270,9 +1322,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mCallState[phoneId] = state; mCallIncomingNumber[phoneId] = incomingNumber; for (Record r : mRecords) { - if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_CALL_STATE) && - (r.subId == subId) && - (r.subId != SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) { + if (r.matchPhoneStateListenerEvent(PhoneStateListener.EVENT_CALL_STATE_CHANGED) + && (r.subId == subId) + && (r.subId != SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) { try { String incomingNumberOrEmpty = getCallIncomingNumber(r, phoneId); r.callback.onCallStateChanged(state, incomingNumberOrEmpty); @@ -1312,8 +1364,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { log("notifyServiceStateForSubscriber: r=" + r + " subId=" + subId + " phoneId=" + phoneId + " state=" + state); } - if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_SERVICE_STATE) && - idMatch(r.subId, subId, phoneId)) { + if (r.matchPhoneStateListenerEvent( + PhoneStateListener.EVENT_SERVICE_STATE_CHANGED) + && idMatch(r.subId, subId, phoneId)) { try { ServiceState stateToSend; @@ -1374,7 +1427,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { try { if ((activationType == SIM_ACTIVATION_TYPE_VOICE) && r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_VOICE_ACTIVATION_STATE) + PhoneStateListener.EVENT_VOICE_ACTIVATION_STATE_CHANGED) && idMatch(r.subId, subId, phoneId)) { if (DBG) { log("notifyVoiceActivationStateForPhoneId: callback.onVASC r=" + r @@ -1385,7 +1438,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } if ((activationType == SIM_ACTIVATION_TYPE_DATA) && r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_DATA_ACTIVATION_STATE) + PhoneStateListener.EVENT_DATA_ACTIVATION_STATE_CHANGED) && idMatch(r.subId, subId, phoneId)) { if (DBG) { log("notifyDataActivationStateForPhoneId: callback.onDASC r=" + r @@ -1424,9 +1477,11 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { log("notifySignalStrengthForPhoneId: r=" + r + " subId=" + subId + " phoneId=" + phoneId + " ss=" + signalStrength); } - if ((r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) + if ((r.matchPhoneStateListenerEvent( + PhoneStateListener.EVENT_SIGNAL_STRENGTHS_CHANGED) || r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)) + PhoneStateListener. + EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED)) && idMatch(r.subId, subId, phoneId)) { try { if (DBG) { @@ -1439,8 +1494,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mRemoveList.add(r.binder); } } - if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_SIGNAL_STRENGTH) && - idMatch(r.subId, subId, phoneId)) { + if (r.matchPhoneStateListenerEvent( + PhoneStateListener.EVENT_SIGNAL_STRENGTH_CHANGED) + && idMatch(r.subId, subId, phoneId)) { try { int gsmSignalStrength = signalStrength.getGsmSignalStrength(); int ss = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength); @@ -1486,8 +1542,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } for (Record r : mRecords) { if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE) && - idMatch(r.subId, subId, phoneId)) { + PhoneStateListener.EVENT_CARRIER_NETWORK_CHANGED) + && idMatch(r.subId, subId, phoneId)) { try { r.callback.onCarrierNetworkChange(active); } catch (RemoteException ex) { @@ -1517,9 +1573,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { if (validatePhoneId(phoneId)) { mCellInfo.set(phoneId, cellInfo); for (Record r : mRecords) { - if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO) && - idMatch(r.subId, subId, phoneId) && - (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE) + if (validateEventAndUserLocked( + r, PhoneStateListener.EVENT_CELL_INFO_CHANGED) + && idMatch(r.subId, subId, phoneId) + && (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE) && checkFineLocationAccess(r, Build.VERSION_CODES.Q))) { try { if (DBG_LOC) { @@ -1551,8 +1608,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mMessageWaiting[phoneId] = mwi; for (Record r : mRecords) { if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) && - idMatch(r.subId, subId, phoneId)) { + PhoneStateListener.EVENT_MESSAGE_WAITING_INDICATOR_CHANGED) + && idMatch(r.subId, subId, phoneId)) { try { r.callback.onMessageWaitingIndicatorChanged(mwi); } catch (RemoteException ex) { @@ -1578,8 +1635,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mUserMobileDataState[phoneId] = state; for (Record r : mRecords) { if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_USER_MOBILE_DATA_STATE) && - idMatch(r.subId, subId, phoneId)) { + PhoneStateListener.EVENT_USER_MOBILE_DATA_STATE_CHANGED) + && idMatch(r.subId, subId, phoneId)) { try { r.callback.onUserMobileDataStateChanged(state); } catch (RemoteException ex) { @@ -1617,7 +1674,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mTelephonyDisplayInfos[phoneId] = telephonyDisplayInfo; for (Record r : mRecords) { if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED) + PhoneStateListener.EVENT_DISPLAY_INFO_CHANGED) && idMatchWithoutDefaultPhoneCheck(r.subId, subId)) { try { r.callback.onDisplayInfoChanged(telephonyDisplayInfo); @@ -1649,8 +1706,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mCallForwarding[phoneId] = cfi; for (Record r : mRecords) { if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) && - idMatch(r.subId, subId, phoneId)) { + PhoneStateListener.EVENT_CALL_FORWARDING_INDICATOR_CHANGED) + && idMatch(r.subId, subId, phoneId)) { try { r.callback.onCallForwardingIndicatorChanged(cfi); } catch (RemoteException ex) { @@ -1677,8 +1734,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mDataActivity[phoneId] = state; for (Record r : mRecords) { // Notify by correct subId. - if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_DATA_ACTIVITY) && - idMatch(r.subId, subId, phoneId)) { + if (r.matchPhoneStateListenerEvent( + PhoneStateListener.EVENT_DATA_ACTIVITY_CHANGED) + && idMatch(r.subId, subId, phoneId)) { try { r.callback.onDataActivity(state); } catch (RemoteException ex) { @@ -1725,7 +1783,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mLocalLog.log(str); for (Record r : mRecords) { if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) + PhoneStateListener.EVENT_DATA_CONNECTION_STATE_CHANGED) && idMatch(r.subId, subId, phoneId)) { try { if (DBG) { @@ -1747,12 +1805,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { preciseState.getApnSetting()); PreciseDataConnectionState oldState = mPreciseDataConnectionStates.get(phoneId) .remove(key); - log("Jack: oldState=" + oldState); - log("Jack: newState=" + preciseState); if (!Objects.equals(oldState, preciseState)) { for (Record r : mRecords) { if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) + PhoneStateListener.EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED) && idMatch(r.subId, subId, phoneId)) { try { r.callback.onPreciseDataConnectionStateChanged(preciseState); @@ -1797,9 +1853,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { if (validatePhoneId(phoneId) && !Objects.equals(cellIdentity, mCellIdentity[phoneId])) { mCellIdentity[phoneId] = cellIdentity; for (Record r : mRecords) { - if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION) && - idMatch(r.subId, subId, phoneId) && - (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE) + if (validateEventAndUserLocked( + r, PhoneStateListener.EVENT_CELL_LOCATION_CHANGED) + && idMatch(r.subId, subId, phoneId) + && (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE) && checkFineLocationAccess(r, Build.VERSION_CODES.Q))) { try { if (DBG_LOC) { @@ -1850,7 +1907,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } for (Record r : mRecords) { - if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_PRECISE_CALL_STATE) + if (r.matchPhoneStateListenerEvent( + PhoneStateListener.EVENT_PRECISE_CALL_STATE_CHANGED) && idMatch(r.subId, subId, phoneId)) { try { r.callback.onPreciseCallStateChanged(mPreciseCallState[phoneId]); @@ -1859,7 +1917,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } if (notifyCallAttributes && r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED) + PhoneStateListener.EVENT_CALL_ATTRIBUTES_CHANGED) && idMatch(r.subId, subId, phoneId)) { try { r.callback.onCallAttributesChanged(mCallAttributes[phoneId]); @@ -1908,7 +1966,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mImsReasonInfo.set(phoneId, imsReasonInfo); for (Record r : mRecords) { if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES) + PhoneStateListener.EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED) && idMatch(r.subId, subId, phoneId)) { try { if (DBG_LOC) { @@ -1940,8 +1998,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mSrvccState[phoneId] = state; for (Record r : mRecords) { if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED) && - idMatch(r.subId, subId, phoneId)) { + PhoneStateListener.EVENT_SRVCC_STATE_CHANGED) + && idMatch(r.subId, subId, phoneId)) { try { if (DBG_LOC) { log("notifySrvccStateChanged: mSrvccState=" + state + " r=" + r); @@ -1969,7 +2027,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { log("notifyOemHookRawEventForSubscriber: r=" + r + " subId=" + subId); } if ((r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT)) + PhoneStateListener.EVENT_OEM_HOOK_RAW)) && idMatch(r.subId, subId, phoneId)) { try { r.callback.onOemHookRawEvent(rawData); @@ -1997,7 +2055,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { for (Record r : mRecords) { if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE)) { + PhoneStateListener.EVENT_PHONE_CAPABILITY_CHANGED)) { try { r.callback.onPhoneCapabilityChanged(capability); } catch (RemoteException ex) { @@ -2022,7 +2080,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { synchronized (mRecords) { for (Record r : mRecords) { if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE)) { + PhoneStateListener.EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED)) { try { r.callback.onActiveDataSubIdChanged(activeDataSubId); } catch (RemoteException ex) { @@ -2049,7 +2107,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { for (Record r : mRecords) { if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED) + PhoneStateListener.EVENT_RADIO_POWER_STATE_CHANGED) && idMatch(r.subId, subId, phoneId)) { try { r.callback.onRadioPowerStateChanged(state); @@ -2078,7 +2136,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { for (Record r : mRecords) { if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST) + PhoneStateListener.EVENT_EMERGENCY_NUMBER_LIST_CHANGED) && idMatch(r.subId, subId, phoneId)) { try { r.callback.onEmergencyNumberListChanged(mEmergencyNumberList); @@ -2110,7 +2168,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { for (Record r : mRecords) { // Send to all listeners regardless of subscription if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL)) { + PhoneStateListener.EVENT_OUTGOING_EMERGENCY_CALL)) { try { r.callback.onOutgoingEmergencyCall(emergencyNumber, subId); } catch (RemoteException ex) { @@ -2134,7 +2192,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { for (Record r : mRecords) { // Send to all listeners regardless of subscription if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_SMS)) { + PhoneStateListener.EVENT_OUTGOING_EMERGENCY_SMS)) { try { r.callback.onOutgoingEmergencySms(emergencyNumber, subId); } catch (RemoteException ex) { @@ -2164,7 +2222,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { for (Record r : mRecords) { if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED) + PhoneStateListener.EVENT_CALL_ATTRIBUTES_CHANGED) && idMatch(r.subId, subId, phoneId)) { try { r.callback.onCallAttributesChanged(mCallAttributes[phoneId]); @@ -2195,7 +2253,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { if (validatePhoneId(phoneId)) { for (Record r : mRecords) { if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_REGISTRATION_FAILURE) + PhoneStateListener.EVENT_REGISTRATION_FAILURE) && idMatch(r.subId, subId, phoneId)) { try { r.callback.onRegistrationFailed( @@ -2238,7 +2296,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { if (VDBG) log("listen: call onBarringInfoChanged=" + barringInfo); for (Record r : mRecords) { if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_BARRING_INFO) + PhoneStateListener.EVENT_BARRING_INFO_CHANGED) && idMatch(r.subId, subId, phoneId)) { try { if (DBG_LOC) { @@ -2258,6 +2316,81 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } + /** + * Send a notification to registrants that the configs of physical channel has changed for + * a particular subscription. + * + * @param subId the subId + * @param configs a list of {@link PhysicalChannelConfig}, the configs of physical channel. + */ + public void notifyPhysicalChannelConfigForSubscriber( + int subId, List<PhysicalChannelConfig> configs) { + if (!checkNotifyPermission("notifyPhysicalChannelConfig()")) { + return; + } + + if (VDBG) { + log("notifyPhysicalChannelConfig: subId=" + subId + " configs=" + configs); + } + + synchronized (mRecords) { + int phoneId = SubscriptionManager.getPhoneId(subId); + if (validatePhoneId(phoneId)) { + mPhysicalChannelConfigs.set(phoneId, configs.get(phoneId)); + for (Record r : mRecords) { + if (r.matchPhoneStateListenerEvent( + PhoneStateListener.EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED) + && idMatch(r.subId, subId, phoneId)) { + try { + if (DBG_LOC) { + log("notifyPhysicalChannelConfig: " + + "mPhysicalChannelConfigs=" + + configs + " r=" + r); + } + r.callback.onPhysicalChannelConfigChanged(configs); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + } + handleRemoveListLocked(); + } + } + + /** + * Notify that the data enabled has changed. + * + * @param enabled True if data is enabled, otherwise disabled. + * @param reason Reason for data enabled/disabled. See {@code DATA_*} in + * {@link TelephonyManager}. + */ + public void notifyDataEnabled(boolean enabled, + @TelephonyManager.DataEnabledReason int reason) { + if (!checkNotifyPermission("notifyDataEnabled()")) { + return; + } + + if (VDBG) { + log("notifyDataEnabled: enabled=" + enabled + " reason=" + reason); + } + + mIsDataEnabled = enabled; + mDataEnabledReason = reason; + synchronized (mRecords) { + for (Record r : mRecords) { + if (r.matchPhoneStateListenerEvent( + PhoneStateListener.EVENT_DATA_ENABLED_CHANGED)) { + try { + r.callback.onDataEnabledChanged(enabled, reason); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + handleRemoveListLocked(); + } + } @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { @@ -2310,6 +2443,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { pw.println("mEmergencyNumberList=" + mEmergencyNumberList); pw.println("mDefaultPhoneId=" + mDefaultPhoneId); pw.println("mDefaultSubId=" + mDefaultSubId); + pw.println("mPhysicalChannelConfigs=" + mPhysicalChannelConfigs); + pw.println("mIsDataEnabled=" + mIsDataEnabled); + pw.println("mDataEnabledReason=" + mDataEnabledReason); pw.decreaseIndent(); @@ -2538,22 +2674,29 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { == PackageManager.PERMISSION_GRANTED; } - private boolean checkListenerPermission(int events, int subId, String callingPackage, + private boolean checkListenerPermission(Set<Integer> events, int subId, String callingPackage, @Nullable String callingFeatureId, String message) { LocationAccessPolicy.LocationPermissionQuery.Builder locationQueryBuilder = new LocationAccessPolicy.LocationPermissionQuery.Builder() - .setCallingPackage(callingPackage) - .setMethod(message + " events: " + events) - .setCallingPid(Binder.getCallingPid()) - .setCallingUid(Binder.getCallingUid()); + .setCallingPackage(callingPackage) + .setMethod(message + " events: " + events) + .setCallingPid(Binder.getCallingPid()) + .setCallingUid(Binder.getCallingUid()); + + boolean shouldCheckLocationPermissions = false; - if ((events & ENFORCE_LOCATION_PERMISSION_MASK) != 0) { + if (isLocationPermissionRequired(events)) { // Everything that requires fine location started in Q. So far... locationQueryBuilder.setMinSdkVersionForFine(Build.VERSION_CODES.Q); // If we're enforcing fine starting in Q, we also want to enforce coarse even for // older SDK versions. locationQueryBuilder.setMinSdkVersionForCoarse(0); + shouldCheckLocationPermissions = true; + } + + boolean isPermissionCheckSuccessful = true; + if (shouldCheckLocationPermissions) { LocationAccessPolicy.LocationPermissionResult result = LocationAccessPolicy.checkLocationPermission( mContext, locationQueryBuilder.build()); @@ -2562,18 +2705,18 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { throw new SecurityException("Unable to listen for events " + events + " due to " + "insufficient location permissions."); case DENIED_SOFT: - return false; + isPermissionCheckSuccessful = false; } } - if ((events & ENFORCE_PHONE_STATE_PERMISSION_MASK) != 0) { + if (isPhoneStatePermissionRequired(events)) { if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState( mContext, subId, callingPackage, callingFeatureId, message)) { - return false; + isPermissionCheckSuccessful = false; } } - if ((events & ENFORCE_PRECISE_PHONE_STATE_PERMISSION_MASK) != 0) { + if (isPrecisePhoneStatePermissionRequired(events)) { // check if calling app has either permission READ_PRECISE_PHONE_STATE // or with carrier privileges try { @@ -2584,47 +2727,46 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - if ((events & READ_ACTIVE_EMERGENCY_SESSION_PERMISSION_MASK) != 0) { + if (isActiveEmergencySessionPermissionRequired(events)) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION, null); } - if ((events & PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) != 0) { + if ((events.contains(PhoneStateListener.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED))) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH, null); } - if ((events & READ_PRIVILEGED_PHONE_STATE_PERMISSION_MASK) != 0) { + if (isPrivilegedPhoneStatePermissionRequired(events)) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null); } - - return true; + return isPermissionCheckSuccessful; } private void handleRemoveListLocked() { int size = mRemoveList.size(); if (VDBG) log("handleRemoveListLocked: mRemoveList.size()=" + size); if (size > 0) { - for (IBinder b: mRemoveList) { + for (IBinder b : mRemoveList) { remove(b); } mRemoveList.clear(); } } - private boolean validateEventsAndUserLocked(Record r, int events) { + private boolean validateEventAndUserLocked(Record r, int event) { int foregroundUser; long callingIdentity = Binder.clearCallingIdentity(); boolean valid = false; try { foregroundUser = ActivityManager.getCurrentUser(); valid = UserHandle.getUserId(r.callerUid) == foregroundUser - && r.matchPhoneStateListenerEvent(events); + && r.matchPhoneStateListenerEvent(event); if (DBG | DBG_LOC) { - log("validateEventsAndUserLocked: valid=" + valid + log("validateEventAndUserLocked: valid=" + valid + " r.callerUid=" + r.callerUid + " foregroundUser=" + foregroundUser - + " r.events=" + r.events + " events=" + events); + + " r.eventList=" + r.eventList + " event=" + event); } } finally { Binder.restoreCallingIdentity(callingIdentity); @@ -2677,6 +2819,11 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } + /** + * Note -- this method should only be used at the site of a permission check if you need to + * explicitly allow apps below a certain SDK level access regardless of location permissions. + * If you don't need app compat logic, use {@link #checkFineLocationAccess(Record)}. + */ private boolean checkFineLocationAccess(Record r, int minSdk) { LocationAccessPolicy.LocationPermissionQuery query = new LocationAccessPolicy.LocationPermissionQuery.Builder() @@ -2695,6 +2842,11 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { }); } + /** + * Note -- this method should only be used at the site of a permission check if you need to + * explicitly allow apps below a certain SDK level access regardless of location permissions. + * If you don't need app compat logic, use {@link #checkCoarseLocationAccess(Record)}. + */ private boolean checkCoarseLocationAccess(Record r, int minSdk) { LocationAccessPolicy.LocationPermissionQuery query = new LocationAccessPolicy.LocationPermissionQuery.Builder() @@ -2714,9 +2866,14 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } private void checkPossibleMissNotify(Record r, int phoneId) { - int events = r.events; + Set<Integer> events = r.eventList; + + if (events == null || events.isEmpty()) { + log("checkPossibleMissNotify: events = null."); + return; + } - if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) { + if ((events.contains(PhoneStateListener.EVENT_SERVICE_STATE_CHANGED))) { try { if (VDBG) log("checkPossibleMissNotify: onServiceStateChanged state=" + mServiceState[phoneId]); @@ -2735,8 +2892,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0 - || (events & PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) != 0) { + if (events.contains(PhoneStateListener.EVENT_SIGNAL_STRENGTHS_CHANGED) + || events.contains( + PhoneStateListener.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED)) { try { if (mSignalStrength[phoneId] != null) { SignalStrength signalStrength = mSignalStrength[phoneId]; @@ -2751,7 +2909,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) { + if (events.contains(PhoneStateListener.EVENT_SIGNAL_STRENGTH_CHANGED)) { try { if (mSignalStrength[phoneId] != null) { int gsmSignalStrength = mSignalStrength[phoneId] @@ -2768,7 +2926,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) { + if (validateEventAndUserLocked(r, PhoneStateListener.EVENT_CELL_INFO_CHANGED)) { try { if (DBG_LOC) { log("checkPossibleMissNotify: onCellInfoChanged[" + phoneId + "] = " @@ -2783,7 +2941,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - if ((events & PhoneStateListener.LISTEN_USER_MOBILE_DATA_STATE) != 0) { + if (events.contains(PhoneStateListener.EVENT_USER_MOBILE_DATA_STATE_CHANGED)) { try { if (VDBG) { log("checkPossibleMissNotify: onUserMobileDataStateChanged phoneId=" @@ -2795,7 +2953,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - if ((events & PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED) != 0) { + if (events.contains(PhoneStateListener.EVENT_DISPLAY_INFO_CHANGED)) { try { if (VDBG) { log("checkPossibleMissNotify: onDisplayInfoChanged phoneId=" @@ -2809,7 +2967,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) { + if (events.contains(PhoneStateListener.EVENT_MESSAGE_WAITING_INDICATOR_CHANGED)) { try { if (VDBG) { log("checkPossibleMissNotify: onMessageWaitingIndicatorChanged phoneId=" @@ -2822,7 +2980,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - if ((events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) { + if (events.contains(PhoneStateListener.EVENT_CALL_FORWARDING_INDICATOR_CHANGED)) { try { if (VDBG) { log("checkPossibleMissNotify: onCallForwardingIndicatorChanged phoneId=" @@ -2835,7 +2993,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) { + if (validateEventAndUserLocked(r, PhoneStateListener.EVENT_CELL_LOCATION_CHANGED)) { try { if (DBG_LOC) { log("checkPossibleMissNotify: onCellLocationChanged mCellIdentity = " @@ -2851,7 +3009,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) { + if (events.contains(PhoneStateListener.EVENT_DATA_CONNECTION_STATE_CHANGED)) { try { if (DBG) { log("checkPossibleMissNotify: onDataConnectionStateChanged(mDataConnectionState" diff --git a/services/core/java/com/android/server/connectivity/PacProxyInstaller.java b/services/core/java/com/android/server/connectivity/PacProxyInstaller.java index aadaf4d9584f..5dc8c1a00eaf 100644 --- a/services/core/java/com/android/server/connectivity/PacProxyInstaller.java +++ b/services/core/java/com/android/server/connectivity/PacProxyInstaller.java @@ -16,6 +16,7 @@ package com.android.server.connectivity; +import android.annotation.NonNull; import android.annotation.WorkerThread; import android.app.AlarmManager; import android.app.PendingIntent; @@ -71,10 +72,6 @@ public class PacProxyInstaller { private static final int DELAY_LONG = 4; private static final long MAX_PAC_SIZE = 20 * 1000 * 1000; - // Return values for #setCurrentProxyScriptUrl - public static final boolean DONT_SEND_BROADCAST = false; - public static final boolean DO_SEND_BROADCAST = true; - private String mCurrentPac; @GuardedBy("mProxyLock") private volatile Uri mPacUrl = Uri.EMPTY; @@ -93,7 +90,7 @@ public class PacProxyInstaller { private volatile boolean mHasSentBroadcast; private volatile boolean mHasDownloaded; - private Handler mConnectivityHandler; + private final Handler mConnectivityHandler; private final int mProxyMessage; /** @@ -102,6 +99,13 @@ public class PacProxyInstaller { private final Object mProxyLock = new Object(); /** + * Lock ensuring consistency between the values of mHasSentBroadcast, mHasDownloaded, the + * last URL and port, and the broadcast message being sent with the correct arguments. + * TODO : this should probably protect all instances of these variables + */ + private final Object mBroadcastStateLock = new Object(); + + /** * Runnable to download PAC script. * The behavior relies on the assumption it always runs on mNetThread to guarantee that the * latest data fetched from mPacUrl is stored in mProxyService. @@ -146,7 +150,7 @@ public class PacProxyInstaller { } } - public PacProxyInstaller(Context context, Handler handler, int proxyMessage) { + public PacProxyInstaller(@NonNull Context context, @NonNull Handler handler, int proxyMessage) { mContext = context; mLastPort = -1; final HandlerThread netThread = new HandlerThread("android.pacproxyinstaller", @@ -176,31 +180,27 @@ public class PacProxyInstaller { * PacProxyInstaller will trigger a new broadcast when it is ready. * * @param proxy Proxy information that is about to be broadcast. - * @return Returns whether the broadcast should be sent : either DO_ or DONT_SEND_BROADCAST */ - public synchronized boolean setCurrentProxyScriptUrl(ProxyInfo proxy) { - if (!Uri.EMPTY.equals(proxy.getPacFileUrl())) { - if (proxy.getPacFileUrl().equals(mPacUrl) && (proxy.getPort() > 0)) { - // Allow to send broadcast, nothing to do. - return DO_SEND_BROADCAST; - } - mPacUrl = proxy.getPacFileUrl(); - mCurrentDelay = DELAY_1; - mHasSentBroadcast = false; - mHasDownloaded = false; - getAlarmManager().cancel(mPacRefreshIntent); - bind(); - return DONT_SEND_BROADCAST; - } else { - getAlarmManager().cancel(mPacRefreshIntent); - synchronized (mProxyLock) { - mPacUrl = Uri.EMPTY; - mCurrentPac = null; - if (mProxyService != null) { - unbind(); + public void setCurrentProxyScriptUrl(@NonNull ProxyInfo proxy) { + synchronized (mBroadcastStateLock) { + if (!Uri.EMPTY.equals(proxy.getPacFileUrl())) { + if (proxy.getPacFileUrl().equals(mPacUrl) && (proxy.getPort() > 0)) return; + mPacUrl = proxy.getPacFileUrl(); + mCurrentDelay = DELAY_1; + mHasSentBroadcast = false; + mHasDownloaded = false; + getAlarmManager().cancel(mPacRefreshIntent); + bind(); + } else { + getAlarmManager().cancel(mPacRefreshIntent); + synchronized (mProxyLock) { + mPacUrl = Uri.EMPTY; + mCurrentPac = null; + if (mProxyService != null) { + unbind(); + } } } - return DO_SEND_BROADCAST; } } @@ -275,6 +275,7 @@ public class PacProxyInstaller { getAlarmManager().set(AlarmManager.ELAPSED_REALTIME, timeTillTrigger, mPacRefreshIntent); } + @GuardedBy("mProxyLock") private void setCurrentProxyScript(String script) { if (mProxyService == null) { Log.e(TAG, "setCurrentProxyScript: no proxy service"); @@ -347,6 +348,9 @@ public class PacProxyInstaller { public void setProxyPort(int port) { if (mLastPort != -1) { // Always need to send if port changed + // TODO: Here lacks synchronization because this write cannot + // guarantee that it's visible from sendProxyIfNeeded() when + // it's called by a Runnable which is post by mNetThread. mHasSentBroadcast = false; } mLastPort = port; @@ -386,13 +390,15 @@ public class PacProxyInstaller { mConnectivityHandler.sendMessage(mConnectivityHandler.obtainMessage(mProxyMessage, proxy)); } - private synchronized void sendProxyIfNeeded() { - if (!mHasDownloaded || (mLastPort == -1)) { - return; - } - if (!mHasSentBroadcast) { - sendPacBroadcast(ProxyInfo.buildPacProxy(mPacUrl, mLastPort)); - mHasSentBroadcast = true; + private void sendProxyIfNeeded() { + synchronized (mBroadcastStateLock) { + if (!mHasDownloaded || (mLastPort == -1)) { + return; + } + if (!mHasSentBroadcast) { + sendPacBroadcast(ProxyInfo.buildPacProxy(mPacUrl, mLastPort)); + mHasSentBroadcast = true; + } } } } diff --git a/services/core/java/com/android/server/connectivity/ProxyTracker.java b/services/core/java/com/android/server/connectivity/ProxyTracker.java index d83ff837d9be..b618d2b99a63 100644 --- a/services/core/java/com/android/server/connectivity/ProxyTracker.java +++ b/services/core/java/com/android/server/connectivity/ProxyTracker.java @@ -226,9 +226,9 @@ public class ProxyTracker { final ProxyInfo defaultProxy = getDefaultProxy(); final ProxyInfo proxyInfo = null != defaultProxy ? defaultProxy : ProxyInfo.buildDirectProxy("", 0, Collections.emptyList()); + mPacProxyInstaller.setCurrentProxyScriptUrl(proxyInfo); - if (mPacProxyInstaller.setCurrentProxyScriptUrl(proxyInfo) - == PacProxyInstaller.DONT_SEND_BROADCAST) { + if (!shouldSendBroadcast(proxyInfo)) { return; } if (DBG) Log.d(TAG, "sending Proxy Broadcast for " + proxyInfo); @@ -244,6 +244,13 @@ public class ProxyTracker { } } + private boolean shouldSendBroadcast(ProxyInfo proxy) { + if (Uri.EMPTY.equals(proxy.getPacFileUrl())) return false; + if (proxy.getPacFileUrl().equals(proxy.getPacFileUrl()) + && (proxy.getPort() > 0)) return true; + return true; + } + /** * Sets the global proxy in memory. Also writes the values to the global settings of the device. * diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java index 289290bab4dc..fbec91576ca1 100644 --- a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java +++ b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java @@ -224,6 +224,10 @@ class RebootEscrowManager { for (UserInfo user : rebootEscrowUsers) { allUsersUnlocked &= restoreRebootEscrowForUser(user.id, escrowKey, kk); } + + // Clear the old key in keystore. A new key will be generated by new RoR requests. + mKeyStoreManager.clearKeyStoreEncryptionKey(); + onEscrowRestoreComplete(allUsersUnlocked); } @@ -273,9 +277,6 @@ class RebootEscrowManager { } catch (IOException e) { Slog.w(TAG, "Could not load reboot escrow data for user " + userId, e); return false; - } finally { - // Clear the old key in keystore. A new key will be generated by new RoR requests. - mKeyStoreManager.clearKeyStoreEncryptionKey(); } } diff --git a/services/core/java/com/android/server/tv/TvInputHal.java b/services/core/java/com/android/server/tv/TvInputHal.java index 42f12eb23d39..07725038255e 100644 --- a/services/core/java/com/android/server/tv/TvInputHal.java +++ b/services/core/java/com/android/server/tv/TvInputHal.java @@ -51,7 +51,8 @@ final class TvInputHal implements Handler.Callback { public interface Callback { void onDeviceAvailable(TvInputHardwareInfo info, TvStreamConfig[] configs); void onDeviceUnavailable(int deviceId); - void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs); + void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs, + int cableConnectionStatus); void onFirstFrameCaptured(int deviceId, int streamId); } @@ -142,8 +143,9 @@ final class TvInputHal implements Handler.Callback { mHandler.obtainMessage(EVENT_DEVICE_UNAVAILABLE, deviceId, 0).sendToTarget(); } - private void streamConfigsChangedFromNative(int deviceId) { - mHandler.obtainMessage(EVENT_STREAM_CONFIGURATION_CHANGED, deviceId, 0).sendToTarget(); + private void streamConfigsChangedFromNative(int deviceId, int cableConnectionStatus) { + mHandler.obtainMessage(EVENT_STREAM_CONFIGURATION_CHANGED, deviceId, + cableConnectionStatus).sendToTarget(); } private void firstFrameCapturedFromNative(int deviceId, int streamId) { @@ -184,6 +186,7 @@ final class TvInputHal implements Handler.Callback { case EVENT_STREAM_CONFIGURATION_CHANGED: { TvStreamConfig[] configs; int deviceId = msg.arg1; + int cableConnectionStatus = msg.arg2; synchronized (mLock) { if (DEBUG) { Slog.d(TAG, "EVENT_STREAM_CONFIGURATION_CHANGED: deviceId = " + deviceId); @@ -191,7 +194,7 @@ final class TvInputHal implements Handler.Callback { retrieveStreamConfigsLocked(deviceId); configs = mStreamConfigs.get(deviceId); } - mCallback.onStreamConfigurationChanged(deviceId, configs); + mCallback.onStreamConfigurationChanged(deviceId, configs, cableConnectionStatus); break; } diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java index 2314afc787c3..3dfb99e5c0fc 100755 --- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java +++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java @@ -156,6 +156,7 @@ class TvInputHardwareManager implements TvInputHal.Callback { synchronized (mLock) { Connection connection = new Connection(info); connection.updateConfigsLocked(configs); + connection.updateCableConnectionStatusLocked(info.getCableConnectionStatus()); mConnections.put(info.getDeviceId(), connection); buildHardwareListLocked(); mHandler.obtainMessage( @@ -202,7 +203,8 @@ class TvInputHardwareManager implements TvInputHal.Callback { } @Override - public void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs) { + public void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs, + int cableConnectionStatus) { synchronized (mLock) { Connection connection = mConnections.get(deviceId); if (connection == null) { @@ -211,12 +213,22 @@ class TvInputHardwareManager implements TvInputHal.Callback { return; } int previousConfigsLength = connection.getConfigsLengthLocked(); + int previousCableConnectionStatus = connection.getInputStateLocked(); connection.updateConfigsLocked(configs); String inputId = mHardwareInputIdMap.get(deviceId); - if (inputId != null - && (previousConfigsLength == 0) != (connection.getConfigsLengthLocked() == 0)) { - mHandler.obtainMessage(ListenerHandler.STATE_CHANGED, - connection.getInputStateLocked(), 0, inputId).sendToTarget(); + if (inputId != null) { + if (connection.updateCableConnectionStatusLocked(cableConnectionStatus)) { + if (previousCableConnectionStatus != connection.getInputStateLocked()) { + mHandler.obtainMessage(ListenerHandler.STATE_CHANGED, + connection.getInputStateLocked(), 0, inputId).sendToTarget(); + } + } else { + if ((previousConfigsLength == 0) + != (connection.getConfigsLengthLocked() == 0)) { + mHandler.obtainMessage(ListenerHandler.STATE_CHANGED, + connection.getInputStateLocked(), 0, inputId).sendToTarget(); + } + } } ITvInputHardwareCallback callback = connection.getCallbackLocked(); if (callback != null) { @@ -624,7 +636,7 @@ class TvInputHardwareManager implements TvInputHal.Callback { } private class Connection implements IBinder.DeathRecipient { - private final TvInputHardwareInfo mHardwareInfo; + private TvInputHardwareInfo mHardwareInfo; private TvInputInfo mInfo; private TvInputHardwareImpl mHardware = null; private ITvInputHardwareCallback mCallback; @@ -633,6 +645,7 @@ class TvInputHardwareManager implements TvInputHal.Callback { private Integer mResolvedUserId = null; private Runnable mOnFirstFrameCaptured; private ResourceClientProfile mResourceClientProfile = null; + private boolean mIsCableConnectionStatusUpdated = false; public Connection(TvInputHardwareInfo hardwareInfo) { mHardwareInfo = hardwareInfo; @@ -735,6 +748,17 @@ class TvInputHardwareManager implements TvInputHal.Callback { + " }"; } + public boolean updateCableConnectionStatusLocked(int cableConnectionStatus) { + // Update connection status only if it's not default value + if (cableConnectionStatus != TvInputHardwareInfo.CABLE_CONNECTION_STATUS_UNKNOWN + || mIsCableConnectionStatusUpdated) { + mIsCableConnectionStatusUpdated = true; + mHardwareInfo = mHardwareInfo.toBuilder() + .cableConnectionStatus(cableConnectionStatus).build(); + } + return mIsCableConnectionStatusUpdated; + } + private int getConfigsLengthLocked() { return mConfigs == null ? 0 : mConfigs.length; } @@ -742,7 +766,9 @@ class TvInputHardwareManager implements TvInputHal.Callback { private int getInputStateLocked() { int configsLength = getConfigsLengthLocked(); if (configsLength > 0) { - return INPUT_STATE_CONNECTED; + if (!mIsCableConnectionStatusUpdated) { + return INPUT_STATE_CONNECTED; + } } switch (mHardwareInfo.getCableConnectionStatus()) { case TvInputHardwareInfo.CABLE_CONNECTION_STATUS_CONNECTED: diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index 6cd02581ee67..d858ae41cee8 100755 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -20,6 +20,7 @@ import static android.media.AudioManager.DEVICE_NONE; import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED; import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED_STANDBY; +import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.content.BroadcastReceiver; @@ -1728,6 +1729,46 @@ public final class TvInputManagerService extends SystemService { } @Override + public void pauseRecording(IBinder sessionToken, @NonNull Bundle params, int userId) { + final int callingUid = Binder.getCallingUid(); + final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, + userId, "pauseRecording"); + final long identity = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + try { + getSessionLocked(sessionToken, callingUid, resolvedUserId) + .pauseRecording(params); + } catch (RemoteException | SessionNotFoundException e) { + Slog.e(TAG, "error in pauseRecording", e); + } + } + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public void resumeRecording(IBinder sessionToken, @NonNull Bundle params, int userId) { + final int callingUid = Binder.getCallingUid(); + final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, + userId, "resumeRecording"); + final long identity = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + try { + getSessionLocked(sessionToken, callingUid, resolvedUserId) + .resumeRecording(params); + } catch (RemoteException | SessionNotFoundException e) { + Slog.e(TAG, "error in resumeRecording", e); + } + } + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override public List<TvInputHardwareInfo> getHardwareList() throws RemoteException { if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) != PackageManager.PERMISSION_GRANTED) { diff --git a/services/core/jni/com_android_server_tv_TvInputHal.cpp b/services/core/jni/com_android_server_tv_TvInputHal.cpp index 4e1a23416330..a5311f33eb36 100644 --- a/services/core/jni/com_android_server_tv_TvInputHal.cpp +++ b/services/core/jni/com_android_server_tv_TvInputHal.cpp @@ -261,7 +261,7 @@ public: void onDeviceAvailable(const TvInputDeviceInfo& info); void onDeviceUnavailable(int deviceId); - void onStreamConfigurationsChanged(int deviceId); + void onStreamConfigurationsChanged(int deviceId, int cableConnectionStatus); void onCaptured(int deviceId, int streamId, uint32_t seq, bool succeeded); private: @@ -519,7 +519,7 @@ void JTvInputHal::onDeviceUnavailable(int deviceId) { deviceId); } -void JTvInputHal::onStreamConfigurationsChanged(int deviceId) { +void JTvInputHal::onStreamConfigurationsChanged(int deviceId, int cableConnectionStatus) { { Mutex::Autolock autoLock(&mLock); KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId); @@ -529,10 +529,8 @@ void JTvInputHal::onStreamConfigurationsChanged(int deviceId) { connections.clear(); } JNIEnv* env = AndroidRuntime::getJNIEnv(); - env->CallVoidMethod( - mThiz, - gTvInputHalClassInfo.streamConfigsChanged, - deviceId); + env->CallVoidMethod(mThiz, gTvInputHalClassInfo.streamConfigsChanged, deviceId, + cableConnectionStatus); } void JTvInputHal::onCaptured(int deviceId, int streamId, uint32_t seq, bool succeeded) { @@ -572,7 +570,8 @@ void JTvInputHal::NotifyHandler::handleMessage(const Message& message) { mHal->onDeviceUnavailable(mEvent.deviceInfo.deviceId); } break; case TvInputEventType::STREAM_CONFIGURATIONS_CHANGED: { - mHal->onStreamConfigurationsChanged(mEvent.deviceInfo.deviceId); + int cableConnectionStatus = static_cast<int>(mEvent.deviceInfo.cableConnectionStatus); + mHal->onStreamConfigurationsChanged(mEvent.deviceInfo.deviceId, cableConnectionStatus); } break; default: ALOGE("Unrecognizable event"); @@ -688,9 +687,8 @@ int register_android_server_tv_TvInputHal(JNIEnv* env) { "deviceAvailableFromNative", "(Landroid/media/tv/TvInputHardwareInfo;)V"); GET_METHOD_ID( gTvInputHalClassInfo.deviceUnavailable, clazz, "deviceUnavailableFromNative", "(I)V"); - GET_METHOD_ID( - gTvInputHalClassInfo.streamConfigsChanged, clazz, - "streamConfigsChangedFromNative", "(I)V"); + GET_METHOD_ID(gTvInputHalClassInfo.streamConfigsChanged, clazz, + "streamConfigsChangedFromNative", "(II)V"); GET_METHOD_ID( gTvInputHalClassInfo.firstFrameCaptured, clazz, "firstFrameCapturedFromNative", "(II)V"); diff --git a/services/searchui/OWNERS b/services/searchui/OWNERS new file mode 100644 index 000000000000..92835c2b0626 --- /dev/null +++ b/services/searchui/OWNERS @@ -0,0 +1,2 @@ +hyunyoungs@google.com +sfufa@google.com diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index 724a9e477b95..e55720c6dc7e 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -109,6 +109,20 @@ import java.util.concurrent.ConcurrentHashMap; */ public abstract class Connection extends Conferenceable { + /**@hide*/ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "STATE_", value = { + STATE_INITIALIZING, + STATE_NEW, + STATE_RINGING, + STATE_DIALING, + STATE_ACTIVE, + STATE_HOLDING, + STATE_DISCONNECTED, + STATE_PULLING_CALL + }) + public @interface ConnectionState {} + /** * The connection is initializing. This is generally the first state for a {@code Connection} * returned by a {@link ConnectionService}. diff --git a/telephony/common/com/android/internal/telephony/SipMessageParsingUtils.java b/telephony/common/com/android/internal/telephony/SipMessageParsingUtils.java new file mode 100644 index 000000000000..c7e7cd5ec64e --- /dev/null +++ b/telephony/common/com/android/internal/telephony/SipMessageParsingUtils.java @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.telephony; + +import android.net.Uri; +import android.util.Log; +import android.util.Pair; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * Utility methods for parsing parts of {@link android.telephony.ims.SipMessage}s. + * See RFC 3261 for more information. + * @hide + */ +// Note: This is lightweight in order to avoid a full SIP stack import in frameworks/base. +public class SipMessageParsingUtils { + private static final String TAG = "SipMessageParsingUtils"; + // "Method" in request-line + // Request-Line = Method SP Request-URI SP SIP-Version CRLF + private static final String[] SIP_REQUEST_METHODS = new String[] {"INVITE", "ACK", "OPTIONS", + "BYE", "CANCEL", "REGISTER", "PRACK", "SUBSCRIBE", "NOTIFY", "PUBLISH", "INFO", "REFER", + "MESSAGE", "UPDATE"}; + + // SIP Version 2.0 (corresponding to RCS 3261), set in "SIP-Version" of Status-Line and + // Request-Line + // + // Request-Line = Method SP Request-URI SP SIP-Version CRLF + // Status-Line = SIP-Version SP Status-Code SP Reason-Phrase CRLF + private static final String SIP_VERSION_2 = "SIP/2.0"; + + // headers are formatted Key:Value + private static final String HEADER_KEY_VALUE_SEPARATOR = ":"; + // Multiple of the same header can be concatenated and put into one header Key:Value pair, for + // example "v: XX1;branch=YY1,XX2;branch=YY2". This needs to be treated as two "v:" headers. + private static final String SUBHEADER_VALUE_SEPARATOR = ","; + + // SIP header parameters have the format ";paramName=paramValue" + private static final String PARAM_SEPARATOR = ";"; + // parameters are formatted paramName=ParamValue + private static final String PARAM_KEY_VALUE_SEPARATOR = "="; + + // The via branch parameter definition + private static final String BRANCH_PARAM_KEY = "branch"; + + // via header key + private static final String VIA_SIP_HEADER_KEY = "via"; + // compact form of the via header key + private static final String VIA_SIP_HEADER_KEY_COMPACT = "v"; + + /** + * @return true if the SIP message start line is considered a request (based on known request + * methods). + */ + public static boolean isSipRequest(String startLine) { + String[] splitLine = splitStartLineAndVerify(startLine); + if (splitLine == null) return false; + return verifySipRequest(splitLine); + } + + /** + * Return the via branch parameter, which is used to identify the transaction ID (request and + * response pair) in a SIP transaction. + * @param headerString The string containing the headers of the SIP message. + */ + public static String getTransactionId(String headerString) { + // search for Via: or v: parameter, we only care about the first one. + List<Pair<String, String>> headers = parseHeaders(headerString, true, + VIA_SIP_HEADER_KEY, VIA_SIP_HEADER_KEY_COMPACT); + for (Pair<String, String> header : headers) { + // Headers can also be concatenated together using a "," between each header value. + // format becomes v: XX1;branch=YY1,XX2;branch=YY2. Need to extract only the first ID's + // branch param YY1. + String[] subHeaders = header.second.split(SUBHEADER_VALUE_SEPARATOR); + for (String subHeader : subHeaders) { + // Search for ;branch=z9hG4bKXXXXXX and return parameter value + String[] params = subHeader.split(PARAM_SEPARATOR); + if (params.length < 2) { + // This param doesn't include a branch param, move to next param. + Log.w(TAG, "getTransactionId: via detected without branch param:" + + subHeader); + continue; + } + // by spec, each param can only appear once in a header. + for (String param : params) { + String[] pair = param.split(PARAM_KEY_VALUE_SEPARATOR); + if (pair.length < 2) { + // ignore info before the first parameter + continue; + } + if (pair.length > 2) { + Log.w(TAG, + "getTransactionId: unexpected parameter" + Arrays.toString(pair)); + } + // Trim whitespace in parameter + pair[0] = pair[0].trim(); + pair[1] = pair[1].trim(); + if (BRANCH_PARAM_KEY.equalsIgnoreCase(pair[0])) { + // There can be multiple "Via" headers in the SIP message, however we want + // to return the first once found, as this corresponds with the transaction + // that is relevant here. + return pair[1]; + } + } + } + } + return null; + } + + private static String[] splitStartLineAndVerify(String startLine) { + String[] splitLine = startLine.split(" "); + if (isStartLineMalformed(splitLine)) return null; + return splitLine; + } + + private static boolean isStartLineMalformed(String[] startLine) { + if (startLine == null || startLine.length == 0) { + return true; + } + // start lines contain three segments separated by spaces (SP): + // Request-Line = Method SP Request-URI SP SIP-Version CRLF + // Status-Line = SIP-Version SP Status-Code SP Reason-Phrase CRLF + return (startLine.length != 3); + } + + private static boolean verifySipRequest(String[] request) { + // Request-Line = Method SP Request-URI SP SIP-Version CRLF + boolean verified = request[2].contains(SIP_VERSION_2); + verified &= (Uri.parse(request[1]).getScheme() != null); + verified &= Arrays.stream(SIP_REQUEST_METHODS).anyMatch(s -> request[0].contains(s)); + return verified; + } + + private static boolean verifySipResponse(String[] response) { + // Status-Line = SIP-Version SP Status-Code SP Reason-Phrase CRLF + boolean verified = response[0].contains(SIP_VERSION_2); + int statusCode = Integer.parseInt(response[1]); + verified &= (statusCode >= 100 && statusCode < 700); + return verified; + } + + /** + * Parse a String representation of the Header portion of the SIP Message and re-structure it + * into a List of key->value pairs representing each header in the order that they appeared in + * the message. + * + * @param headerString The raw string containing all headers + * @param stopAtFirstMatch Return early when the first match is found from matching header keys. + * @param matchingHeaderKeys An optional list of Strings containing header keys that should be + * returned if they exist. If none exist, all keys will be returned. + * (This is internally an equalsIgnoreMatch comparison). + * @return the matched header keys and values. + */ + private static List<Pair<String, String>> parseHeaders(String headerString, + boolean stopAtFirstMatch, String... matchingHeaderKeys) { + // Ensure there is no leading whitespace + headerString = removeLeadingWhitespace(headerString); + + List<Pair<String, String>> result = new ArrayList<>(); + // Split the string line-by-line. + String[] headerLines = headerString.split("\\r?\\n"); + if (headerLines.length == 0) { + return Collections.emptyList(); + } + + String headerKey = null; + StringBuilder headerValueSegment = new StringBuilder(); + // loop through each line, either parsing a "key: value" pair or appending values that span + // multiple lines. + for (String line : headerLines) { + // This line is a continuation of the last line if it starts with whitespace or tab + if (line.startsWith("\t") || line.startsWith(" ")) { + headerValueSegment.append(removeLeadingWhitespace(line)); + continue; + } + // This line is the start of a new key, If headerKey/value is already populated from a + // previous key/value pair, add it to list of parsed header pairs. + if (headerKey != null) { + final String key = headerKey; + if (matchingHeaderKeys == null || matchingHeaderKeys.length == 0 + || Arrays.stream(matchingHeaderKeys).anyMatch( + (s) -> s.equalsIgnoreCase(key))) { + result.add(new Pair<>(key, headerValueSegment.toString())); + if (stopAtFirstMatch) { + return result; + } + } + headerKey = null; + headerValueSegment = new StringBuilder(); + } + + // Format is "Key:Value", ignore any ":" after the first. + String[] pair = line.split(HEADER_KEY_VALUE_SEPARATOR, 2); + if (pair.length < 2) { + // malformed line, skip + Log.w(TAG, "parseHeaders - received malformed line: " + line); + continue; + } + + headerKey = pair[0].trim(); + for (int i = 1; i < pair.length; i++) { + headerValueSegment.append(removeLeadingWhitespace(pair[i])); + } + } + // Pick up the last pending header being parsed, if it exists. + if (headerKey != null) { + final String key = headerKey; + if (matchingHeaderKeys == null || matchingHeaderKeys.length == 0 + || Arrays.stream(matchingHeaderKeys).anyMatch( + (s) -> s.equalsIgnoreCase(key))) { + result.add(new Pair<>(key, headerValueSegment.toString())); + } + } + + return result; + } + + private static String removeLeadingWhitespace(String line) { + return line.replaceFirst("^\\s*", ""); + } +} diff --git a/telephony/java/android/telephony/PhoneCapability.java b/telephony/java/android/telephony/PhoneCapability.java index b785037e51c1..6571858fc4ae 100644 --- a/telephony/java/android/telephony/PhoneCapability.java +++ b/telephony/java/android/telephony/PhoneCapability.java @@ -28,8 +28,6 @@ import java.util.Objects; /** * Define capability of a modem group. That is, the capabilities * are shared between those modems defined by list of modem IDs. - * - * @hide */ public final class PhoneCapability implements Parcelable { // Hardcoded default DSDS capability. diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java index ed09d538a3b1..1273aa3abbc9 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -478,7 +478,9 @@ public class PhoneNumberUtils { /** * Compare phone numbers a and b, return true if they're identical enough for caller ID purposes. + * @deprecated use {@link #areSamePhoneNumber(String, String, String)} instead */ + @Deprecated public static boolean compare(String a, String b) { // We've used loose comparation at least Eclair, which may change in the future. @@ -489,7 +491,9 @@ public class PhoneNumberUtils { * Compare phone numbers a and b, and return true if they're identical * enough for caller ID purposes. Checks a resource to determine whether * to use a strict or loose comparison algorithm. + * @deprecated use {@link #areSamePhoneNumber(String, String, String)} instead */ + @Deprecated public static boolean compare(Context context, String a, String b) { boolean useStrict = context.getResources().getBoolean( com.android.internal.R.bool.config_use_strict_phone_number_comparation); @@ -3218,7 +3222,7 @@ public class PhoneNumberUtils { } // The conversion map is not defined (this is default). Skip conversion. - if (sConvertToEmergencyMap == null || sConvertToEmergencyMap.length == 0 ) { + if (sConvertToEmergencyMap == null || sConvertToEmergencyMap.length == 0) { return number; } @@ -3254,4 +3258,47 @@ public class PhoneNumberUtils { } return number; } + + /** + * Determines if two phone numbers are the same. + * <p> + * Matching is based on <a href="https://github.com/google/libphonenumber>libphonenumber</a>. + * Unlike {@link #compare(String, String)}, matching takes into account national + * dialing plans rather than simply matching the last 7 digits of the two phone numbers. As a + * result, it is expected that some numbers which would match using the previous method will no + * longer match using this new approach. + * + * @param number1 + * @param number2 + * @param defaultCountryIso The lowercase two letter ISO 3166-1 country code. Used when parsing + * the phone numbers where it is not possible to determine the country + * associated with a phone number based on the number alone. It + * is recommended to pass in + * {@link TelephonyManager#getNetworkCountryIso()}. + * @return True if the two given phone number are same. + */ + public static boolean areSamePhoneNumber(@NonNull String number1, + @NonNull String number2, @NonNull String defaultCountryIso) { + PhoneNumberUtil util = PhoneNumberUtil.getInstance(); + PhoneNumber n1; + PhoneNumber n2; + defaultCountryIso = defaultCountryIso.toUpperCase(); + try { + n1 = util.parseAndKeepRawInput(number1, defaultCountryIso); + n2 = util.parseAndKeepRawInput(number2, defaultCountryIso); + } catch (NumberParseException e) { + return false; + } + + PhoneNumberUtil.MatchType matchType = util.isNumberMatch(n1, n2); + if (matchType == PhoneNumberUtil.MatchType.EXACT_MATCH + || matchType == PhoneNumberUtil.MatchType.NSN_MATCH) { + return true; + } else if (matchType == PhoneNumberUtil.MatchType.SHORT_NSN_MATCH) { + return (n1.getNationalNumber() == n2.getNationalNumber() + && n1.getCountryCode() == n2.getCountryCode()); + } else { + return false; + } + } } diff --git a/telephony/java/android/telephony/PhysicalChannelConfig.java b/telephony/java/android/telephony/PhysicalChannelConfig.java index af62ba4b93a1..327d6313c4dc 100644 --- a/telephony/java/android/telephony/PhysicalChannelConfig.java +++ b/telephony/java/android/telephony/PhysicalChannelConfig.java @@ -17,6 +17,8 @@ package android.telephony; import android.annotation.IntDef; +import android.annotation.IntRange; +import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; import android.telephony.Annotation.NetworkType; @@ -26,12 +28,10 @@ import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.Objects; -/** - * @hide - */ public final class PhysicalChannelConfig implements Parcelable { // TODO(b/72993578) consolidate these enums in a central location. + /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef({CONNECTION_PRIMARY_SERVING, CONNECTION_SECONDARY_SERVING, CONNECTION_UNKNOWN}) public @interface ConnectionStatus {} @@ -47,7 +47,13 @@ public final class PhysicalChannelConfig implements Parcelable { public static final int CONNECTION_SECONDARY_SERVING = 2; /** Connection status is unknown. */ - public static final int CONNECTION_UNKNOWN = Integer.MAX_VALUE; + public static final int CONNECTION_UNKNOWN = -1; + + /** Channel number is unknown. */ + public static final int CHANNEL_NUMBER_UNKNOWN = -1; + + /** Physical Cell Id is unknown. */ + public static final int PHYSICAL_CELL_ID_UNKNOWN = -1; /** * Connection status of the cell. @@ -75,7 +81,7 @@ public final class PhysicalChannelConfig implements Parcelable { private int mFrequencyRange; /** - * The absolute radio frequency channel number, {@link Integer#MAX_VALUE} if unknown. + * The absolute radio frequency channel number, {@link #CHANNEL_NUMBER_UNKNOWN} if unknown. */ private int mChannelNumber; @@ -86,7 +92,7 @@ public final class PhysicalChannelConfig implements Parcelable { private int[] mContextIds; /** - * The physical cell identifier for this cell - PCI, PSC, {@link Integer#MAX_VALUE} if known. + * The physical cell identifier for this cell - PCI, PSC, {@link #PHYSICAL_CELL_ID_UNKNOWN} */ private int mPhysicalCellId; @@ -96,7 +102,7 @@ public final class PhysicalChannelConfig implements Parcelable { } @Override - public void writeToParcel(Parcel dest, int flags) { + public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeInt(mCellConnectionStatus); dest.writeInt(mCellBandwidthDownlinkKhz); dest.writeInt(mRat); @@ -120,6 +126,7 @@ public final class PhysicalChannelConfig implements Parcelable { * physical channel has no data call mapped to it. * * @return an integer list indicates the data call ids. + * @hide */ public int[] getContextIds() { return mContextIds; @@ -131,6 +138,7 @@ public final class PhysicalChannelConfig implements Parcelable { * @see {@link ServiceState#FREQUENCY_RANGE_MID} * @see {@link ServiceState#FREQUENCY_RANGE_HIGH} * @see {@link ServiceState#FREQUENCY_RANGE_MMWAVE} + * @hide */ @ServiceState.FrequencyRange public int getFrequencyRange() { @@ -139,7 +147,7 @@ public final class PhysicalChannelConfig implements Parcelable { /** * @return the absolute radio frequency channel number for this physical channel, - * {@link Integer#MAX_VALUE} if unknown. + * {@link #CHANNEL_NUMBER_UNKNOWN} if unknown. */ public int getChannelNumber() { return mChannelNumber; @@ -152,18 +160,20 @@ public final class PhysicalChannelConfig implements Parcelable { * In EUTRAN, this value is physical layer cell identity. The range is [0, 503]. * Reference: 3GPP TS 36.211 section 6.11. * - * In 5G RAN, this value is physical layer cell identity. The range is [0, 1008]. + * In 5G RAN, this value is physical layer cell identity. The range is [0, 1007]. * Reference: 3GPP TS 38.211 section 7.4.2.1. * - * @return the physical cell identifier for this cell, {@link Integer#MAX_VALUE} if unknown. + * @return the physical cell identifier for this cell, {@link #PHYSICAL_CELL_ID_UNKNOWN} + * if {@link android.telephony.CellInfo#UNAVAILABLE}. */ + @IntRange(from = 0, to = 1007) public int getPhysicalCellId() { return mPhysicalCellId; } /**The radio technology for this physical channel. */ @NetworkType - public int getRat() { + public int getNetworkType() { return mRat; } @@ -181,7 +191,10 @@ public final class PhysicalChannelConfig implements Parcelable { return mCellConnectionStatus; } - /** @return String representation of the connection status */ + /** + * @return String representation of the connection status + * @hide + */ private String getConnectionStatusString() { switch(mCellConnectionStatus) { case CONNECTION_PRIMARY_SERVING: @@ -274,7 +287,10 @@ public final class PhysicalChannelConfig implements Parcelable { mPhysicalCellId = builder.mPhysicalCellId; } - /** The builder of {@code PhysicalChannelConfig}. */ + /** + * The builder of {@code PhysicalChannelConfig}. + * @hide + */ public static final class Builder { private int mRat; private int mFrequencyRange; @@ -284,60 +300,51 @@ public final class PhysicalChannelConfig implements Parcelable { private int[] mContextIds; private int mPhysicalCellId; - /** @hide */ public Builder() { mRat = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN; mFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN; - mChannelNumber = Integer.MAX_VALUE; + mChannelNumber = CHANNEL_NUMBER_UNKNOWN; mCellBandwidthDownlinkKhz = 0; mCellConnectionStatus = CONNECTION_UNKNOWN; mContextIds = new int[0]; - mPhysicalCellId = Integer.MAX_VALUE; + mPhysicalCellId = PHYSICAL_CELL_ID_UNKNOWN; } - /** @hide */ public PhysicalChannelConfig build() { return new PhysicalChannelConfig(this); } - /** @hide */ public Builder setRat(int rat) { this.mRat = rat; return this; } - /** @hide */ public Builder setFrequencyRange(int frequencyRange) { this.mFrequencyRange = frequencyRange; return this; } - /** @hide */ public Builder setChannelNumber(int channelNumber) { this.mChannelNumber = channelNumber; return this; } - /** @hide */ public Builder setCellBandwidthDownlinkKhz(int cellBandwidthDownlinkKhz) { this.mCellBandwidthDownlinkKhz = cellBandwidthDownlinkKhz; return this; } - /** @hide */ public Builder setCellConnectionStatus(int connectionStatus) { this.mCellConnectionStatus = connectionStatus; return this; } - /** @hide */ public Builder setContextIds(int[] contextIds) { if (contextIds != null) Arrays.sort(contextIds); this.mContextIds = contextIds; return this; } - /** @hide */ public Builder setPhysicalCellId(int physicalCellId) { this.mPhysicalCellId = physicalCellId; return this; diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index c05e90b28fa8..f39ee095758c 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -124,6 +124,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.UUID; import java.util.concurrent.Executor; import java.util.function.Consumer; @@ -155,6 +156,7 @@ import java.util.function.Consumer; public class TelephonyManager { private static final String TAG = "TelephonyManager"; + private TelephonyRegistryManager mTelephonyRegistryMgr; /** * To expand the error codes for {@link TelephonyManager#updateAvailableNetworks} and * {@link TelephonyManager#setPreferredOpportunisticDataSubscription}. @@ -5569,8 +5571,7 @@ public class TelephonyManager { // /** - * Registers a listener object to receive notification of changes - * in specified telephony states. + * Registers a listener object to receive notification of changes in specified telephony states. * <p> * To register a listener, pass a {@link PhoneStateListener} and specify at least one telephony * state of interest in the events argument. @@ -5580,13 +5581,15 @@ public class TelephonyManager { * values. * <p> * To un-register a listener, pass the listener object and set the events argument to - * {@link PhoneStateListener#LISTEN_NONE LISTEN_NONE} (0). + * {@link PhoneStateListener#LISTEN_NONE} (0). * * If this TelephonyManager object has been created with {@link #createForSubscriptionId}, * applies to the given subId. Otherwise, applies to - * {@link SubscriptionManager#getDefaultSubscriptionId()}. To listen events for multiple subIds, + * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}. To listen events for multiple subIds, * pass a separate listener object to each TelephonyManager object created with - * {@link #createForSubscriptionId}. + * {@link #createForSubscriptionId}. Only {@link PhoneStateListener#LISTEN_CALL_STATE} event can + * be used to receive changes for all subIds through + * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}. * * Note: if you call this method while in the middle of a binder transaction, you <b>must</b> * call {@link android.os.Binder#clearCallingIdentity()} before calling this method. A @@ -5596,23 +5599,28 @@ public class TelephonyManager { * instability. If a process has registered too many listeners without unregistering them, it * may encounter an {@link IllegalStateException} when trying to register more listeners. * - * @param listener The {@link PhoneStateListener} object to register - * (or unregister) - * @param events The telephony state(s) of interest to the listener, - * as a bitwise-OR combination of {@link PhoneStateListener} - * LISTEN_ flags. + * @param listener The {@link PhoneStateListener} object to register (or unregister) + * @param events The telephony state(s) of interest to the listener, as a bitwise-OR combination + * of {@link PhoneStateListener} LISTEN_ flags. + * @deprecated Use {@link #registerPhoneStateListener(Executor, PhoneStateListener)}. */ + @Deprecated public void listen(PhoneStateListener listener, int events) { - if (mContext == null) return; - boolean notifyNow = (getITelephony() != null); - TelephonyRegistryManager telephonyRegistry = - (TelephonyRegistryManager) - mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); - if (telephonyRegistry != null) { - telephonyRegistry.listenForSubscriber(mSubId, getOpPackageName(), getAttributionTag(), - listener, events, notifyNow); + if (!listener.isExecutorSet()) { + throw new IllegalStateException("PhoneStateListener should be created on a thread " + + "with Looper.myLooper() != null"); + } + boolean notifyNow = getITelephony() != null; + mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class); + if (mTelephonyRegistryMgr != null) { + if (events != PhoneStateListener.LISTEN_NONE) { + mTelephonyRegistryMgr.registerPhoneStateListenerWithEvents(mSubId, + getOpPackageName(), getAttributionTag(), listener, events, notifyNow); + } else { + unregisterPhoneStateListener(listener); + } } else { - Rlog.w(TAG, "telephony registry not ready."); + throw new IllegalStateException("telephony service is null."); } } @@ -8689,11 +8697,18 @@ public class TelephonyManager { */ public static final int CALL_COMPOSER_STATUS_ON = 1; + /** + * Call composer status indicating that sending/receiving pictures is disabled. + * All other attachments are still enabled in this state. + */ + public static final int CALL_COMPOSER_STATUS_ON_NO_PICTURES = 2; + /** @hide */ @IntDef(prefix = {"CALL_COMPOSER_STATUS_"}, value = { CALL_COMPOSER_STATUS_ON, CALL_COMPOSER_STATUS_OFF, + CALL_COMPOSER_STATUS_ON_NO_PICTURES, }) public @interface CallComposerStatus {} @@ -8701,8 +8716,9 @@ public class TelephonyManager { * Set the user-set status for enriched calling with call composer. * * @param status user-set status for enriched calling with call composer; - * it must be a value of either {@link #CALL_COMPOSER_STATUS_ON} - * or {@link #CALL_COMPOSER_STATUS_OFF}. + * it must be any of {@link #CALL_COMPOSER_STATUS_ON} + * {@link #CALL_COMPOSER_STATUS_OFF}, + * or {@link #CALL_COMPOSER_STATUS_ON_NO_PICTURES} * * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()} @@ -8712,7 +8728,8 @@ public class TelephonyManager { */ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallComposerStatus(@CallComposerStatus int status) { - if (status != CALL_COMPOSER_STATUS_ON && status != CALL_COMPOSER_STATUS_OFF) { + if (status > CALL_COMPOSER_STATUS_ON_NO_PICTURES + || status < CALL_COMPOSER_STATUS_OFF) { throw new IllegalArgumentException("requested status is invalid"); } try { @@ -8734,8 +8751,9 @@ public class TelephonyManager { * * @throws SecurityException if the caller does not have the permission. * - * @return the user-set status for enriched calling with call composer either - * {@link #CALL_COMPOSER_STATUS_ON} or {@link #CALL_COMPOSER_STATUS_OFF}. + * @return the user-set status for enriched calling with call composer, any of + * {@link #CALL_COMPOSER_STATUS_ON}, {@link #CALL_COMPOSER_STATUS_OFF}, or + * {@link #CALL_COMPOSER_STATUS_ON_NO_PICTURES}. */ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public @CallComposerStatus int getCallComposerStatus() { @@ -14583,4 +14601,71 @@ public class TelephonyManager { e.execute(() -> callback.onAuthenticationFailure(GBA_FAILURE_REASON_FEATURE_NOT_READY)); } } + + /** + * Registers a listener object to receive notification of changes in specified telephony states. + * <p> + * To register a listener, pass a {@link PhoneStateListener} which implements + * interfaces of events. For example, + * FakeServiceStateChangedListener extends {@link PhoneStateListener} implements + * {@link PhoneStateListener.ServiceStateChangedListener}. + * + * At registration, and when a specified telephony state changes, the telephony manager invokes + * the appropriate callback method on the listener object and passes the current (updated) + * values. + * <p> + * + * If this TelephonyManager object has been created with {@link #createForSubscriptionId}, + * applies to the given subId. Otherwise, applies to + * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}. To listen events for multiple subIds, + * pass a separate listener object to each TelephonyManager object created with + * {@link #createForSubscriptionId}. Only {@link PhoneStateListener.CallStateChangedListener} + * can be used to receive changes for all subIds through + * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}. + * + * Note: if you call this method while in the middle of a binder transaction, you <b>must</b> + * call {@link android.os.Binder#clearCallingIdentity()} before calling this method. A + * {@link SecurityException} will be thrown otherwise. + * + * This API should be used sparingly -- large numbers of listeners will cause system + * instability. If a process has registered too many listeners without unregistering them, it + * may encounter an {@link IllegalStateException} when trying to register more listeners. + * + * @param executor The executor of where the callback will execute. + * @param listener The {@link PhoneStateListener} object to register. + */ + public void registerPhoneStateListener(@NonNull @CallbackExecutor Executor executor, + @NonNull PhoneStateListener listener) { + if (executor == null || listener == null) { + throw new IllegalArgumentException("PhoneStateListener and executor must be non-null"); + } + mTelephonyRegistryMgr = (TelephonyRegistryManager) + mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); + if (mTelephonyRegistryMgr != null) { + mTelephonyRegistryMgr.registerPhoneStateListener(executor, mSubId, + getOpPackageName(), getAttributionTag(), listener, getITelephony() != null); + } else { + throw new IllegalStateException("telephony service is null."); + } + } + + /** + * Unregister an existing {@link PhoneStateListener}. + * + * @param listener The {@link PhoneStateListener} object to unregister. + */ + public void unregisterPhoneStateListener(@NonNull PhoneStateListener listener) { + + if (mContext == null) { + throw new IllegalStateException("telephony service is null."); + } + + mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class); + if (mTelephonyRegistryMgr != null) { + mTelephonyRegistryMgr.unregisterPhoneStateListener(mSubId, getOpPackageName(), + getAttributionTag(), listener, getITelephony() != null); + } else { + throw new IllegalStateException("telephony service is null."); + } + } } diff --git a/telephony/java/android/telephony/ims/DelegateRegistrationState.java b/telephony/java/android/telephony/ims/DelegateRegistrationState.java index 66281edc0de1..fd206c1e803f 100644 --- a/telephony/java/android/telephony/ims/DelegateRegistrationState.java +++ b/telephony/java/android/telephony/ims/DelegateRegistrationState.java @@ -320,4 +320,11 @@ public final class DelegateRegistrationState implements Parcelable { public int hashCode() { return Objects.hash(mRegisteredTags, mDeregisteringTags, mDeregisteredTags); } + + @Override + public String toString() { + return "DelegateRegistrationState{ registered={" + mRegisteredTags + + "}, deregistering={" + mDeregisteringTags + "}, deregistered={" + + mDeregisteredTags + "}}"; + } } diff --git a/telephony/java/android/telephony/ims/SipMessage.java b/telephony/java/android/telephony/ims/SipMessage.java index 1539224dedcf..006cca84e44b 100644 --- a/telephony/java/android/telephony/ims/SipMessage.java +++ b/telephony/java/android/telephony/ims/SipMessage.java @@ -22,6 +22,8 @@ import android.os.Build; import android.os.Parcel; import android.os.Parcelable; +import com.android.internal.telephony.SipMessageParsingUtils; + import java.util.Arrays; import java.util.Objects; @@ -38,9 +40,6 @@ public final class SipMessage implements Parcelable { // Should not be set to true for production! private static final boolean IS_DEBUGGING = Build.IS_ENG; - private static final String[] SIP_REQUEST_METHODS = new String[] {"INVITE", "ACK", "OPTIONS", - "BYE", "CANCEL", "REGISTER"}; - private final String mStartLine; private final String mHeaderSection; private final byte[] mContent; @@ -72,6 +71,7 @@ public final class SipMessage implements Parcelable { mContent = new byte[source.readInt()]; source.readByteArray(mContent); } + /** * @return The start line of the SIP message, which contains either the request-line or * status-line. @@ -128,34 +128,25 @@ public final class SipMessage implements Parcelable { } else { b.append(sanitizeStartLineRequest(mStartLine)); } - b.append("], ["); - b.append("Header: ["); + b.append("], Header: ["); if (IS_DEBUGGING) { b.append(mHeaderSection); } else { // only identify transaction id/call ID when it is available. b.append("***"); } - b.append("], "); - b.append("Content: [NOT SHOWN]"); + b.append("], Content: "); + b.append(getContent().length == 0 ? "[NONE]" : "[NOT SHOWN]"); return b.toString(); } /** - * Start lines containing requests are formatted: METHOD SP Request-URI SP SIP-Version CRLF. * Detect if this is a REQUEST and redact Request-URI portion here, as it contains PII. */ private String sanitizeStartLineRequest(String startLine) { + if (!SipMessageParsingUtils.isSipRequest(startLine)) return startLine; String[] splitLine = startLine.split(" "); - if (splitLine == null || splitLine.length == 0) { - return "(INVALID STARTLINE)"; - } - for (String method : SIP_REQUEST_METHODS) { - if (splitLine[0].contains(method)) { - return splitLine[0] + " <Request-URI> " + splitLine[2]; - } - } - return startLine; + return splitLine[0] + " <Request-URI> " + splitLine[2]; } @Override diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java index 522ad8160870..9d919015087d 100644 --- a/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java +++ b/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java @@ -28,6 +28,10 @@ import android.telephony.ims.SipDelegateImsConfiguration; import android.telephony.ims.SipDelegateManager; import android.telephony.ims.SipMessage; import android.telephony.ims.stub.SipDelegate; +import android.text.TextUtils; +import android.util.Log; + +import com.android.internal.telephony.SipMessageParsingUtils; import java.util.ArrayList; import java.util.Set; @@ -40,6 +44,7 @@ import java.util.concurrent.Executor; * @hide */ public class SipDelegateAidlWrapper implements DelegateStateCallback, DelegateMessageCallback { + private static final String LOG_TAG = "SipDelegateAW"; private final ISipDelegate.Stub mDelegateBinder = new ISipDelegate.Stub() { @Override @@ -183,11 +188,15 @@ public class SipDelegateAidlWrapper implements DelegateStateCallback, DelegateMe } private void notifyLocalMessageFailedToBeReceived(SipMessage m, int reason) { - //TODO: parse transaction ID or throw IllegalArgumentException if the SipMessage - // transaction ID can not be parsed. + String transactionId = SipMessageParsingUtils.getTransactionId(m.getHeaderSection()); + if (TextUtils.isEmpty(transactionId)) { + Log.w(LOG_TAG, "failure to parse SipMessage."); + throw new IllegalArgumentException("Malformed SipMessage, can not determine " + + "transaction ID."); + } SipDelegate d = mDelegate; if (d != null) { - mExecutor.execute(() -> d.notifyMessageReceiveError(null, reason)); + mExecutor.execute(() -> d.notifyMessageReceiveError(transactionId, reason)); } } } diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java index a35039bd7668..c877aca8ba96 100644 --- a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java +++ b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java @@ -28,9 +28,12 @@ import android.telephony.ims.SipMessage; import android.telephony.ims.stub.DelegateConnectionMessageCallback; import android.telephony.ims.stub.DelegateConnectionStateCallback; import android.telephony.ims.stub.SipDelegate; +import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; +import com.android.internal.telephony.SipMessageParsingUtils; + import java.util.List; import java.util.NoSuchElementException; import java.util.concurrent.Executor; @@ -265,9 +268,13 @@ public class SipDelegateConnectionAidlWrapper implements SipDelegateConnection, } private void notifyLocalMessageFailedToSend(SipMessage m, int reason) { - //TODO: parse transaction ID or throw IllegalArgumentException if the SipMessage - // transaction ID can not be parsed. + String transactionId = SipMessageParsingUtils.getTransactionId(m.getHeaderSection()); + if (TextUtils.isEmpty(transactionId)) { + Log.w(LOG_TAG, "sendMessage detected a malformed SipMessage and can not get a " + + "transaction ID."); + throw new IllegalArgumentException("Could not send SipMessage due to malformed header"); + } mExecutor.execute(() -> - mMessageCallback.onMessageSendFailure(null, reason)); + mMessageCallback.onMessageSendFailure(transactionId, reason)); } } diff --git a/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java b/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java index d2cb9761a028..d9734a7475c0 100644 --- a/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java +++ b/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java @@ -18,15 +18,12 @@ package android.telephony.ims.stub; import android.annotation.NonNull; import android.annotation.SystemApi; -import android.net.Uri; import android.telephony.ims.ImsException; import android.telephony.ims.RcsContactUceCapability; import android.telephony.ims.RcsUceAdapter; import android.telephony.ims.feature.ImsFeature; import android.telephony.ims.feature.RcsFeature; -import java.util.List; - /** * The interface of the capabilities event listener for ImsService to notify the framework of the * UCE request and status updated. @@ -84,25 +81,4 @@ public interface CapabilityExchangeEventListener { * Telephony stack has crashed. */ void onUnpublish() throws ImsException; - - /** - * Inform the framework of a query for this device's UCE capabilities. - * <p> - * The framework will respond via the - * {@link OptionsRequestCallback#onRespondToCapabilityRequest} or - * {@link OptionsRequestCallback#onRespondToCapabilityRequestWithError} - * @param contactUri The URI associated with the remote contact that is - * requesting capabilities. - * @param remoteCapabilities The remote contact's capability information. - * @param callback The callback of this request which is sent from the remote user. - * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is not - * currently connected to the framework. This can happen if the {@link RcsFeature} is not - * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received - * the {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare - * cases when the Telephony stack has crashed. - * @hide - */ - void onRemoteCapabilityRequest(@NonNull Uri contactUri, - @NonNull List<String> remoteCapabilities, - @NonNull OptionsRequestCallback callback) throws ImsException; } diff --git a/tests/net/common/java/android/net/CaptivePortalDataTest.kt b/tests/net/common/java/android/net/CaptivePortalDataTest.kt index 8710d23730b6..2cb16d3372d7 100644 --- a/tests/net/common/java/android/net/CaptivePortalDataTest.kt +++ b/tests/net/common/java/android/net/CaptivePortalDataTest.kt @@ -18,12 +18,15 @@ package android.net import android.os.Build import androidx.test.filters.SmallTest +import com.android.modules.utils.build.SdkLevel import com.android.testutils.assertParcelSane import com.android.testutils.assertParcelingIsLossless +import com.android.testutils.DevSdkIgnoreRule import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo import com.android.testutils.DevSdkIgnoreRunner import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue +import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import kotlin.test.assertEquals @@ -33,6 +36,9 @@ import kotlin.test.assertNotEquals @RunWith(DevSdkIgnoreRunner::class) @IgnoreUpTo(Build.VERSION_CODES.Q) class CaptivePortalDataTest { + @Rule @JvmField + val ignoreRule = DevSdkIgnoreRule() + private val data = CaptivePortalData.Builder() .setRefreshTime(123L) .setUserPortalUrl(Uri.parse("https://portal.example.com/test")) @@ -41,7 +47,11 @@ class CaptivePortalDataTest { .setBytesRemaining(456L) .setExpiryTime(789L) .setCaptive(true) - .setVenueFriendlyName("venue friendly name") + .apply { + if (SdkLevel.isAtLeastS()) { + setVenueFriendlyName("venue friendly name") + } + } .build() private fun makeBuilder() = CaptivePortalData.Builder(data) @@ -67,8 +77,11 @@ class CaptivePortalDataTest { assertNotEqualsAfterChange { it.setBytesRemaining(789L) } assertNotEqualsAfterChange { it.setExpiryTime(12L) } assertNotEqualsAfterChange { it.setCaptive(false) } - assertNotEqualsAfterChange { it.setVenueFriendlyName("another friendly name") } - assertNotEqualsAfterChange { it.setVenueFriendlyName(null) } + + if (SdkLevel.isAtLeastS()) { + assertNotEqualsAfterChange { it.setVenueFriendlyName("another friendly name") } + assertNotEqualsAfterChange { it.setVenueFriendlyName(null) } + } } @Test @@ -111,7 +124,7 @@ class CaptivePortalDataTest { assertFalse(makeBuilder().setCaptive(false).build().isCaptive) } - @Test + @Test @IgnoreUpTo(Build.VERSION_CODES.R) fun testVenueFriendlyName() { assertEquals("venue friendly name", data.venueFriendlyName) } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index b6e6816ca531..4a282e806d8a 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -8429,6 +8429,7 @@ public class ConnectivityServiceTest { mCm.registerNetworkCallback(genericRequest, genericNetworkCallback); mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback); mCm.registerNetworkCallback(cellRequest, cellNetworkCallback); + waitForIdle(); final ConnectivityService.NetworkRequestInfo[] nriOutput = mService.requestsSortedById(); diff --git a/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java b/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java new file mode 100644 index 000000000000..31561901be9e --- /dev/null +++ b/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.vcn; + +import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; + +import android.net.wifi.WifiInfo; +import android.os.Parcel; + +import org.junit.Test; + +public class VcnTransportInfoTest { + private static final int SUB_ID = 1; + private static final int NETWORK_ID = 5; + private static final WifiInfo WIFI_INFO = + new WifiInfo.Builder().setNetworkId(NETWORK_ID).build(); + + private static final VcnTransportInfo CELL_UNDERLYING_INFO = new VcnTransportInfo(SUB_ID); + private static final VcnTransportInfo WIFI_UNDERLYING_INFO = new VcnTransportInfo(WIFI_INFO); + + @Test + public void testGetWifiInfo() { + assertEquals(WIFI_INFO, WIFI_UNDERLYING_INFO.getWifiInfo()); + + assertNull(CELL_UNDERLYING_INFO.getWifiInfo()); + } + + @Test + public void testGetSubId() { + assertEquals(SUB_ID, CELL_UNDERLYING_INFO.getSubId()); + + assertEquals(INVALID_SUBSCRIPTION_ID, WIFI_UNDERLYING_INFO.getSubId()); + } + + @Test + public void testEquals() { + assertEquals(CELL_UNDERLYING_INFO, CELL_UNDERLYING_INFO); + assertEquals(WIFI_UNDERLYING_INFO, WIFI_UNDERLYING_INFO); + assertNotEquals(CELL_UNDERLYING_INFO, WIFI_UNDERLYING_INFO); + } + + @Test + public void testParcelUnparcel() { + verifyParcelingIsNull(CELL_UNDERLYING_INFO); + verifyParcelingIsNull(WIFI_UNDERLYING_INFO); + } + + private void verifyParcelingIsNull(VcnTransportInfo vcnTransportInfo) { + Parcel parcel = Parcel.obtain(); + vcnTransportInfo.writeToParcel(parcel, 0 /* flags */); + assertNull(VcnTransportInfo.CREATOR.createFromParcel(parcel)); + } +} |