diff options
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/app/SystemServiceRegistry.java | 4 | ||||
| -rw-r--r-- | core/java/android/content/Context.java | 3 | ||||
| -rw-r--r-- | core/java/android/service/carrier/CarrierService.java | 2 | ||||
| -rw-r--r-- | core/java/android/telephony/PhoneStateListener.java | 1279 | ||||
| -rw-r--r-- | core/java/android/telephony/TelephonyRegistryManager.java (renamed from core/java/android/os/telephony/TelephonyRegistryManager.java) | 179 |
5 files changed, 1458 insertions, 9 deletions
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 0f5d6a30bc31..0fa8fa8c752e 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -157,7 +157,7 @@ import android.os.health.SystemHealthManager; import android.os.image.DynamicSystemManager; import android.os.image.IDynamicSystemService; import android.os.storage.StorageManager; -import android.os.telephony.TelephonyRegistryManager; +import android.telephony.TelephonyRegistryManager; import android.permission.PermissionControllerManager; import android.permission.PermissionManager; import android.print.IPrintManager; @@ -611,7 +611,7 @@ final class SystemServiceRegistry { new CachedServiceFetcher<TelephonyRegistryManager>() { @Override public TelephonyRegistryManager createService(ContextImpl ctx) { - return new TelephonyRegistryManager(); + return new TelephonyRegistryManager(ctx); }}); registerService(Context.TELEPHONY_SUBSCRIPTION_SERVICE, SubscriptionManager.class, diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index bb96ed265e6b..aca8f5d8a4e2 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -63,6 +63,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.storage.StorageManager; import android.provider.MediaStore; +import android.telephony.TelephonyRegistryManager; import android.util.AttributeSet; import android.view.Display; import android.view.DisplayAdjustments; @@ -4755,7 +4756,7 @@ public abstract class Context { /** * Use with {@link #getSystemService(String)} to retrieve an - * {@link android.os.telephony.TelephonyRegistryManager}. + * {@link TelephonyRegistryManager}. * @hide */ @SystemApi diff --git a/core/java/android/service/carrier/CarrierService.java b/core/java/android/service/carrier/CarrierService.java index 9184d6d51f44..eefc1b70bac9 100644 --- a/core/java/android/service/carrier/CarrierService.java +++ b/core/java/android/service/carrier/CarrierService.java @@ -22,7 +22,7 @@ import android.os.Bundle; import android.os.IBinder; import android.os.PersistableBundle; import android.os.ResultReceiver; -import android.os.telephony.TelephonyRegistryManager; +import android.telephony.TelephonyRegistryManager; import android.util.Log; /** diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java new file mode 100644 index 000000000000..2af827e36696 --- /dev/null +++ b/core/java/android/telephony/PhoneStateListener.java @@ -0,0 +1,1279 @@ +/* + * 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.TestApi; +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.Annotation.CallState; +import android.telephony.Annotation.RadioPowerState; +import android.telephony.Annotation.SimActivationState; +import android.telephony.Annotation.SrvccState; +import android.telephony.emergency.EmergencyNumber; +import android.telephony.ims.ImsReasonInfo; + +import com.android.internal.telephony.IPhoneStateListener; +import com.android.internal.annotations.VisibleForTesting; + +import dalvik.system.VMRuntime; + +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. + * + * @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; + + /** + * Listen for the emergency number placed from an outgoing call. + * + * <p>Requires permission {@link android.Manifest.permission#READ_ACTIVE_EMERGENCY_SESSION} + * + * @see #onOutgoingEmergencyCall + * @hide + */ + @SystemApi + @TestApi + @RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) + public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 0x10000000; + + /** + * Listen for the emergency number placed from an outgoing SMS. + * + * <p>Requires permission {@link android.Manifest.permission#READ_ACTIVE_EMERGENCY_SESSION} + * + * @see #onOutgoingEmergencySms + * @hide + */ + @SystemApi + @TestApi + @RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) + public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 0x20000000; + + /* + * 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()); + if (subId != null && VMRuntime.getRuntime().getTargetSdkVersion() + >= Build.VERSION_CODES.Q) { + throw new IllegalArgumentException("PhoneStateListener with subId: " + + subId + " is not supported, use default constructor"); + } + } + /** + * 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))); + if (subId != null && VMRuntime.getRuntime().getTargetSdkVersion() + >= Build.VERSION_CODES.Q) { + throw new IllegalArgumentException("PhoneStateListener with subId: " + + subId + " is not supported, use default constructor"); + } + } + + /** + * 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(@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(@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(@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(@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 an outgoing call is placed to an emergency number. + * + * @param placedEmergencyNumber the emergency number {@link EmergencyNumber} the call is placed + * to. + * @hide + */ + @SystemApi + @TestApi + public void onOutgoingEmergencyCall(@NonNull EmergencyNumber placedEmergencyNumber) { + // default implementation empty + } + + /** + * Callback invoked when an outgoing SMS is placed to an emergency number. + * + * @param sentEmergencyNumber the emergency number {@link EmergencyNumber} the SMS is sent to. + * @hide + */ + @SystemApi + @TestApi + public void onOutgoingEmergencySms(@NonNull EmergencyNumber sentEmergencyNumber) { + // 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(@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))); + } + + public void onEmergencyNumberListChanged(Map emergencyNumberList) { + PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); + if (psl == null) return; + + Binder.withCleanCallingIdentity( + () -> mExecutor.execute( + () -> psl.onEmergencyNumberListChanged(emergencyNumberList))); + } + + public void onOutgoingEmergencyCall(@NonNull EmergencyNumber placedEmergencyNumber) { + PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); + if (psl == null) return; + + Binder.withCleanCallingIdentity( + () -> mExecutor.execute( + () -> psl.onOutgoingEmergencyCall(placedEmergencyNumber))); + } + + public void onOutgoingEmergencySms(@NonNull EmergencyNumber sentEmergencyNumber) { + PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); + if (psl == null) return; + + Binder.withCleanCallingIdentity( + () -> mExecutor.execute( + () -> psl.onOutgoingEmergencySms(sentEmergencyNumber))); + } + + public void onPhoneCapabilityChanged(PhoneCapability capability) { + PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); + if (psl == null) return; + + Binder.withCleanCallingIdentity( + () -> mExecutor.execute(() -> psl.onPhoneCapabilityChanged(capability))); + } + + public void onRadioPowerStateChanged(@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); + } +} diff --git a/core/java/android/os/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java index b67409988da0..456789fb77bc 100644 --- a/core/java/android/os/telephony/TelephonyRegistryManager.java +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -13,12 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package android.os.telephony; +package android.telephony; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.SystemApi; +import android.annotation.TestApi; +import android.content.Context; import android.net.LinkProperties; import android.net.NetworkCapabilities; +import android.os.Binder; import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerExecutor; import android.os.RemoteException; import android.os.ServiceManager; import android.telephony.Annotation; @@ -41,8 +49,15 @@ import android.telephony.SignalStrength; import android.telephony.TelephonyManager; import android.telephony.data.ApnSetting; import android.telephony.ims.ImsReasonInfo; +import android.util.Log; + +import com.android.internal.telephony.IOnSubscriptionsChangedListener; import com.android.internal.telephony.ITelephonyRegistry; + +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.concurrent.Executor; /** * A centralized place to notify telephony related status changes, e.g, {@link ServiceState} update @@ -59,9 +74,26 @@ public class TelephonyRegistryManager { private static final String TAG = "TelephonyRegistryManager"; private static ITelephonyRegistry sRegistry; + private final Context mContext; + + /** + * A mapping between {@link SubscriptionManager.OnSubscriptionsChangedListener} and + * its callback IOnSubscriptionsChangedListener. + */ + private final Map<SubscriptionManager.OnSubscriptionsChangedListener, + IOnSubscriptionsChangedListener> mSubscriptionChangedListenerMap = new HashMap<>(); + /** + * A mapping between {@link SubscriptionManager.OnOpportunisticSubscriptionsChangedListener} and + * its callback IOnSubscriptionsChangedListener. + */ + private final Map<SubscriptionManager.OnOpportunisticSubscriptionsChangedListener, + IOnSubscriptionsChangedListener> mOpportunisticSubscriptionChangedListenerMap + = new HashMap<>(); + /** @hide **/ - public TelephonyRegistryManager() { + public TelephonyRegistryManager(@NonNull Context context) { + mContext = context; if (sRegistry == null) { sRegistry = ITelephonyRegistry.Stub.asInterface( ServiceManager.getService("telephony.registry")); @@ -69,6 +101,113 @@ public class TelephonyRegistryManager { } /** + * Register for changes to the list of active {@link SubscriptionInfo} records or to the + * individual records themselves. When a change occurs the onSubscriptionsChanged method of + * the listener will be invoked immediately if there has been a notification. The + * onSubscriptionChanged method will also be triggered once initially when calling this + * function. + * + * @param listener an instance of {@link SubscriptionManager.OnSubscriptionsChangedListener} + * with onSubscriptionsChanged overridden. + * @param executor the executor that will execute callbacks. + */ + public void addOnSubscriptionsChangedListener( + @NonNull SubscriptionManager.OnSubscriptionsChangedListener listener, + @NonNull Executor executor) { + IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() { + @Override + public void onSubscriptionsChanged () { + Log.d(TAG, "onSubscriptionsChangedListener callback received."); + executor.execute(() -> listener.onSubscriptionsChanged()); + } + }; + mSubscriptionChangedListenerMap.put(listener, callback); + try { + sRegistry.addOnSubscriptionsChangedListener(mContext.getOpPackageName(), callback); + } catch (RemoteException ex) { + // system server crash + } + } + + /** + * Unregister the {@link SubscriptionManager.OnSubscriptionsChangedListener}. This is not + * strictly necessary as the listener will automatically be unregistered if an attempt to + * invoke the listener fails. + * + * @param listener that is to be unregistered. + */ + public void removeOnSubscriptionsChangedListener( + @NonNull SubscriptionManager.OnSubscriptionsChangedListener listener) { + if (mSubscriptionChangedListenerMap.get(listener) == null) { + return; + } + try { + sRegistry.removeOnSubscriptionsChangedListener(mContext.getOpPackageName(), + mSubscriptionChangedListenerMap.get(listener)); + mSubscriptionChangedListenerMap.remove(listener); + } catch (RemoteException ex) { + // system server crash + } + } + + /** + * Register for changes to the list of opportunistic subscription records or to the + * individual records themselves. When a change occurs the onOpportunisticSubscriptionsChanged + * method of the listener will be invoked immediately if there has been a notification. + * + * @param listener an instance of + * {@link SubscriptionManager.OnOpportunisticSubscriptionsChangedListener} with + * onOpportunisticSubscriptionsChanged overridden. + * @param executor an Executor that will execute callbacks. + */ + public void addOnOpportunisticSubscriptionsChangedListener( + @NonNull SubscriptionManager.OnOpportunisticSubscriptionsChangedListener listener, + @NonNull Executor executor) { + /** + * The callback methods need to be called on the executor thread where + * this object was created. If the binder did that for us it'd be nice. + */ + IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() { + @Override + public void onSubscriptionsChanged() { + final long identity = Binder.clearCallingIdentity(); + try { + Log.d(TAG, "onOpportunisticSubscriptionsChanged callback received."); + executor.execute(() -> listener.onOpportunisticSubscriptionsChanged()); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + }; + mOpportunisticSubscriptionChangedListenerMap.put(listener, callback); + try { + sRegistry.addOnOpportunisticSubscriptionsChangedListener(mContext.getOpPackageName(), + callback); + } catch (RemoteException ex) { + // system server crash + } + } + + /** + * Unregister the {@link SubscriptionManager.OnOpportunisticSubscriptionsChangedListener} + * that is currently listening opportunistic subscriptions change. This is not strictly + * necessary as the listener will automatically be unregistered if an attempt to invoke the + * listener fails. + * + * @param listener that is to be unregistered. + */ + public void removeOnOpportunisticSubscriptionsChangedListener( + @NonNull SubscriptionManager.OnOpportunisticSubscriptionsChangedListener listener) { + try { + sRegistry.removeOnSubscriptionsChangedListener(mContext.getOpPackageName(), + mOpportunisticSubscriptionChangedListenerMap.get(listener)); + mOpportunisticSubscriptionChangedListenerMap.remove(listener); + } catch (RemoteException ex) { + // system server crash + } + } + + /** * Informs the system of an intentional upcoming carrier network change by a carrier app. * This call 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. @@ -98,14 +237,33 @@ public class TelephonyRegistryManager { * @param slotIndex for which call state changed. Can be derived from subId except when subId is * invalid. * @param state latest call state. e.g, offhook, ringing - * @param incomingNumer incoming phone number. + * @param incomingNumber incoming phone number. * * @hide */ public void notifyCallStateChanged(int subId, int slotIndex, @CallState int state, - String incomingNumer) { + String incomingNumber) { try { - sRegistry.notifyCallState(slotIndex, subId, state, incomingNumer); + sRegistry.notifyCallState(slotIndex, subId, state, incomingNumber); + } catch (RemoteException ex) { + // system server crash + } + } + + /** + * Notify call state changed on all subscriptions. + * + * @param state latest call state. e.g, offhook, ringing + * @param incomingNumber incoming phone number. + * @hide + */ + @SystemApi + @TestApi + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public void notifyCallStateChangedForAllSubscriptions(@CallState int state, + @Nullable String incomingNumber) { + try { + sRegistry.notifyCallStateForAllSubs(state, incomingNumber); } catch (RemoteException ex) { // system server crash } @@ -545,4 +703,15 @@ public class TelephonyRegistryManager { } } + /** + * @param activeDataSubId + * @hide + */ + public void notifyActiveDataSubIdChanged(int activeDataSubId) { + try { + sRegistry.notifyActiveDataSubIdChanged(activeDataSubId); + } catch (RemoteException ex) { + + } + } } |
