1726 lines
71 KiB
Java
1726 lines
71 KiB
Java
/*
|
|
* Copyright (C) 2019 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
package android.telephony;
|
|
|
|
import android.annotation.CallbackExecutor;
|
|
import android.annotation.FlaggedApi;
|
|
import android.annotation.NonNull;
|
|
import android.annotation.Nullable;
|
|
import android.annotation.RequiresFeature;
|
|
import android.annotation.RequiresPermission;
|
|
import android.annotation.SystemApi;
|
|
import android.annotation.SystemService;
|
|
import android.compat.Compatibility;
|
|
import android.compat.annotation.ChangeId;
|
|
import android.compat.annotation.EnabledAfter;
|
|
import android.content.Context;
|
|
import android.content.pm.PackageManager;
|
|
import android.os.Binder;
|
|
import android.os.Build;
|
|
import android.os.RemoteException;
|
|
import android.os.ServiceManager;
|
|
import android.service.carrier.CarrierService;
|
|
import android.telephony.Annotation.CallState;
|
|
import android.telephony.Annotation.DataActivityType;
|
|
import android.telephony.Annotation.DisconnectCauses;
|
|
import android.telephony.Annotation.NetworkType;
|
|
import android.telephony.Annotation.PreciseDisconnectCauses;
|
|
import android.telephony.Annotation.RadioPowerState;
|
|
import android.telephony.Annotation.SimActivationState;
|
|
import android.telephony.Annotation.SrvccState;
|
|
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
|
|
import android.telephony.TelephonyManager.CarrierPrivilegesCallback;
|
|
import android.telephony.emergency.EmergencyNumber;
|
|
import android.telephony.ims.ImsCallSession;
|
|
import android.telephony.ims.ImsReasonInfo;
|
|
import android.telephony.ims.MediaQualityStatus;
|
|
import android.util.ArraySet;
|
|
import android.util.Log;
|
|
|
|
import com.android.internal.annotations.GuardedBy;
|
|
import com.android.internal.listeners.ListenerExecutor;
|
|
import com.android.internal.telephony.ICarrierConfigChangeListener;
|
|
import com.android.internal.telephony.ICarrierPrivilegesCallback;
|
|
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
|
|
import com.android.internal.telephony.ITelephonyRegistry;
|
|
import com.android.server.telecom.flags.Flags;
|
|
|
|
import java.lang.ref.WeakReference;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
import java.util.Objects;
|
|
import java.util.Set;
|
|
import java.util.WeakHashMap;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import java.util.concurrent.Executor;
|
|
import java.util.stream.Collectors;
|
|
|
|
/**
|
|
* A centralized place to notify telephony related status changes, e.g, {@link ServiceState} update
|
|
* or {@link PhoneCapability} changed. This might trigger callback from applications side through
|
|
* {@link android.telephony.PhoneStateListener}
|
|
*
|
|
* Limit API access to only carrier apps with certain permissions or apps running on
|
|
* privileged UID.
|
|
*
|
|
* TelephonyRegistryManager is intended for use on devices that implement
|
|
* {@link android.content.pm.PackageManager#FEATURE_TELEPHONY FEATURE_TELEPHONY}. On devices
|
|
* that do not implement this feature, the behavior is not reliable.
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@SystemService(Context.TELEPHONY_REGISTRY_SERVICE)
|
|
@RequiresFeature(PackageManager.FEATURE_TELEPHONY)
|
|
@FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES)
|
|
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 ConcurrentHashMap<SubscriptionManager.OnSubscriptionsChangedListener,
|
|
IOnSubscriptionsChangedListener>
|
|
mSubscriptionChangedListenerMap = new ConcurrentHashMap<>();
|
|
/**
|
|
* A mapping between {@link SubscriptionManager.OnOpportunisticSubscriptionsChangedListener} and
|
|
* its callback IOnSubscriptionsChangedListener.
|
|
*/
|
|
private final ConcurrentHashMap<SubscriptionManager.OnOpportunisticSubscriptionsChangedListener,
|
|
IOnSubscriptionsChangedListener>
|
|
mOpportunisticSubscriptionChangedListenerMap = new ConcurrentHashMap<>();
|
|
|
|
/**
|
|
* A mapping between {@link CarrierConfigManager.CarrierConfigChangeListener} and its callback
|
|
* ICarrierConfigChangeListener.
|
|
*/
|
|
private final ConcurrentHashMap<CarrierConfigManager.CarrierConfigChangeListener,
|
|
ICarrierConfigChangeListener>
|
|
mCarrierConfigChangeListenerMap = new ConcurrentHashMap<>();
|
|
|
|
|
|
/** @hide **/
|
|
public TelephonyRegistryManager(@NonNull Context context) {
|
|
mContext = context;
|
|
if (sRegistry == null) {
|
|
sRegistry = ITelephonyRegistry.Stub.asInterface(
|
|
ServiceManager.getService("telephony.registry"));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Register for changes to the list of {@link SubscriptionInfo} records or to the
|
|
* individual records (active or inactive) themselves. When a change occurs, the
|
|
* {@link OnSubscriptionsChangedListener#onSubscriptionsChanged()} method of
|
|
* the listener will be invoked immediately. The
|
|
* {@link OnSubscriptionsChangedListener#onSubscriptionsChanged()} method will also be invoked
|
|
* once initially when calling this method.
|
|
*
|
|
* @param listener an instance of {@link OnSubscriptionsChangedListener} with
|
|
* {@link OnSubscriptionsChangedListener#onSubscriptionsChanged()} overridden.
|
|
* @param executor the executor that will execute callbacks.
|
|
* @hide
|
|
*/
|
|
public void addOnSubscriptionsChangedListener(
|
|
@NonNull SubscriptionManager.OnSubscriptionsChangedListener listener,
|
|
@NonNull Executor executor) {
|
|
if (mSubscriptionChangedListenerMap.get(listener) != null) {
|
|
Log.d(TAG, "addOnSubscriptionsChangedListener listener already present");
|
|
return;
|
|
}
|
|
IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() {
|
|
@Override
|
|
public void onSubscriptionsChanged () {
|
|
final long identity = Binder.clearCallingIdentity();
|
|
try {
|
|
executor.execute(() -> listener.onSubscriptionsChanged());
|
|
} finally {
|
|
Binder.restoreCallingIdentity(identity);
|
|
}
|
|
}
|
|
};
|
|
mSubscriptionChangedListenerMap.put(listener, callback);
|
|
try {
|
|
sRegistry.addOnSubscriptionsChangedListener(mContext.getOpPackageName(),
|
|
mContext.getAttributionTag(), callback);
|
|
} catch (RemoteException ex) {
|
|
// system server crash
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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.
|
|
* @hide
|
|
*/
|
|
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
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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.
|
|
* @hide
|
|
*/
|
|
public void addOnOpportunisticSubscriptionsChangedListener(
|
|
@NonNull SubscriptionManager.OnOpportunisticSubscriptionsChangedListener listener,
|
|
@NonNull Executor executor) {
|
|
if (mOpportunisticSubscriptionChangedListenerMap.get(listener) != null) {
|
|
Log.d(TAG, "addOnOpportunisticSubscriptionsChangedListener listener already present");
|
|
return;
|
|
}
|
|
/**
|
|
* 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(),
|
|
mContext.getAttributionTag(), callback);
|
|
} catch (RemoteException ex) {
|
|
// system server crash
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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.
|
|
* @hide
|
|
*/
|
|
public void removeOnOpportunisticSubscriptionsChangedListener(
|
|
@NonNull SubscriptionManager.OnOpportunisticSubscriptionsChangedListener listener) {
|
|
if (mOpportunisticSubscriptionChangedListenerMap.get(listener) == null) {
|
|
return;
|
|
}
|
|
try {
|
|
sRegistry.removeOnSubscriptionsChangedListener(mContext.getOpPackageName(),
|
|
mOpportunisticSubscriptionChangedListenerMap.get(listener));
|
|
mOpportunisticSubscriptionChangedListenerMap.remove(listener);
|
|
} catch (RemoteException ex) {
|
|
// system server crash
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* To check the SDK version for {@code #listenFromListener}.
|
|
*/
|
|
@ChangeId
|
|
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.P)
|
|
private static final long LISTEN_CODE_CHANGE = 147600208L;
|
|
|
|
/**
|
|
* Listen for incoming subscriptions
|
|
* @param subId Subscription ID
|
|
* @param pkg Package name
|
|
* @param featureId Feature ID
|
|
* @param listener Listener providing callback
|
|
* @param events Events
|
|
* @param notifyNow Whether to notify instantly
|
|
* @hide
|
|
*/
|
|
public void listenFromListener(int subId, @NonNull boolean renounceFineLocationAccess,
|
|
@NonNull boolean renounceCoarseLocationAccess, @NonNull String pkg,
|
|
@NonNull String featureId, @NonNull PhoneStateListener listener,
|
|
@NonNull int events, boolean notifyNow) {
|
|
if (listener == null) {
|
|
throw new IllegalStateException("telephony service is null.");
|
|
}
|
|
|
|
try {
|
|
int[] eventsList = getEventsFromBitmask(events).stream().mapToInt(i -> i).toArray();
|
|
// subId from PhoneStateListener is deprecated Q on forward, use the subId from
|
|
// TelephonyManager instance. Keep using subId from PhoneStateListener for pre-Q.
|
|
if (Compatibility.isChangeEnabled(LISTEN_CODE_CHANGE)) {
|
|
// Since mSubId in PhoneStateListener is deprecated from Q on forward, this is
|
|
// the only place to set mSubId and its for "informational" only.
|
|
listener.mSubId = (eventsList.length == 0)
|
|
? SubscriptionManager.INVALID_SUBSCRIPTION_ID : subId;
|
|
} else if (listener.mSubId != null) {
|
|
subId = listener.mSubId;
|
|
}
|
|
sRegistry.listenWithEventList(renounceFineLocationAccess, renounceCoarseLocationAccess,
|
|
subId, pkg, featureId, listener.callback, eventsList, notifyNow);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Listen for incoming subscriptions
|
|
* @param subId Subscription ID
|
|
* @param pkg Package name
|
|
* @param featureId Feature ID
|
|
* @param telephonyCallback Listener providing callback
|
|
* @param events List events
|
|
* @param notifyNow Whether to notify instantly
|
|
*/
|
|
private void listenFromCallback(boolean renounceFineLocationAccess,
|
|
boolean renounceCoarseLocationAccess, int subId,
|
|
@NonNull String pkg, @NonNull String featureId,
|
|
@NonNull TelephonyCallback telephonyCallback, @NonNull int[] events,
|
|
boolean notifyNow) {
|
|
try {
|
|
sRegistry.listenWithEventList(renounceFineLocationAccess, renounceCoarseLocationAccess,
|
|
subId, pkg, featureId, telephonyCallback.callback, events, notifyNow);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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.
|
|
* <p>
|
|
* Based on the active parameter passed in, this method will either show or hide the alternative
|
|
* UI. There is no timeout associated with showing this UX, so a carrier app must be sure to
|
|
* call with active set to false sometime after calling with it set to {@code true}.
|
|
* <p>
|
|
* This will apply to all subscriptions the carrier app has carrier privileges on.
|
|
* <p>
|
|
* Requires Permission: calling app has carrier privileges.
|
|
*
|
|
* @param active Whether the carrier network change is or shortly will be
|
|
* active. Set this value to true to begin showing alternative UI and false to stop.
|
|
* @see TelephonyManager#hasCarrierPrivileges
|
|
* @hide
|
|
*/
|
|
public void notifyCarrierNetworkChange(boolean active) {
|
|
try {
|
|
sRegistry.notifyCarrierNetworkChange(active);
|
|
} catch (RemoteException ex) {
|
|
// system server crash
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Informs the system of an intentional upcoming carrier network change by a carrier app on the
|
|
* given {@code subscriptionId}. 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.
|
|
* <p>
|
|
* Based on the active parameter passed in, this method will either show or hide the
|
|
* alternative UI. There is no timeout associated with showing this UX, so a carrier app must be
|
|
* sure to call with active set to false sometime after calling with it set to {@code true}.
|
|
* <p>
|
|
* Requires Permission: calling app has carrier privileges.
|
|
*
|
|
* @param subscriptionId the subscription of the carrier network.
|
|
* @param active whether the carrier network change is or shortly will be active. Set this value
|
|
* to true to begin showing alternative UI and false to stop.
|
|
* @see TelephonyManager#hasCarrierPrivileges
|
|
* @hide
|
|
*/
|
|
public void notifyCarrierNetworkChange(int subscriptionId, boolean active) {
|
|
try {
|
|
sRegistry.notifyCarrierNetworkChangeWithSubId(subscriptionId, active);
|
|
} catch (RemoteException ex) {
|
|
// system server crash
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify call state changed on certain subscription.
|
|
*
|
|
* @param slotIndex for which call state changed. Can be derived from subId except when subId is
|
|
* invalid.
|
|
* @param subId for which call state changed.
|
|
* @param state latest call state. e.g, offhook, ringing
|
|
* @param incomingNumber incoming phone number.
|
|
* @hide
|
|
*/
|
|
public void notifyCallStateChanged(int slotIndex, int subId, @CallState int state,
|
|
@Nullable String incomingNumber) {
|
|
try {
|
|
sRegistry.notifyCallState(slotIndex, subId, state, incomingNumber);
|
|
} catch (RemoteException ex) {
|
|
// system server crash
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify call state changed on all subscriptions, excluding over-the-top VOIP calls (otherwise
|
|
* known as self-managed calls in the Android Platform).
|
|
*
|
|
* @param state latest call state. e.g, offhook, ringing
|
|
* @param incomingNumber incoming phone number or null in the case for OTT VOIP calls
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@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
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify {@link SubscriptionInfo} change.
|
|
* @hide
|
|
*/
|
|
public void notifySubscriptionInfoChanged() {
|
|
try {
|
|
sRegistry.notifySubscriptionInfoChanged();
|
|
} catch (RemoteException ex) {
|
|
// system server crash
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify opportunistic {@link SubscriptionInfo} change.
|
|
* @hide
|
|
*/
|
|
public void notifyOpportunisticSubscriptionInfoChanged() {
|
|
try {
|
|
sRegistry.notifyOpportunisticSubscriptionInfoChanged();
|
|
} catch (RemoteException ex) {
|
|
// system server crash
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify {@link ServiceState} update on certain subscription.
|
|
*
|
|
* @param slotIndex for which the service state changed. Can be derived from subId except
|
|
* subId is invalid.
|
|
* @param subId for which the service state changed.
|
|
* @param state service state e.g, in service, out of service or roaming status.
|
|
* @hide
|
|
*/
|
|
public void notifyServiceStateChanged(int slotIndex, int subId, @NonNull ServiceState state) {
|
|
try {
|
|
sRegistry.notifyServiceStateForPhoneId(slotIndex, subId, state);
|
|
} catch (RemoteException ex) {
|
|
// system server crash
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify {@link SignalStrength} update on certain subscription.
|
|
*
|
|
* @param slotIndex for which the signalstrength changed. Can be derived from subId except when
|
|
* subId is invalid.
|
|
* @param subId for which the signalstrength changed.
|
|
* @param signalStrength e.g, signalstrength level {@see SignalStrength#getLevel()}
|
|
* @hide
|
|
*/
|
|
public void notifySignalStrengthChanged(int slotIndex, int subId,
|
|
@NonNull SignalStrength signalStrength) {
|
|
try {
|
|
sRegistry.notifySignalStrengthForPhoneId(slotIndex, subId, signalStrength);
|
|
} catch (RemoteException ex) {
|
|
// system server crash
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify changes to the message-waiting indicator on certain subscription. e.g, The status bar
|
|
* uses message waiting indicator to determine when to display the voicemail icon.
|
|
*
|
|
* @param slotIndex for which message waiting indicator changed. Can be derived from subId
|
|
* except when subId is invalid.
|
|
* @param subId for which message waiting indicator changed.
|
|
* @param msgWaitingInd {@code true} indicates there is message-waiting indicator, {@code false}
|
|
* otherwise.
|
|
* @hide
|
|
*/
|
|
public void notifyMessageWaitingChanged(int slotIndex, int subId, boolean msgWaitingInd) {
|
|
try {
|
|
sRegistry.notifyMessageWaitingChangedForPhoneId(slotIndex, subId, msgWaitingInd);
|
|
} catch (RemoteException ex) {
|
|
// system process is dead
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify changes to the call-forwarding status on certain subscription.
|
|
*
|
|
* @param subId for which call forwarding status changed.
|
|
* @param callForwardInd {@code true} indicates there is call forwarding, {@code false}
|
|
* otherwise.
|
|
* @hide
|
|
*/
|
|
public void notifyCallForwardingChanged(int subId, boolean callForwardInd) {
|
|
try {
|
|
sRegistry.notifyCallForwardingChangedForSubscriber(subId, callForwardInd);
|
|
} catch (RemoteException ex) {
|
|
// system process is dead
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify changes to activity state changes on certain subscription.
|
|
*
|
|
* @param subId for which data activity state changed.
|
|
* @param dataActivityType indicates the latest data activity type e.g. {@link
|
|
* TelephonyManager#DATA_ACTIVITY_IN}
|
|
* @hide
|
|
*/
|
|
public void notifyDataActivityChanged(int subId, @DataActivityType int dataActivityType) {
|
|
try {
|
|
sRegistry.notifyDataActivityForSubscriber(subId, dataActivityType);
|
|
} catch (RemoteException ex) {
|
|
// system process is dead
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify changes to activity state changes on certain subscription.
|
|
*
|
|
* @param slotIndex for which data activity changed. Can be derived from subId except
|
|
* when subId is invalid.
|
|
* @param subId for which data activity state changed.
|
|
* @param dataActivityType indicates the latest data activity type e.g. {@link
|
|
* TelephonyManager#DATA_ACTIVITY_IN}
|
|
* @hide
|
|
*/
|
|
public void notifyDataActivityChanged(int slotIndex, int subId,
|
|
@DataActivityType int dataActivityType) {
|
|
try {
|
|
sRegistry.notifyDataActivityForSubscriberWithSlot(slotIndex, subId, dataActivityType);
|
|
} catch (RemoteException ex) {
|
|
// system process is dead
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify changes to default (Internet) data connection state on certain subscription.
|
|
*
|
|
* @param slotIndex for which data connections state changed. Can be derived from subId except
|
|
* when subId is invalid.
|
|
* @param subId for which data connection state changed.
|
|
* @param preciseState the PreciseDataConnectionState
|
|
*
|
|
* @see PreciseDataConnectionState
|
|
* @see TelephonyManager#DATA_DISCONNECTED
|
|
* @hide
|
|
*/
|
|
public void notifyDataConnectionForSubscriber(int slotIndex, int subId,
|
|
@NonNull PreciseDataConnectionState preciseState) {
|
|
try {
|
|
sRegistry.notifyDataConnectionForSubscriber(
|
|
slotIndex, subId, preciseState);
|
|
} catch (RemoteException ex) {
|
|
// system process is dead
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify {@link CallQuality} change on certain subscription.
|
|
*
|
|
* @param slotIndex for which call quality state changed. Can be derived from subId except when
|
|
* subId is invalid.
|
|
* @param subId for which call quality state changed.
|
|
* @param callQuality Information about call quality e.g, call quality level
|
|
* @param networkType associated with this data connection. e.g, LTE
|
|
* @hide
|
|
*/
|
|
public void notifyCallQualityChanged(int slotIndex, int subId, @NonNull CallQuality callQuality,
|
|
@NetworkType int networkType) {
|
|
try {
|
|
sRegistry.notifyCallQualityChanged(callQuality, slotIndex, subId, networkType);
|
|
} catch (RemoteException ex) {
|
|
// system process is dead
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify change of media quality status {@link MediaQualityStatus} crosses media quality
|
|
* threshold
|
|
* <p/>
|
|
* Currently thresholds for this indication can be configurable by CARRIER_CONFIG
|
|
* {@link CarrierConfigManager#KEY_VOICE_RTP_THRESHOLDS_PACKET_LOSS_RATE_INT}
|
|
* {@link CarrierConfigManager#KEY_VOICE_RTP_THRESHOLDS_INACTIVITY_TIME_IN_MILLIS_INT}
|
|
* {@link CarrierConfigManager#KEY_VOICE_RTP_THRESHOLDS_JITTER_INT}
|
|
*
|
|
* @param status media quality status
|
|
* @hide
|
|
*/
|
|
public void notifyMediaQualityStatusChanged(
|
|
int slotIndex, int subId, @NonNull MediaQualityStatus status) {
|
|
try {
|
|
sRegistry.notifyMediaQualityStatusChanged(slotIndex, subId, status);
|
|
} catch (RemoteException ex) {
|
|
// system server crash
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify emergency number list changed on certain subscription.
|
|
*
|
|
* @param slotIndex for which emergency number list changed. Can be derived from subId except
|
|
* when subId is invalid.
|
|
* @param subId for which emergency number list changed.
|
|
* @hide
|
|
*/
|
|
public void notifyEmergencyNumberList( int slotIndex, int subId) {
|
|
try {
|
|
sRegistry.notifyEmergencyNumberList(slotIndex, subId);
|
|
} catch (RemoteException ex) {
|
|
// system process is dead
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify outgoing emergency call to all applications that have registered a listener
|
|
* ({@link PhoneStateListener}) or a callback ({@link TelephonyCallback}) to monitor changes in
|
|
* telephony states.
|
|
* @param simSlotIndex Sender phone ID.
|
|
* @param subscriptionId Sender subscription ID.
|
|
* @param emergencyNumber Emergency number.
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
|
|
public void notifyOutgoingEmergencyCall(int simSlotIndex, int subscriptionId,
|
|
@NonNull EmergencyNumber emergencyNumber) {
|
|
try {
|
|
sRegistry.notifyOutgoingEmergencyCall(simSlotIndex, subscriptionId, emergencyNumber);
|
|
} catch (RemoteException ex) {
|
|
// system process is dead
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify outgoing emergency SMS.
|
|
* @param phoneId Sender phone ID.
|
|
* @param subId Sender subscription ID.
|
|
* @param emergencyNumber Emergency number.
|
|
* @hide
|
|
*/
|
|
public void notifyOutgoingEmergencySms(int phoneId, int subId,
|
|
@NonNull EmergencyNumber emergencyNumber) {
|
|
try {
|
|
sRegistry.notifyOutgoingEmergencySms(phoneId, subId, emergencyNumber);
|
|
} catch (RemoteException ex) {
|
|
// system process is dead
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify radio power state changed on certain subscription.
|
|
*
|
|
* @param slotIndex for which radio power state changed. Can be derived from subId except when
|
|
* subId is invalid.
|
|
* @param subId for which radio power state changed.
|
|
* @param radioPowerState the current modem radio state.
|
|
* @hide
|
|
*/
|
|
public void notifyRadioPowerStateChanged(int slotIndex, int subId,
|
|
@RadioPowerState int radioPowerState) {
|
|
try {
|
|
sRegistry.notifyRadioPowerStateChanged(slotIndex, subId, radioPowerState);
|
|
} catch (RemoteException ex) {
|
|
// system process is dead
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify {@link PhoneCapability} changed.
|
|
*
|
|
* @param phoneCapability the capability of the modem group.
|
|
* @hide
|
|
*/
|
|
public void notifyPhoneCapabilityChanged(@NonNull PhoneCapability phoneCapability) {
|
|
try {
|
|
sRegistry.notifyPhoneCapabilityChanged(phoneCapability);
|
|
} catch (RemoteException ex) {
|
|
// system process is dead
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sim activation type: voice
|
|
* @see #notifyVoiceActivationStateChanged
|
|
* @hide
|
|
*/
|
|
public static final int SIM_ACTIVATION_TYPE_VOICE = 0;
|
|
/**
|
|
* Sim activation type: data
|
|
* @see #notifyDataActivationStateChanged
|
|
* @hide
|
|
*/
|
|
public static final int SIM_ACTIVATION_TYPE_DATA = 1;
|
|
|
|
/**
|
|
* Notify data activation state changed on certain subscription.
|
|
* @see TelephonyManager#getDataActivationState()
|
|
*
|
|
* @param slotIndex for which data activation state changed. Can be derived from subId except
|
|
* when subId is invalid.
|
|
* @param subId for which data activation state changed.
|
|
* @param activationState sim activation state e.g, activated.
|
|
* @hide
|
|
*/
|
|
public void notifyDataActivationStateChanged(int slotIndex, int subId,
|
|
@SimActivationState int activationState) {
|
|
try {
|
|
sRegistry.notifySimActivationStateChangedForPhoneId(slotIndex, subId,
|
|
SIM_ACTIVATION_TYPE_DATA, activationState);
|
|
} catch (RemoteException ex) {
|
|
// system process is dead
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify voice activation state changed on certain subscription.
|
|
* @see TelephonyManager#getVoiceActivationState()
|
|
*
|
|
* @param slotIndex for which voice activation state changed. Can be derived from subId except
|
|
* subId is invalid.
|
|
* @param subId for which voice activation state changed.
|
|
* @param activationState sim activation state e.g, activated.
|
|
* @hide
|
|
*/
|
|
public void notifyVoiceActivationStateChanged(int slotIndex, int subId,
|
|
@SimActivationState int activationState) {
|
|
try {
|
|
sRegistry.notifySimActivationStateChangedForPhoneId(slotIndex, subId,
|
|
SIM_ACTIVATION_TYPE_VOICE, activationState);
|
|
} catch (RemoteException ex) {
|
|
// system process is dead
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify User mobile data state changed on certain subscription. e.g, mobile data is enabled
|
|
* or disabled.
|
|
*
|
|
* @param slotIndex for which mobile data state has changed. Can be derived from subId except
|
|
* when subId is invalid.
|
|
* @param subId for which mobile data state has changed.
|
|
* @param state {@code true} indicates mobile data is enabled/on. {@code false} otherwise.
|
|
* @hide
|
|
*/
|
|
public void notifyUserMobileDataStateChanged(int slotIndex, int subId, boolean state) {
|
|
try {
|
|
sRegistry.notifyUserMobileDataStateChangedForPhoneId(slotIndex, subId, state);
|
|
} catch (RemoteException ex) {
|
|
// system process is dead
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify display info changed.
|
|
*
|
|
* @param slotIndex The SIM slot index for which display info has changed. Can be
|
|
* derived from {@code subscriptionId} except when {@code subscriptionId} is invalid, such as
|
|
* when the device is in emergency-only mode.
|
|
* @param subscriptionId Subscription id for which display network info has changed.
|
|
* @param telephonyDisplayInfo The display info.
|
|
* @hide
|
|
*/
|
|
public void notifyDisplayInfoChanged(int slotIndex, int subscriptionId,
|
|
@NonNull TelephonyDisplayInfo telephonyDisplayInfo) {
|
|
try {
|
|
sRegistry.notifyDisplayInfoChanged(slotIndex, subscriptionId, telephonyDisplayInfo);
|
|
} catch (RemoteException ex) {
|
|
// system process is dead
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify IMS call disconnect causes which contains {@link android.telephony.ims.ImsReasonInfo}.
|
|
*
|
|
* @param subId for which ims call disconnect.
|
|
* @param imsReasonInfo the reason for ims call disconnect.
|
|
* @hide
|
|
*/
|
|
public void notifyImsDisconnectCause(int subId, @NonNull ImsReasonInfo imsReasonInfo) {
|
|
try {
|
|
sRegistry.notifyImsDisconnectCause(subId, imsReasonInfo);
|
|
} catch (RemoteException ex) {
|
|
// system process is dead
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify single Radio Voice Call Continuity (SRVCC) state change for the currently active call
|
|
* on certain subscription.
|
|
*
|
|
* @param subId for which srvcc state changed.
|
|
* @param state srvcc state
|
|
* @hide
|
|
*/
|
|
public void notifySrvccStateChanged(int subId, @SrvccState int state) {
|
|
try {
|
|
sRegistry.notifySrvccStateChanged(subId, state);
|
|
} catch (RemoteException ex) {
|
|
// system process is dead
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify precise call state changed on certain subscription, including foreground, background
|
|
* and ringcall states.
|
|
*
|
|
* @param slotIndex for which precise call state changed. Can be derived from subId except when
|
|
* subId is invalid.
|
|
* @param subId for which precise call state changed.
|
|
* @param callStates Array of PreciseCallState of foreground, background & ringing calls.
|
|
* @param imsCallIds Array of IMS call session ID{@link ImsCallSession#getCallId} for
|
|
* ringing, foreground & background calls.
|
|
* @param imsServiceTypes Array of IMS call service type for ringing, foreground &
|
|
* background calls.
|
|
* @param imsCallTypes Array of IMS call type for ringing, foreground & background calls.
|
|
* @hide
|
|
*/
|
|
public void notifyPreciseCallState(int slotIndex, int subId,
|
|
@Annotation.PreciseCallStates int[] callStates, String[] imsCallIds,
|
|
@Annotation.ImsCallServiceType int[] imsServiceTypes,
|
|
@Annotation.ImsCallType int[] imsCallTypes) {
|
|
try {
|
|
sRegistry.notifyPreciseCallState(slotIndex, subId, callStates,
|
|
imsCallIds, imsServiceTypes, imsCallTypes);
|
|
} catch (RemoteException ex) {
|
|
// system process is dead
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify call disconnect causes which contains {@link DisconnectCause} and {@link
|
|
* android.telephony.PreciseDisconnectCause}.
|
|
*
|
|
* @param slotIndex for which call disconnected. Can be derived from subId except when subId is
|
|
* invalid.
|
|
* @param subId for which call disconnected.
|
|
* @param cause {@link DisconnectCause} for the disconnected call.
|
|
* @param preciseCause {@link android.telephony.PreciseDisconnectCause} for the disconnected
|
|
* call.
|
|
* @hide
|
|
*/
|
|
public void notifyDisconnectCause(int slotIndex, int subId, @DisconnectCauses int cause,
|
|
@PreciseDisconnectCauses int preciseCause) {
|
|
try {
|
|
sRegistry.notifyDisconnectCause(slotIndex, subId, cause, preciseCause);
|
|
} catch (RemoteException ex) {
|
|
// system process is dead
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify {@link android.telephony.CellLocation} changed.
|
|
*
|
|
* <p>To be compatible with {@link TelephonyRegistry}, use {@link CellIdentity} which is
|
|
* parcelable, and convert to CellLocation in client code.
|
|
* @hide
|
|
*/
|
|
public void notifyCellLocation(int subId, @NonNull CellIdentity cellLocation) {
|
|
try {
|
|
sRegistry.notifyCellLocationForSubscriber(subId, cellLocation);
|
|
} catch (RemoteException ex) {
|
|
// system process is dead
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify {@link CellInfo} changed on certain subscription. e.g, when an observed cell info has
|
|
* changed or new cells have been added or removed on the given subscription.
|
|
*
|
|
* @param subId for which cellinfo changed.
|
|
* @param cellInfo A list of cellInfo associated with the given subscription.
|
|
* @hide
|
|
*/
|
|
public void notifyCellInfoChanged(int subId, @NonNull List<CellInfo> cellInfo) {
|
|
try {
|
|
sRegistry.notifyCellInfoForSubscriber(subId, cellInfo);
|
|
} catch (RemoteException ex) {
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify that the active data subscription ID has changed.
|
|
* @param activeDataSubId The new subscription ID for active data
|
|
* @hide
|
|
*/
|
|
public void notifyActiveDataSubIdChanged(int activeDataSubId) {
|
|
try {
|
|
sRegistry.notifyActiveDataSubIdChanged(activeDataSubId);
|
|
} catch (RemoteException ex) {
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Report that Registration or a Location/Routing/Tracking Area update has failed.
|
|
*
|
|
* @param slotIndex for which call disconnected. Can be derived from subId except when subId is
|
|
* invalid.
|
|
* @param subId for which cellinfo changed.
|
|
* @param cellIdentity the CellIdentity, which must include the globally unique identifier
|
|
* for the cell (for example, all components of the CGI or ECGI).
|
|
* @param chosenPlmn a 5 or 6 digit alphanumeric PLMN (MCC|MNC) among those broadcast by the
|
|
* cell that was chosen for the failed registration attempt.
|
|
* @param domain DOMAIN_CS, DOMAIN_PS or both in case of a combined procedure.
|
|
* @param causeCode the primary failure cause code of the procedure.
|
|
* For GSM/UMTS (MM), values are in TS 24.008 Sec 10.5.95
|
|
* For GSM/UMTS (GMM), values are in TS 24.008 Sec 10.5.147
|
|
* For LTE (EMM), cause codes are TS 24.301 Sec 9.9.3.9
|
|
* For NR (5GMM), cause codes are TS 24.501 Sec 9.11.3.2
|
|
* Integer.MAX_VALUE if this value is unused.
|
|
* @param additionalCauseCode the cause code of any secondary/combined procedure if appropriate.
|
|
* For UMTS, if a combined attach succeeds for PS only, then the GMM cause code shall be
|
|
* included as an additionalCauseCode. For LTE (ESM), cause codes are in
|
|
* TS 24.301 9.9.4.4. Integer.MAX_VALUE if this value is unused.
|
|
* @hide
|
|
*/
|
|
public void notifyRegistrationFailed(int slotIndex, int subId,
|
|
@NonNull CellIdentity cellIdentity, @NonNull String chosenPlmn,
|
|
int domain, int causeCode, int additionalCauseCode) {
|
|
try {
|
|
sRegistry.notifyRegistrationFailed(slotIndex, subId, cellIdentity,
|
|
chosenPlmn, domain, causeCode, additionalCauseCode);
|
|
} catch (RemoteException ex) {
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify {@link BarringInfo} has changed for a specific subscription.
|
|
*
|
|
* @param slotIndex for the phone object that got updated barring info.
|
|
* @param subId for which the BarringInfo changed.
|
|
* @param barringInfo updated BarringInfo.
|
|
* @hide
|
|
*/
|
|
public void notifyBarringInfoChanged(
|
|
int slotIndex, int subId, @NonNull BarringInfo barringInfo) {
|
|
try {
|
|
sRegistry.notifyBarringInfoChanged(slotIndex, subId, barringInfo);
|
|
} catch (RemoteException ex) {
|
|
// system server crash
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify {@link PhysicalChannelConfig} has changed for a specific subscription.
|
|
*
|
|
* @param slotIndex for which physical channel configs changed.
|
|
* @param subId the subId
|
|
* @param configs a list of {@link PhysicalChannelConfig}, the configs of physical channel.
|
|
* @hide
|
|
*/
|
|
public void notifyPhysicalChannelConfigForSubscriber(int slotIndex, int subId,
|
|
List<PhysicalChannelConfig> configs) {
|
|
try {
|
|
sRegistry.notifyPhysicalChannelConfigForSubscriber(slotIndex, subId, configs);
|
|
} catch (RemoteException ex) {
|
|
// system server crash
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify that the data enabled has changed.
|
|
*
|
|
* @param enabled True if data is enabled, otherwise disabled.
|
|
* @param reason Reason for data enabled/disabled. See {@code REASON_*} in
|
|
* {@link TelephonyManager}.
|
|
* @hide
|
|
*/
|
|
public void notifyDataEnabled(int slotIndex, int subId, boolean enabled,
|
|
@TelephonyManager.DataEnabledReason int reason) {
|
|
try {
|
|
sRegistry.notifyDataEnabled(slotIndex, subId, enabled, reason);
|
|
} catch (RemoteException ex) {
|
|
// system server crash
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify the allowed network types has changed for a specific subscription and the specific
|
|
* reason.
|
|
* @param slotIndex for which allowed network types changed.
|
|
* @param subId for which allowed network types changed.
|
|
* @param reason an allowed network type reasons.
|
|
* @param allowedNetworkType an allowed network type bitmask value.
|
|
* @hide
|
|
*/
|
|
public void notifyAllowedNetworkTypesChanged(int slotIndex, int subId,
|
|
int reason, long allowedNetworkType) {
|
|
try {
|
|
sRegistry.notifyAllowedNetworkTypesChanged(slotIndex, subId, reason,
|
|
allowedNetworkType);
|
|
} catch (RemoteException ex) {
|
|
// system process is dead
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify that the link capacity estimate has changed.
|
|
* @param slotIndex for the phone object that gets the updated link capacity estimate
|
|
* @param subId for subscription that gets the updated link capacity estimate
|
|
* @param linkCapacityEstimateList a list of {@link LinkCapacityEstimate}
|
|
* @hide
|
|
*/
|
|
public void notifyLinkCapacityEstimateChanged(int slotIndex, int subId,
|
|
List<LinkCapacityEstimate> linkCapacityEstimateList) {
|
|
try {
|
|
sRegistry.notifyLinkCapacityEstimateChanged(slotIndex, subId, linkCapacityEstimateList);
|
|
} catch (RemoteException ex) {
|
|
// system server crash
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify external listeners that the subscriptions supporting simultaneous cellular calling
|
|
* have changed.
|
|
* @param subIds The new set of subIds supporting simultaneous cellular calling.
|
|
* @hide
|
|
*/
|
|
public void notifySimultaneousCellularCallingSubscriptionsChanged(
|
|
@NonNull Set<Integer> subIds) {
|
|
try {
|
|
sRegistry.notifySimultaneousCellularCallingSubscriptionsChanged(
|
|
subIds.stream().mapToInt(i -> i).toArray());
|
|
} catch (RemoteException ex) {
|
|
// system server crash
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify external listeners that carrier roaming non-terrestrial network mode changed.
|
|
* @param subId subscription ID.
|
|
* @param active {@code true} If the device is connected to carrier roaming
|
|
* non-terrestrial network or was connected within the
|
|
* {CarrierConfigManager#KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT}
|
|
* duration, {code false} otherwise.
|
|
* @hide
|
|
*/
|
|
public void notifyCarrierRoamingNtnModeChanged(int subId, boolean active) {
|
|
try {
|
|
sRegistry.notifyCarrierRoamingNtnModeChanged(subId, active);
|
|
} catch (RemoteException ex) {
|
|
// system server crash
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Processes potential event changes from the provided {@link TelephonyCallback}.
|
|
*
|
|
* @param telephonyCallback callback for monitoring callback changes to the telephony state.
|
|
* @hide
|
|
*/
|
|
public @NonNull Set<Integer> getEventsFromCallback(
|
|
@NonNull TelephonyCallback telephonyCallback) {
|
|
Set<Integer> eventList = new ArraySet<>();
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.ServiceStateListener) {
|
|
eventList.add(TelephonyCallback.EVENT_SERVICE_STATE_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.MessageWaitingIndicatorListener) {
|
|
eventList.add(TelephonyCallback.EVENT_MESSAGE_WAITING_INDICATOR_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.CallForwardingIndicatorListener) {
|
|
eventList.add(TelephonyCallback.EVENT_CALL_FORWARDING_INDICATOR_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.CellLocationListener) {
|
|
eventList.add(TelephonyCallback.EVENT_CELL_LOCATION_CHANGED);
|
|
}
|
|
|
|
// Note: Legacy PhoneStateListeners use EVENT_LEGACY_CALL_STATE_CHANGED
|
|
if (telephonyCallback instanceof TelephonyCallback.CallStateListener) {
|
|
eventList.add(TelephonyCallback.EVENT_CALL_STATE_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.DataConnectionStateListener) {
|
|
eventList.add(TelephonyCallback.EVENT_DATA_CONNECTION_STATE_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.DataActivityListener) {
|
|
eventList.add(TelephonyCallback.EVENT_DATA_ACTIVITY_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.SignalStrengthsListener) {
|
|
eventList.add(TelephonyCallback.EVENT_SIGNAL_STRENGTHS_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.CellInfoListener) {
|
|
eventList.add(TelephonyCallback.EVENT_CELL_INFO_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.PreciseCallStateListener) {
|
|
eventList.add(TelephonyCallback.EVENT_PRECISE_CALL_STATE_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.CallDisconnectCauseListener) {
|
|
eventList.add(TelephonyCallback.EVENT_CALL_DISCONNECT_CAUSE_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.ImsCallDisconnectCauseListener) {
|
|
eventList.add(TelephonyCallback.EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.PreciseDataConnectionStateListener) {
|
|
eventList.add(TelephonyCallback.EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.SrvccStateListener) {
|
|
eventList.add(TelephonyCallback.EVENT_SRVCC_STATE_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.VoiceActivationStateListener) {
|
|
eventList.add(TelephonyCallback.EVENT_VOICE_ACTIVATION_STATE_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.DataActivationStateListener) {
|
|
eventList.add(TelephonyCallback.EVENT_DATA_ACTIVATION_STATE_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.UserMobileDataStateListener) {
|
|
eventList.add(TelephonyCallback.EVENT_USER_MOBILE_DATA_STATE_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.DisplayInfoListener) {
|
|
eventList.add(TelephonyCallback.EVENT_DISPLAY_INFO_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.EmergencyNumberListListener) {
|
|
eventList.add(TelephonyCallback.EVENT_EMERGENCY_NUMBER_LIST_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.OutgoingEmergencyCallListener) {
|
|
eventList.add(TelephonyCallback.EVENT_OUTGOING_EMERGENCY_CALL);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.OutgoingEmergencySmsListener) {
|
|
eventList.add(TelephonyCallback.EVENT_OUTGOING_EMERGENCY_SMS);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.PhoneCapabilityListener) {
|
|
eventList.add(TelephonyCallback.EVENT_PHONE_CAPABILITY_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.ActiveDataSubscriptionIdListener) {
|
|
eventList.add(TelephonyCallback.EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.RadioPowerStateListener) {
|
|
eventList.add(TelephonyCallback.EVENT_RADIO_POWER_STATE_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.CarrierNetworkListener) {
|
|
eventList.add(TelephonyCallback.EVENT_CARRIER_NETWORK_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.RegistrationFailedListener) {
|
|
eventList.add(TelephonyCallback.EVENT_REGISTRATION_FAILURE);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.CallAttributesListener) {
|
|
eventList.add(TelephonyCallback.EVENT_CALL_ATTRIBUTES_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.BarringInfoListener) {
|
|
eventList.add(TelephonyCallback.EVENT_BARRING_INFO_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.PhysicalChannelConfigListener) {
|
|
eventList.add(TelephonyCallback.EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.DataEnabledListener) {
|
|
eventList.add(TelephonyCallback.EVENT_DATA_ENABLED_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.AllowedNetworkTypesListener) {
|
|
eventList.add(TelephonyCallback.EVENT_ALLOWED_NETWORK_TYPE_LIST_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.LinkCapacityEstimateChangedListener) {
|
|
eventList.add(TelephonyCallback.EVENT_LINK_CAPACITY_ESTIMATE_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.MediaQualityStatusChangedListener) {
|
|
eventList.add(TelephonyCallback.EVENT_MEDIA_QUALITY_STATUS_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.EmergencyCallbackModeListener) {
|
|
eventList.add(TelephonyCallback.EVENT_EMERGENCY_CALLBACK_MODE_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback
|
|
instanceof TelephonyCallback.SimultaneousCellularCallingSupportListener) {
|
|
eventList.add(
|
|
TelephonyCallback.EVENT_SIMULTANEOUS_CELLULAR_CALLING_SUBSCRIPTIONS_CHANGED);
|
|
}
|
|
|
|
if (telephonyCallback instanceof TelephonyCallback.CarrierRoamingNtnModeListener) {
|
|
eventList.add(TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_MODE_CHANGED);
|
|
}
|
|
return eventList;
|
|
}
|
|
|
|
private @NonNull Set<Integer> getEventsFromBitmask(int eventMask) {
|
|
|
|
Set<Integer> eventList = new ArraySet<>();
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_SERVICE_STATE_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_SIGNAL_STRENGTH_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_MESSAGE_WAITING_INDICATOR_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_CALL_FORWARDING_INDICATOR_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_CELL_LOCATION_CHANGED);
|
|
}
|
|
|
|
// Note: Legacy call state listeners can get the phone number which is not provided in the
|
|
// new version in TelephonyCallback.
|
|
if ((eventMask & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_LEGACY_CALL_STATE_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_DATA_CONNECTION_STATE_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_DATA_ACTIVITY_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_SIGNAL_STRENGTHS_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_CELL_INFO_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_PRECISE_CALL_STATE_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_DATA_CONNECTION_REAL_TIME_INFO) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_DATA_CONNECTION_REAL_TIME_INFO_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_OEM_HOOK_RAW);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_SRVCC_STATE_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_CARRIER_NETWORK_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_VOICE_ACTIVATION_STATE) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_VOICE_ACTIVATION_STATE_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_DATA_ACTIVATION_STATE) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_DATA_ACTIVATION_STATE_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_USER_MOBILE_DATA_STATE) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_USER_MOBILE_DATA_STATE_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_DISPLAY_INFO_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_PHONE_CAPABILITY_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_RADIO_POWER_STATE_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_EMERGENCY_NUMBER_LIST_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_CALL_DISCONNECT_CAUSE_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_CALL_ATTRIBUTES_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_OUTGOING_EMERGENCY_CALL);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_SMS) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_OUTGOING_EMERGENCY_SMS);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_REGISTRATION_FAILURE) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_REGISTRATION_FAILURE);
|
|
}
|
|
|
|
if ((eventMask & PhoneStateListener.LISTEN_BARRING_INFO) != 0) {
|
|
eventList.add(TelephonyCallback.EVENT_BARRING_INFO_CHANGED);
|
|
}
|
|
return eventList;
|
|
|
|
}
|
|
|
|
/**
|
|
* Registers a callback object to receive notification of changes in specified telephony states.
|
|
* <p>
|
|
* To register a callback, pass a {@link TelephonyCallback} which implements
|
|
* interfaces of events. For example,
|
|
* FakeServiceStateCallback extends {@link TelephonyCallback} implements
|
|
* {@link TelephonyCallback.ServiceStateListener}.
|
|
*
|
|
* At registration, and when a specified telephony state changes, the telephony manager invokes
|
|
* the appropriate callback method on the callback object and passes the current (updated)
|
|
* values.
|
|
* <p>
|
|
*
|
|
* If this TelephonyManager object has been created with
|
|
* {@link TelephonyManager#createForSubscriptionId}, applies to the given subId.
|
|
* Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}.
|
|
* To register events for multiple subIds, pass a separate callback object to
|
|
* each TelephonyManager object created with {@link TelephonyManager#createForSubscriptionId}.
|
|
*
|
|
* Note: if you call this method while in the middle of a binder transaction, you <b>must</b>
|
|
* call {@link android.os.Binder#clearCallingIdentity()} before calling this method. A
|
|
* {@link SecurityException} will be thrown otherwise.
|
|
*
|
|
* This API should be used sparingly -- large numbers of callbacks will cause system
|
|
* instability. If a process has registered too many callbacks without unregistering them, it
|
|
* may encounter an {@link IllegalStateException} when trying to register more callbacks.
|
|
*
|
|
* @param callback The {@link TelephonyCallback} object to register.
|
|
* @hide
|
|
*/
|
|
public void registerTelephonyCallback(boolean renounceFineLocationAccess,
|
|
boolean renounceCoarseLocationAccess,
|
|
@NonNull @CallbackExecutor Executor executor,
|
|
int subId, String pkgName, String attributionTag, @NonNull TelephonyCallback callback,
|
|
boolean notifyNow) {
|
|
if (callback == null) {
|
|
throw new IllegalStateException("telephony service is null.");
|
|
}
|
|
callback.init(executor);
|
|
listenFromCallback(renounceFineLocationAccess, renounceCoarseLocationAccess, subId,
|
|
pkgName, attributionTag, callback,
|
|
getEventsFromCallback(callback).stream().mapToInt(i -> i).toArray(), notifyNow);
|
|
}
|
|
|
|
/**
|
|
* Unregister an existing {@link TelephonyCallback}.
|
|
*
|
|
* @param callback The {@link TelephonyCallback} object to unregister.
|
|
* @hide
|
|
*/
|
|
public void unregisterTelephonyCallback(int subId, String pkgName, String attributionTag,
|
|
@NonNull TelephonyCallback callback, boolean notifyNow) {
|
|
listenFromCallback(false, false, subId,
|
|
pkgName, attributionTag, callback, new int[0], notifyNow);
|
|
}
|
|
|
|
private static class CarrierPrivilegesCallbackWrapper extends ICarrierPrivilegesCallback.Stub
|
|
implements ListenerExecutor {
|
|
@NonNull private final WeakReference<CarrierPrivilegesCallback> mCallback;
|
|
@NonNull private final Executor mExecutor;
|
|
|
|
CarrierPrivilegesCallbackWrapper(
|
|
@NonNull CarrierPrivilegesCallback callback, @NonNull Executor executor) {
|
|
mCallback = new WeakReference<>(callback);
|
|
mExecutor = executor;
|
|
}
|
|
|
|
@Override
|
|
public void onCarrierPrivilegesChanged(
|
|
@NonNull List<String> privilegedPackageNames, @NonNull int[] privilegedUids) {
|
|
// AIDL interface does not support Set, keep the List/Array and translate them here
|
|
Set<String> privilegedPkgNamesSet = Set.copyOf(privilegedPackageNames);
|
|
Set<Integer> privilegedUidsSet = Arrays.stream(privilegedUids).boxed().collect(
|
|
Collectors.toSet());
|
|
Binder.withCleanCallingIdentity(
|
|
() ->
|
|
executeSafely(
|
|
mExecutor,
|
|
mCallback::get,
|
|
cpc ->
|
|
cpc.onCarrierPrivilegesChanged(
|
|
privilegedPkgNamesSet, privilegedUidsSet)));
|
|
}
|
|
|
|
@Override
|
|
public void onCarrierServiceChanged(@Nullable String packageName, int uid) {
|
|
Binder.withCleanCallingIdentity(
|
|
() ->
|
|
executeSafely(
|
|
mExecutor,
|
|
mCallback::get,
|
|
cpc -> cpc.onCarrierServiceChanged(packageName, uid)));
|
|
}
|
|
}
|
|
|
|
@NonNull
|
|
@GuardedBy("sCarrierPrivilegeCallbacks")
|
|
private static final WeakHashMap<CarrierPrivilegesCallback,
|
|
WeakReference<CarrierPrivilegesCallbackWrapper>>
|
|
sCarrierPrivilegeCallbacks = new WeakHashMap<>();
|
|
|
|
/**
|
|
* Registers a {@link CarrierPrivilegesCallback} on the given {@code logicalSlotIndex} to
|
|
* receive callbacks when the set of packages with carrier privileges changes. The callback will
|
|
* immediately be called with the latest state.
|
|
*
|
|
* @param logicalSlotIndex The SIM slot to listen on
|
|
* @param executor The executor where {@code listener} will be invoked
|
|
* @param callback The callback to register
|
|
* @hide
|
|
*/
|
|
public void addCarrierPrivilegesCallback(
|
|
int logicalSlotIndex,
|
|
@NonNull @CallbackExecutor Executor executor,
|
|
@NonNull CarrierPrivilegesCallback callback) {
|
|
if (callback == null || executor == null) {
|
|
throw new IllegalArgumentException("callback and executor must be non-null");
|
|
}
|
|
synchronized (sCarrierPrivilegeCallbacks) {
|
|
WeakReference<CarrierPrivilegesCallbackWrapper> existing =
|
|
sCarrierPrivilegeCallbacks.get(callback);
|
|
if (existing != null && existing.get() != null) {
|
|
Log.d(TAG, "addCarrierPrivilegesCallback: callback already registered");
|
|
return;
|
|
}
|
|
CarrierPrivilegesCallbackWrapper wrapper =
|
|
new CarrierPrivilegesCallbackWrapper(callback, executor);
|
|
sCarrierPrivilegeCallbacks.put(callback, new WeakReference<>(wrapper));
|
|
try {
|
|
sRegistry.addCarrierPrivilegesCallback(
|
|
logicalSlotIndex,
|
|
wrapper,
|
|
mContext.getOpPackageName(),
|
|
mContext.getAttributionTag());
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Unregisters a {@link CarrierPrivilegesCallback}.
|
|
*
|
|
* @param callback The callback to unregister
|
|
* @hide
|
|
*/
|
|
public void removeCarrierPrivilegesCallback(@NonNull CarrierPrivilegesCallback callback) {
|
|
if (callback == null) {
|
|
throw new IllegalArgumentException("listener must be non-null");
|
|
}
|
|
synchronized (sCarrierPrivilegeCallbacks) {
|
|
WeakReference<CarrierPrivilegesCallbackWrapper> ref =
|
|
sCarrierPrivilegeCallbacks.remove(callback);
|
|
if (ref == null) return;
|
|
CarrierPrivilegesCallbackWrapper wrapper = ref.get();
|
|
if (wrapper == null) return;
|
|
try {
|
|
sRegistry.removeCarrierPrivilegesCallback(wrapper, mContext.getOpPackageName());
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify listeners that the set of packages with carrier privileges has changed.
|
|
*
|
|
* @param logicalSlotIndex The SIM slot the change occurred on
|
|
* @param privilegedPackageNames The updated set of packages names with carrier privileges
|
|
* @param privilegedUids The updated set of UIDs with carrier privileges
|
|
* @hide
|
|
*/
|
|
public void notifyCarrierPrivilegesChanged(
|
|
int logicalSlotIndex,
|
|
@NonNull Set<String> privilegedPackageNames,
|
|
@NonNull Set<Integer> privilegedUids) {
|
|
if (privilegedPackageNames == null || privilegedUids == null) {
|
|
throw new IllegalArgumentException(
|
|
"privilegedPackageNames and privilegedUids must be non-null");
|
|
}
|
|
try {
|
|
// AIDL doesn't support Set yet. Convert Set to List/Array
|
|
List<String> pkgList = List.copyOf(privilegedPackageNames);
|
|
int[] uids = privilegedUids.stream().mapToInt(Number::intValue).toArray();
|
|
sRegistry.notifyCarrierPrivilegesChanged(logicalSlotIndex, pkgList, uids);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify listeners that the {@link CarrierService} for current user has changed.
|
|
*
|
|
* @param logicalSlotIndex the SIM slot the change occurred on
|
|
* @param packageName the package name of the changed {@link CarrierService}
|
|
* @param uid the UID of the changed {@link CarrierService}
|
|
* @hide
|
|
*/
|
|
public void notifyCarrierServiceChanged(int logicalSlotIndex, @Nullable String packageName,
|
|
int uid) {
|
|
try {
|
|
sRegistry.notifyCarrierServiceChanged(logicalSlotIndex, packageName, uid);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Register a {@link android.telephony.CarrierConfigManager.CarrierConfigChangeListener} to get
|
|
* notification when carrier configurations have changed.
|
|
*
|
|
* @param executor The executor on which the callback will be executed.
|
|
* @param listener The CarrierConfigChangeListener to be registered with.
|
|
* @hide
|
|
*/
|
|
public void addCarrierConfigChangedListener(
|
|
@NonNull @CallbackExecutor Executor executor,
|
|
@NonNull CarrierConfigManager.CarrierConfigChangeListener listener) {
|
|
Objects.requireNonNull(executor, "Executor should be non-null.");
|
|
Objects.requireNonNull(listener, "Listener should be non-null.");
|
|
if (mCarrierConfigChangeListenerMap.get(listener) != null) {
|
|
Log.e(TAG, "registerCarrierConfigChangeListener: listener already present");
|
|
return;
|
|
}
|
|
|
|
ICarrierConfigChangeListener callback = new ICarrierConfigChangeListener.Stub() {
|
|
@Override
|
|
public void onCarrierConfigChanged(int slotIndex, int subId, int carrierId,
|
|
int specificCarrierId) {
|
|
Log.d(TAG, "onCarrierConfigChanged call in ICarrierConfigChangeListener callback");
|
|
final long identify = Binder.clearCallingIdentity();
|
|
try {
|
|
executor.execute(() -> listener.onCarrierConfigChanged(slotIndex, subId,
|
|
carrierId, specificCarrierId));
|
|
} finally {
|
|
Binder.restoreCallingIdentity(identify);
|
|
}
|
|
}
|
|
};
|
|
|
|
try {
|
|
sRegistry.addCarrierConfigChangeListener(callback,
|
|
mContext.getOpPackageName(), mContext.getAttributionTag());
|
|
mCarrierConfigChangeListenerMap.put(listener, callback);
|
|
} catch (RemoteException re) {
|
|
// system server crashes
|
|
throw re.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Unregister to stop the notification when carrier configurations changed.
|
|
*
|
|
* @param listener The CarrierConfigChangeListener to be unregistered with.
|
|
* @hide
|
|
*/
|
|
public void removeCarrierConfigChangedListener(
|
|
@NonNull CarrierConfigManager.CarrierConfigChangeListener listener) {
|
|
Objects.requireNonNull(listener, "Listener should be non-null.");
|
|
if (mCarrierConfigChangeListenerMap.get(listener) == null) {
|
|
Log.e(TAG, "removeCarrierConfigChangedListener: listener was not present");
|
|
return;
|
|
}
|
|
|
|
try {
|
|
sRegistry.removeCarrierConfigChangeListener(
|
|
mCarrierConfigChangeListenerMap.get(listener), mContext.getOpPackageName());
|
|
mCarrierConfigChangeListenerMap.remove(listener);
|
|
} catch (RemoteException re) {
|
|
// System sever crashes
|
|
throw re.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify the registrants the carrier configurations have changed.
|
|
*
|
|
* @param slotIndex The SIM slot index on which to monitor and get notification.
|
|
* @param subId The subscription on the SIM slot. May be
|
|
* {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}.
|
|
* @param carrierId The optional carrier Id, may be
|
|
* {@link TelephonyManager#UNKNOWN_CARRIER_ID}.
|
|
* @param specificCarrierId The optional specific carrier Id, may be {@link
|
|
* TelephonyManager#UNKNOWN_CARRIER_ID}.
|
|
* @hide
|
|
*/
|
|
public void notifyCarrierConfigChanged(int slotIndex, int subId, int carrierId,
|
|
int specificCarrierId) {
|
|
// Only validate slotIndex, all others are optional and allowed to be invalid
|
|
if (!SubscriptionManager.isValidPhoneId(slotIndex)) {
|
|
Log.e(TAG, "notifyCarrierConfigChanged, ignored: invalid slotIndex " + slotIndex);
|
|
return;
|
|
}
|
|
try {
|
|
sRegistry.notifyCarrierConfigChanged(slotIndex, subId, carrierId, specificCarrierId);
|
|
} catch (RemoteException re) {
|
|
throw re.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify Callback Mode has been started.
|
|
* @param phoneId Sender phone ID.
|
|
* @param subId Sender subscription ID.
|
|
* @param type for callback mode entry.
|
|
* See {@link TelephonyManager.EmergencyCallbackModeType}.
|
|
* @hide
|
|
*/
|
|
public void notifyCallBackModeStarted(int phoneId, int subId,
|
|
@TelephonyManager.EmergencyCallbackModeType int type) {
|
|
try {
|
|
Log.d(TAG, "notifyCallBackModeStarted:type=" + type);
|
|
sRegistry.notifyCallbackModeStarted(phoneId, subId, type);
|
|
} catch (RemoteException ex) {
|
|
// system process is dead
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify Callback Mode has been stopped.
|
|
* @param phoneId Sender phone ID.
|
|
* @param subId Sender subscription ID.
|
|
* @param type for callback mode entry.
|
|
* See {@link TelephonyManager.EmergencyCallbackModeType}.
|
|
* @param reason for changing callback mode.
|
|
* See {@link TelephonyManager.EmergencyCallbackModeStopReason}.
|
|
* @hide
|
|
*/
|
|
public void notifyCallbackModeStopped(int phoneId, int subId,
|
|
@TelephonyManager.EmergencyCallbackModeType int type,
|
|
@TelephonyManager.EmergencyCallbackModeStopReason int reason) {
|
|
try {
|
|
Log.d(TAG, "notifyCallbackModeStopped:type=" + type + ", reason=" + reason);
|
|
sRegistry.notifyCallbackModeStopped(phoneId, subId, type, reason);
|
|
} catch (RemoteException ex) {
|
|
// system process is dead
|
|
throw ex.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
}
|