Java tutorial
/* * Copyright (C) 2008 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.telephony; import android.Manifest; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.HandlerExecutor; import android.os.Looper; import android.telephony.emergency.EmergencyNumber; import android.telephony.ims.ImsReasonInfo; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.IPhoneStateListener; import java.lang.ref.WeakReference; import java.util.List; import java.util.Map; import java.util.concurrent.Executor; /** * A listener class for monitoring changes in specific telephony states * on the device, including service state, signal strength, message * waiting indicator (voicemail), and others. * <p> * Override the methods for the state that you wish to receive updates for, and * pass your PhoneStateListener object, along with bitwise-or of the LISTEN_ * flags to {@link TelephonyManager#listen TelephonyManager.listen()}. Methods are * called when the state changes, as well as once on initial registration. * <p> * Note that access to some telephony information is * permission-protected. Your application won't receive updates for protected * information unless it has the appropriate permissions declared in * its manifest file. Where permissions apply, they are noted in the * appropriate LISTEN_ flags. */ public class PhoneStateListener { private static final String LOG_TAG = "PhoneStateListener"; private static final boolean DBG = false; // STOPSHIP if true /** * Stop listening for updates. * * The PhoneStateListener is not tied to any subscription and unregistered for any update. */ public static final int LISTEN_NONE = 0; /** * Listen for changes to the network service state (cellular). * * @see #onServiceStateChanged * @see ServiceState */ public static final int LISTEN_SERVICE_STATE = 0x00000001; /** * Listen for changes to the network signal strength (cellular). * {@more} * * @see #onSignalStrengthChanged * * @deprecated by {@link #LISTEN_SIGNAL_STRENGTHS} */ @Deprecated public static final int LISTEN_SIGNAL_STRENGTH = 0x00000002; /** * Listen for changes to the message-waiting indicator. * {@more} * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE * 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 #onMessageWaitingIndicatorChanged */ public static final int LISTEN_MESSAGE_WAITING_INDICATOR = 0x00000004; /** * Listen for changes to the call-forwarding indicator. * {@more} * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE * READ_PHONE_STATE} or that the calling app has carrier privileges (see * {@link TelephonyManager#hasCarrierPrivileges}). * * @see #onCallForwardingIndicatorChanged */ public static final int LISTEN_CALL_FORWARDING_INDICATOR = 0x00000008; /** * Listen for changes to the device's cell location. Note that * this will result in frequent callbacks to the listener. * {@more} * Requires Permission: {@link android.Manifest.permission#ACCESS_COARSE_LOCATION * ACCESS_COARSE_LOCATION} * <p> * 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 #onCellLocationChanged */ public static final int LISTEN_CELL_LOCATION = 0x00000010; /** * Listen for changes to the device call state. * {@more} * * @see #onCallStateChanged */ public static final int LISTEN_CALL_STATE = 0x00000020; /** * Listen for changes to the data connection state (cellular). * * @see #onDataConnectionStateChanged */ public static final int LISTEN_DATA_CONNECTION_STATE = 0x00000040; /** * Listen for changes to the direction of data traffic on the data * connection (cellular). * {@more} * Example: The status bar uses this to display the appropriate * data-traffic icon. * * @see #onDataActivity */ public static final int LISTEN_DATA_ACTIVITY = 0x00000080; /** * Listen for changes to the network signal strengths (cellular). * <p> * Example: The status bar uses this to control the signal-strength * icon. * * @see #onSignalStrengthsChanged */ public static final int LISTEN_SIGNAL_STRENGTHS = 0x00000100; /** * Listen for changes to OTASP mode. * * @see #onOtaspChanged * @hide */ public static final int LISTEN_OTASP_CHANGED = 0x00000200; /** * Listen for changes to observed cell info. * * @see #onCellInfoChanged */ public static final int LISTEN_CELL_INFO = 0x00000400; /** * Listen for {@link PreciseCallState.State} of ringing, background and foreground calls. * * @hide */ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE)) @SystemApi public static final int LISTEN_PRECISE_CALL_STATE = 0x00000800; /** * Listen for {@link PreciseDataConnectionState} on the data connection (cellular). * * @see #onPreciseDataConnectionStateChanged * * @hide */ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE)) @SystemApi public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 0x00001000; /** * Listen for real time info for all data connections (cellular)). * {@more} * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE * READ_PRECISE_PHONE_STATE} * @see #onDataConnectionRealTimeInfoChanged(DataConnectionRealTimeInfo) * * @deprecated Use {@link TelephonyManager#getModemActivityInfo()} * @hide */ @Deprecated public static final int LISTEN_DATA_CONNECTION_REAL_TIME_INFO = 0x00002000; /** * Listen for changes to the SRVCC state of the active call. * @see #onServiceStateChanged(ServiceState) * @hide */ @SystemApi @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_SRVCC_STATE_CHANGED = 0x00004000; /** * Listen for OEM hook raw event * * @see #onOemHookRawEvent * @hide * @deprecated OEM needs a vendor-extension hal and their apps should use that instead */ @Deprecated public static final int LISTEN_OEM_HOOK_RAW_EVENT = 0x00008000; /** * Listen for carrier network changes indicated by a carrier app. * * @see #onCarrierNetworkRequest * @see TelephonyManager#notifyCarrierNetworkChange(boolean) * @hide */ public static final int LISTEN_CARRIER_NETWORK_CHANGE = 0x00010000; /** * Listen 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 * {@more} * Example: TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED indicates voice service has been * fully activated * * @see #onVoiceActivationStateChanged * @hide */ @SystemApi public static final int LISTEN_VOICE_ACTIVATION_STATE = 0x00020000; /** * Listen 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 * {@more} * Example: TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED indicates data service has been * fully activated * * @see #onDataActivationStateChanged * @hide */ public static final int LISTEN_DATA_ACTIVATION_STATE = 0x00040000; /** * Listen for changes to the user mobile data state * * @see #onUserMobileDataStateChanged */ public static final int LISTEN_USER_MOBILE_DATA_STATE = 0x00080000; /** * Listen for changes to the physical channel configuration. * * @see #onPhysicalChannelConfigurationChanged * @hide */ public static final int LISTEN_PHYSICAL_CHANNEL_CONFIGURATION = 0x00100000; /** * Listen for changes to the phone capability. * * @see #onPhoneCapabilityChanged * @hide */ public static final int LISTEN_PHONE_CAPABILITY_CHANGE = 0x00200000; /** * Listen for changes to active data subId. 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. * * Requires Permission: No permission is required to listen, but notification requires * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} or the calling * app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}) * on any active subscription. * * @see #onActiveDataSubscriptionIdChanged */ public static final int LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE = 0x00400000; /** * Listen for changes to the radio power state. * * @see #onRadioPowerStateChanged * @hide */ @SystemApi public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 0x00800000; /** * Listen 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 #onEmergencyNumberListChanged */ public static final int LISTEN_EMERGENCY_NUMBER_LIST = 0x01000000; /** * Listen for call disconnect causes which contains {@link DisconnectCause} and * {@link PreciseDisconnectCause}. * * @hide */ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE)) @SystemApi public static final int LISTEN_CALL_DISCONNECT_CAUSES = 0x02000000; /** * Listen for changes to the call attributes of a currently active call. * {@more} * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE * READ_PRECISE_PHONE_STATE} * * @see #onCallAttributesChanged * @hide */ @SystemApi public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 0x04000000; /** * Listen for IMS call disconnect causes which contains * {@link android.telephony.ims.ImsReasonInfo} * * @see #onImsCallDisconnectCauseChanged(ImsReasonInfo) * @hide */ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE)) @SystemApi public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 0x08000000; /* * Subscription used to listen to the phone state changes * @hide */ /** @hide */ @UnsupportedAppUsage protected Integer mSubId; /** * @hide */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) @UnsupportedAppUsage public final IPhoneStateListener callback; /** * Create a PhoneStateListener for the Phone with the default subscription. * This class requires Looper.myLooper() not return null. */ public PhoneStateListener() { this(null, Looper.myLooper()); } /** * Create a PhoneStateListener for the Phone with the default subscription * using a particular non-null Looper. * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public PhoneStateListener(Looper looper) { this(null, looper); } /** * Create a PhoneStateListener for the Phone using the specified subscription. * This class requires Looper.myLooper() not return null. To supply your * own non-null Looper use PhoneStateListener(int subId, Looper looper) below. * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public PhoneStateListener(Integer subId) { this(subId, Looper.myLooper()); } /** * Create a PhoneStateListener for the Phone using the specified subscription * and non-null Looper. * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public PhoneStateListener(Integer subId, Looper looper) { this(subId, new HandlerExecutor(new Handler(looper))); } /** * Create a PhoneStateListener for the Phone using the specified Executor * * <p>Create a PhoneStateListener with a specified Executor for handling necessary callbacks. * The Executor must not be null. * * @param executor a non-null Executor that will execute callbacks for the PhoneStateListener. */ public PhoneStateListener(@NonNull Executor executor) { this(null, executor); } private PhoneStateListener(Integer subId, Executor e) { if (e == null) { throw new IllegalArgumentException("PhoneStateListener Executor must be non-null"); } mSubId = subId; callback = new IPhoneStateListenerStub(this, e); } /** * Callback invoked when device service state changes on the registered subscription. * Note, the registration subId comes from {@link TelephonyManager} object which registers * 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()}. * * @see ServiceState#STATE_EMERGENCY_ONLY * @see ServiceState#STATE_IN_SERVICE * @see ServiceState#STATE_OUT_OF_SERVICE * @see ServiceState#STATE_POWER_OFF */ public void onServiceStateChanged(ServiceState serviceState) { // default implementation empty } /** * Callback invoked when network signal strength changes on the registered subscription. * Note, the registration subId comes from {@link TelephonyManager} object which registers * 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()}. * * @see ServiceState#STATE_EMERGENCY_ONLY * @see ServiceState#STATE_IN_SERVICE * @see ServiceState#STATE_OUT_OF_SERVICE * @see ServiceState#STATE_POWER_OFF * @deprecated Use {@link #onSignalStrengthsChanged(SignalStrength)} */ @Deprecated public void onSignalStrengthChanged(int asu) { // default implementation empty } /** * Callback invoked when the message-waiting indicator changes on the registered subscription. * Note, the registration subId comes from {@link TelephonyManager} object which registers * 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()}. */ public void onMessageWaitingIndicatorChanged(boolean mwi) { // default implementation empty } /** * Callback invoked when the call-forwarding indicator changes on the registered subscription. * Note, the registration subId comes from {@link TelephonyManager} object which registers * 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()}. */ public void onCallForwardingIndicatorChanged(boolean cfi) { // default implementation empty } /** * Callback invoked when device cell location changes on the registered subscription. * Note, the registration subId comes from {@link TelephonyManager} object which registers * 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()}. */ public void onCellLocationChanged(CellLocation location) { // default implementation empty } /** * Callback invoked when device call state changes. * <p> * Reports the state of Telephony (mobile) calls on the device for the registered subscription. * <p> * Note: the registration subId comes from {@link TelephonyManager} object which registers * 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()}. * <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 READ_CALL_LOG} permission or carrier * privileges (see {@link TelephonyManager#hasCarrierPrivileges}), an empty string will be * passed as an argument. */ public void onCallStateChanged(@TelephonyManager.CallState int state, String phoneNumber) { // default implementation empty } /** * Callback invoked when connection state changes on the registered subscription. * Note, the registration subId comes from {@link TelephonyManager} object which registers * 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()}. * * @see TelephonyManager#DATA_DISCONNECTED * @see TelephonyManager#DATA_CONNECTING * @see TelephonyManager#DATA_CONNECTED * @see TelephonyManager#DATA_SUSPENDED */ public void onDataConnectionStateChanged(int state) { // default implementation empty } /** * same as above, but with the network type. Both called. */ public void onDataConnectionStateChanged(int state, int networkType) { } /** * Callback invoked when data activity state changes on the registered subscription. * Note, the registration subId comes from {@link TelephonyManager} object which registers * 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()}. * * @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 */ public void onDataActivity(int direction) { // default implementation empty } /** * Callback invoked when network signal strengths changes on the registered subscription. * Note, the registration subId comes from {@link TelephonyManager} object which registers * 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()}. */ public void onSignalStrengthsChanged(SignalStrength signalStrength) { // default implementation empty } /** * The Over The Air Service Provisioning (OTASP) has changed on the registered subscription. * Note, the registration subId comes from {@link TelephonyManager} object which registers * 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()}. * * Requires the READ_PHONE_STATE permission. * @param otaspMode is integer <code>OTASP_UNKNOWN=1<code> * means the value is currently unknown and the system should wait until * <code>OTASP_NEEDED=2<code> or <code>OTASP_NOT_NEEDED=3<code> is received before * making the decision to perform OTASP or not. * * @hide */ @UnsupportedAppUsage public void onOtaspChanged(int otaspMode) { // default implementation empty } /** * Callback invoked when a observed cell info has changed or new cells have been added * or removed on the registered subscription. * Note, the registration subId s from {@link TelephonyManager} object which registers * 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()}. * * @param cellInfo is the list of currently visible cells. */ public void onCellInfoChanged(List<CellInfo> cellInfo) { } /** * Callback invoked when precise device call state changes on the registered subscription. * Note, the registration subId comes from {@link TelephonyManager} object which registers * 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()}. * @param callState {@link PreciseCallState} * @hide */ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE)) @SystemApi public void onPreciseCallStateChanged(@NonNull PreciseCallState callState) { // default implementation empty } /** * Callback invoked when call disconnect cause changes on the registered subscription. * Note, the registration subId comes from {@link TelephonyManager} object which registers * 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()}. * * @param disconnectCause {@link DisconnectCause}. * @param preciseDisconnectCause {@link PreciseDisconnectCause}. * * @hide */ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE)) @SystemApi public void onCallDisconnectCauseChanged(int disconnectCause, int preciseDisconnectCause) { // default implementation empty } /** * Callback invoked when Ims call disconnect cause changes on the registered subscription. * Note, the registration subId comes from {@link TelephonyManager} object which registers * 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()}. * * @param imsReasonInfo {@link ImsReasonInfo} contains details on why IMS call failed. * * @hide */ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE)) @SystemApi public void onImsCallDisconnectCauseChanged(@NonNull ImsReasonInfo imsReasonInfo) { // default implementation empty } /** * Callback invoked when data connection state changes with precise information * on the registered subscription. * Note, the registration subId comes from {@link TelephonyManager} object which registers * 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()}. * * @param dataConnectionState {@link PreciseDataConnectionState} * * @hide */ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE)) @SystemApi public void onPreciseDataConnectionStateChanged(@NonNull PreciseDataConnectionState dataConnectionState) { // default implementation empty } /** * Callback invoked when data connection real time info changes on the registered subscription. * Note, the registration subId comes from {@link TelephonyManager} object which registers * 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()}. * * @hide */ @UnsupportedAppUsage public void onDataConnectionRealTimeInfoChanged(DataConnectionRealTimeInfo dcRtInfo) { // default implementation empty } /** * 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 subId comes from {@link TelephonyManager} object which registers * 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()}. * * @hide */ @SystemApi public void onSrvccStateChanged(@TelephonyManager.SrvccState int srvccState) { } /** * Callback invoked when the SIM voice activation state has changed on the registered * subscription. * Note, the registration subId comes from {@link TelephonyManager} object which registers * 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()}. * * @param state is the current SIM voice activation state * @hide */ @SystemApi public void onVoiceActivationStateChanged(@TelephonyManager.SimActivationState int state) { } /** * Callback invoked when the SIM data activation state has changed on the registered * subscription. * Note, the registration subId comes from {@link TelephonyManager} object which registers * 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()}. * * @param state is the current SIM data activation state * @hide */ public void onDataActivationStateChanged(@TelephonyManager.SimActivationState int state) { } /** * Callback invoked when the user mobile data state has changed on the registered subscription. * Note, the registration subId comes from {@link TelephonyManager} object which registers * 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()}. * * @param enabled indicates whether the current user mobile data state is enabled or disabled. */ public void onUserMobileDataStateChanged(boolean enabled) { // default implementation empty } /** * Callback invoked when the current physical channel configuration has changed on the * registered subscription. * Note, the registration subId comes from {@link TelephonyManager} object which registers * 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()}. * * @param configs List of the current {@link PhysicalChannelConfig}s * @hide */ public void onPhysicalChannelConfigurationChanged(@NonNull List<PhysicalChannelConfig> configs) { // default implementation empty } /** * Callback invoked when the current emergency number list has changed on the registered * subscription. * Note, the registration subId comes from {@link TelephonyManager} object which registers * 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()}. * * @param emergencyNumberList Map including the key as the active subscription ID * (Note: if there is no active subscription, the key is * {@link SubscriptionManager#getDefaultSubscriptionId}) * and the value as the list of {@link EmergencyNumber}; * null if this information is not available. * @hide */ public void onEmergencyNumberListChanged(@NonNull Map<Integer, List<EmergencyNumber>> emergencyNumberList) { // default implementation empty } /** * 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)}. * 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()}. * * Requires the READ_PRIVILEGED_PHONE_STATE permission. * @param rawData is the byte array of the OEM hook raw data. * @hide */ @UnsupportedAppUsage public void onOemHookRawEvent(byte[] rawData) { // default implementation empty } /** * Callback invoked when phone capability changes. * Note, this callback triggers regardless of registered subscription. * * Requires the READ_PRIVILEGED_PHONE_STATE permission. * @param capability the new phone capability * @hide */ public void onPhoneCapabilityChanged(PhoneCapability capability) { // default implementation empty } /** * Callback invoked when active data subId changes. * Note, this callback triggers regardless of registered subscription. * * Requires the READ_PHONE_STATE permission. * @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. */ public void onActiveDataSubscriptionIdChanged(int subId) { // default implementation empty } /** * Callback invoked when the call attributes changes on the registered subscription. * Note, the registration subId comes from {@link TelephonyManager} object which registers * 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()}. * * Requires the READ_PRIVILEGED_PHONE_STATE permission. * @param callAttributes the call attributes * @hide */ @SystemApi public void onCallAttributesChanged(@NonNull CallAttributes callAttributes) { // default implementation empty } /** * Callback invoked when modem radio power state changes on the registered subscription. * Note, the registration subId comes from {@link TelephonyManager} object which registers * 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()}. * * Requires * the READ_PRIVILEGED_PHONE_STATE permission. * @param state the modem radio power state * @hide */ @SystemApi public void onRadioPowerStateChanged(@TelephonyManager.RadioPowerState int state) { // default implementation empty } /** * 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.telephony.TelephonyManager#notifyCarrierNetworkChange(boolean)} * * 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 Whether the carrier network change is or shortly * will be active. This value is true to indicate * showing alternative UI and false to stop. * * @hide */ public void onCarrierNetworkChange(boolean active) { // default implementation empty } /** * The callback methods need to be called on the handler thread where * this object was created. If the binder did that for us it'd be nice. * * Using a static class and weak reference here to avoid memory leak caused by the * IPhoneStateListener.Stub callback retaining references to the outside PhoneStateListeners: * even caller has been destroyed and "un-registered" the PhoneStateListener, it is still not * eligible for GC given the references coming from: * Native Stack --> PhoneStateListener --> Context (Activity). * memory of caller's context will be collected after GC from service side get triggered */ private static class IPhoneStateListenerStub extends IPhoneStateListener.Stub { private WeakReference<PhoneStateListener> mPhoneStateListenerWeakRef; private Executor mExecutor; IPhoneStateListenerStub(PhoneStateListener phoneStateListener, Executor executor) { mPhoneStateListenerWeakRef = new WeakReference<PhoneStateListener>(phoneStateListener); mExecutor = executor; } public void onServiceStateChanged(ServiceState serviceState) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> psl.onServiceStateChanged(serviceState))); } public void onSignalStrengthChanged(int asu) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> psl.onSignalStrengthChanged(asu))); } public void onMessageWaitingIndicatorChanged(boolean mwi) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity( () -> mExecutor.execute(() -> psl.onMessageWaitingIndicatorChanged(mwi))); } public void onCallForwardingIndicatorChanged(boolean cfi) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity( () -> mExecutor.execute(() -> psl.onCallForwardingIndicatorChanged(cfi))); } public void onCellLocationChanged(Bundle bundle) { CellLocation location = CellLocation.newFromBundle(bundle); PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> psl.onCellLocationChanged(location))); } public void onCallStateChanged(int state, String incomingNumber) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity( () -> mExecutor.execute(() -> psl.onCallStateChanged(state, incomingNumber))); } public void onDataConnectionStateChanged(int state, int networkType) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> { psl.onDataConnectionStateChanged(state, networkType); psl.onDataConnectionStateChanged(state); })); } public void onDataActivity(int direction) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> psl.onDataActivity(direction))); } public void onSignalStrengthsChanged(SignalStrength signalStrength) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity( () -> mExecutor.execute(() -> psl.onSignalStrengthsChanged(signalStrength))); } public void onOtaspChanged(int otaspMode) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> psl.onOtaspChanged(otaspMode))); } public void onCellInfoChanged(List<CellInfo> cellInfo) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> psl.onCellInfoChanged(cellInfo))); } public void onPreciseCallStateChanged(PreciseCallState callState) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity( () -> mExecutor.execute(() -> psl.onPreciseCallStateChanged(callState))); } public void onCallDisconnectCauseChanged(int disconnectCause, int preciseDisconnectCause) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity(() -> mExecutor .execute(() -> psl.onCallDisconnectCauseChanged(disconnectCause, preciseDisconnectCause))); } public void onPreciseDataConnectionStateChanged(PreciseDataConnectionState dataConnectionState) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity( () -> mExecutor.execute(() -> psl.onPreciseDataConnectionStateChanged(dataConnectionState))); } public void onDataConnectionRealTimeInfoChanged(DataConnectionRealTimeInfo dcRtInfo) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity( () -> mExecutor.execute(() -> psl.onDataConnectionRealTimeInfoChanged(dcRtInfo))); } public void onSrvccStateChanged(int state) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> psl.onSrvccStateChanged(state))); } public void onVoiceActivationStateChanged(int activationState) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity( () -> mExecutor.execute(() -> psl.onVoiceActivationStateChanged(activationState))); } public void onDataActivationStateChanged(int activationState) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity( () -> mExecutor.execute(() -> psl.onDataActivationStateChanged(activationState))); } public void onUserMobileDataStateChanged(boolean enabled) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity( () -> mExecutor.execute(() -> psl.onUserMobileDataStateChanged(enabled))); } public void onOemHookRawEvent(byte[] rawData) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> psl.onOemHookRawEvent(rawData))); } public void onCarrierNetworkChange(boolean active) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> psl.onCarrierNetworkChange(active))); } public void onPhysicalChannelConfigurationChanged(List<PhysicalChannelConfig> configs) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity( () -> mExecutor.execute(() -> psl.onPhysicalChannelConfigurationChanged(configs))); } @Override public void onEmergencyNumberListChanged(Map emergencyNumberList) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity( () -> mExecutor.execute(() -> psl.onEmergencyNumberListChanged(emergencyNumberList))); } public void onPhoneCapabilityChanged(PhoneCapability capability) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity( () -> mExecutor.execute(() -> psl.onPhoneCapabilityChanged(capability))); } public void onRadioPowerStateChanged(@TelephonyManager.RadioPowerState int state) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> psl.onRadioPowerStateChanged(state))); } public void onCallAttributesChanged(CallAttributes callAttributes) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity( () -> mExecutor.execute(() -> psl.onCallAttributesChanged(callAttributes))); } public void onActiveDataSubIdChanged(int subId) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity( () -> mExecutor.execute(() -> psl.onActiveDataSubscriptionIdChanged(subId))); } public void onImsCallDisconnectCauseChanged(ImsReasonInfo disconnectCause) { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; Binder.withCleanCallingIdentity( () -> mExecutor.execute(() -> psl.onImsCallDisconnectCauseChanged(disconnectCause))); } } private void log(String s) { Rlog.d(LOG_TAG, s); } }