Introduce CarrierPrivilegesCallback to replace CarrierPrivilegesListener

Add new interface in CarrierPrivilegesCallback to notify the registrants
that carrier service for current user has changed.

Reshape the parameters of onCarrierPrivilegesChanged callback with
both Set instead of List/Array.

CarrierPrivilegesListener is deprecated. Once all clients have migrated
to CarrierPrivilegesCallback, it will be throughly cleaned up.

Bug: 216549778
Test: atest CarrierPrivilegesTrackerTest CarrierServiceTest
Test: atest WifiCarrierInfoManagerTest TelephonyRegistryManagerTest
Test: atest TelephonySubscriptionTrackerTest

Change-Id: I195a99ec6508c7fe3398908bfca632d8446ab29c
This commit is contained in:
Rambo Wang
2022-02-16 20:41:25 -08:00
parent f76ef62d1a
commit b66e3e3aa8
6 changed files with 359 additions and 63 deletions

View File

@@ -13337,7 +13337,7 @@ package android.telephony {
} }
public class TelephonyManager { public class TelephonyManager {
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void addCarrierPrivilegesListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener); method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void addCarrierPrivilegesListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener);
method @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) @WorkerThread public void bootstrapAuthenticationRequest(int, @NonNull android.net.Uri, @NonNull android.telephony.gba.UaSecurityProtocolIdentifier, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.BootstrapAuthenticationCallback); method @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) @WorkerThread public void bootstrapAuthenticationRequest(int, @NonNull android.net.Uri, @NonNull android.telephony.gba.UaSecurityProtocolIdentifier, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.BootstrapAuthenticationCallback);
method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void call(String, String); method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void call(String, String);
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.PinResult changeIccLockPin(@NonNull String, @NonNull String); method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.PinResult changeIccLockPin(@NonNull String, @NonNull String);
@@ -13437,7 +13437,8 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyOtaEmergencyNumberDbInstalled(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyOtaEmergencyNumberDbInstalled();
method @RequiresPermission(android.Manifest.permission.REBOOT) public int prepareForUnattendedReboot(); method @RequiresPermission(android.Manifest.permission.REBOOT) public int prepareForUnattendedReboot();
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio(); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void removeCarrierPrivilegesListener(@NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerCarrierPrivilegesCallback(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CarrierPrivilegesCallback);
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void removeCarrierPrivilegesListener(@NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void reportDefaultNetworkStatus(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void reportDefaultNetworkStatus(boolean);
method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback); method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestModemActivityInfo(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.telephony.ModemActivityInfo,android.telephony.TelephonyManager.ModemActivityInfoException>); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestModemActivityInfo(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.telephony.ModemActivityInfo,android.telephony.TelephonyManager.ModemActivityInfoException>);
@@ -13487,6 +13488,7 @@ package android.telephony {
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterCarrierPrivilegesCallback(@NonNull android.telephony.TelephonyManager.CarrierPrivilegesCallback);
method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor); method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor);
method public void updateServiceLocation(); method public void updateServiceLocation();
field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_ANOMALY_REPORTED = "android.telephony.action.ANOMALY_REPORTED"; field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_ANOMALY_REPORTED = "android.telephony.action.ANOMALY_REPORTED";
@@ -13592,8 +13594,13 @@ package android.telephony {
field public static final int RESULT_SUCCESS = 0; // 0x0 field public static final int RESULT_SUCCESS = 0; // 0x0
} }
public static interface TelephonyManager.CarrierPrivilegesListener { public static interface TelephonyManager.CarrierPrivilegesCallback {
method public void onCarrierPrivilegesChanged(@NonNull java.util.List<java.lang.String>, @NonNull int[]); method public void onCarrierPrivilegesChanged(@NonNull java.util.Set<java.lang.String>, @NonNull java.util.Set<java.lang.Integer>);
method public default void onCarrierServiceChanged(@Nullable String, int);
}
@Deprecated public static interface TelephonyManager.CarrierPrivilegesListener {
method @Deprecated public void onCarrierPrivilegesChanged(@NonNull java.util.List<java.lang.String>, @NonNull int[]);
} }
public static class TelephonyManager.ModemActivityInfoException extends java.lang.Exception { public static class TelephonyManager.ModemActivityInfoException extends java.lang.Exception {

View File

@@ -27,6 +27,7 @@ import android.os.Binder;
import android.os.Build; import android.os.Build;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ServiceManager; import android.os.ServiceManager;
import android.service.carrier.CarrierService;
import android.telephony.Annotation.CallState; import android.telephony.Annotation.CallState;
import android.telephony.Annotation.DataActivityType; import android.telephony.Annotation.DataActivityType;
import android.telephony.Annotation.DisconnectCauses; import android.telephony.Annotation.DisconnectCauses;
@@ -36,6 +37,7 @@ import android.telephony.Annotation.PreciseDisconnectCauses;
import android.telephony.Annotation.RadioPowerState; import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SimActivationState; import android.telephony.Annotation.SimActivationState;
import android.telephony.Annotation.SrvccState; import android.telephony.Annotation.SrvccState;
import android.telephony.TelephonyManager.CarrierPrivilegesCallback;
import android.telephony.TelephonyManager.CarrierPrivilegesListener; import android.telephony.TelephonyManager.CarrierPrivilegesListener;
import android.telephony.emergency.EmergencyNumber; import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.ImsReasonInfo; import android.telephony.ims.ImsReasonInfo;
@@ -44,17 +46,19 @@ import android.util.Log;
import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy;
import com.android.internal.listeners.ListenerExecutor; import com.android.internal.listeners.ListenerExecutor;
import com.android.internal.telephony.ICarrierPrivilegesListener; import com.android.internal.telephony.ICarrierPrivilegesCallback;
import com.android.internal.telephony.IOnSubscriptionsChangedListener; import com.android.internal.telephony.IOnSubscriptionsChangedListener;
import com.android.internal.telephony.ITelephonyRegistry; import com.android.internal.telephony.ITelephonyRegistry;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.stream.Collectors;
/** /**
* A centralized place to notify telephony related status changes, e.g, {@link ServiceState} update * A centralized place to notify telephony related status changes, e.g, {@link ServiceState} update
@@ -1260,34 +1264,78 @@ public class TelephonyRegistryManager {
pkgName, attributionTag, callback, new int[0], notifyNow); pkgName, attributionTag, callback, new int[0], notifyNow);
} }
private static class CarrierPrivilegesListenerWrapper extends ICarrierPrivilegesListener.Stub // TODO(b/216549778): Remove listener logic once all clients switch to CarrierPrivilegesCallback
private static class CarrierPrivilegesCallbackWrapper extends ICarrierPrivilegesCallback.Stub
implements ListenerExecutor { implements ListenerExecutor {
private final WeakReference<CarrierPrivilegesListener> mListener; // Either mListener or mCallback may be null, never both
private final Executor mExecutor; @Nullable private final WeakReference<CarrierPrivilegesListener> mListener;
@Nullable private final WeakReference<CarrierPrivilegesCallback> mCallback;
@NonNull private final Executor mExecutor;
CarrierPrivilegesListenerWrapper(CarrierPrivilegesListener listener, Executor executor) { CarrierPrivilegesCallbackWrapper(
@NonNull CarrierPrivilegesCallback callback, @NonNull Executor executor) {
mListener = null;
mCallback = new WeakReference<>(callback);
mExecutor = executor;
}
CarrierPrivilegesCallbackWrapper(
@NonNull CarrierPrivilegesListener listener, @NonNull Executor executor) {
mListener = new WeakReference<>(listener); mListener = new WeakReference<>(listener);
mCallback = null;
mExecutor = executor; mExecutor = executor;
} }
@Override @Override
public void onCarrierPrivilegesChanged( public void onCarrierPrivilegesChanged(
List<String> privilegedPackageNames, int[] privilegedUids) { @NonNull List<String> privilegedPackageNames, @NonNull int[] privilegedUids) {
Binder.withCleanCallingIdentity( if (mListener != null) {
() -> Binder.withCleanCallingIdentity(
executeSafely( () ->
mExecutor, executeSafely(
mListener::get, mExecutor,
cpl -> mListener::get,
cpl.onCarrierPrivilegesChanged( cpl ->
privilegedPackageNames, privilegedUids))); cpl.onCarrierPrivilegesChanged(
privilegedPackageNames, privilegedUids)));
}
if (mCallback != null) {
// 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) {
if (mCallback != null) {
Binder.withCleanCallingIdentity(
() ->
executeSafely(
mExecutor,
mCallback::get,
cpc -> cpc.onCarrierServiceChanged(packageName, uid)));
}
} }
} }
@GuardedBy("sCarrierPrivilegeListeners") // TODO(b/216549778): Change the map key to CarrierPrivilegesCallback once all clients switch to
private static final WeakHashMap< // CarrierPrivilegesCallback. Before that, the key is either CarrierPrivilegesCallback or
CarrierPrivilegesListener, WeakReference<CarrierPrivilegesListenerWrapper>> // CarrierPrivilegesListener, no logic actually depends on the type.
sCarrierPrivilegeListeners = new WeakHashMap<>(); @NonNull
@GuardedBy("sCarrierPrivilegeCallbacks")
private static final WeakHashMap<Object, WeakReference<CarrierPrivilegesCallbackWrapper>>
sCarrierPrivilegeCallbacks = new WeakHashMap<>();
/** /**
* Registers a {@link CarrierPrivilegesListener} on the given {@code logicalSlotIndex} to * Registers a {@link CarrierPrivilegesListener} on the given {@code logicalSlotIndex} to
@@ -1297,7 +1345,11 @@ public class TelephonyRegistryManager {
* @param logicalSlotIndex The SIM slot to listen on * @param logicalSlotIndex The SIM slot to listen on
* @param executor The executor where {@code listener} will be invoked * @param executor The executor where {@code listener} will be invoked
* @param listener The callback to register * @param listener The callback to register
*
* @deprecated Use {@link #addCarrierPrivilegesCallback} instead. This API will be removed
* prior to API finalization.
*/ */
@Deprecated
public void addCarrierPrivilegesListener( public void addCarrierPrivilegesListener(
int logicalSlotIndex, int logicalSlotIndex,
@NonNull @CallbackExecutor Executor executor, @NonNull @CallbackExecutor Executor executor,
@@ -1305,18 +1357,18 @@ public class TelephonyRegistryManager {
if (listener == null || executor == null) { if (listener == null || executor == null) {
throw new IllegalArgumentException("listener and executor must be non-null"); throw new IllegalArgumentException("listener and executor must be non-null");
} }
synchronized (sCarrierPrivilegeListeners) { synchronized (sCarrierPrivilegeCallbacks) {
WeakReference<CarrierPrivilegesListenerWrapper> existing = WeakReference<CarrierPrivilegesCallbackWrapper> existing =
sCarrierPrivilegeListeners.get(listener); sCarrierPrivilegeCallbacks.get(listener);
if (existing != null && existing.get() != null) { if (existing != null && existing.get() != null) {
Log.d(TAG, "addCarrierPrivilegesListener: listener already registered"); Log.d(TAG, "addCarrierPrivilegesListener: listener already registered");
return; return;
} }
CarrierPrivilegesListenerWrapper wrapper = CarrierPrivilegesCallbackWrapper wrapper =
new CarrierPrivilegesListenerWrapper(listener, executor); new CarrierPrivilegesCallbackWrapper(listener, executor);
sCarrierPrivilegeListeners.put(listener, new WeakReference<>(wrapper)); sCarrierPrivilegeCallbacks.put(listener, new WeakReference<>(wrapper));
try { try {
sRegistry.addCarrierPrivilegesListener( sRegistry.addCarrierPrivilegesCallback(
logicalSlotIndex, logicalSlotIndex,
wrapper, wrapper,
mContext.getOpPackageName(), mContext.getOpPackageName(),
@@ -1331,19 +1383,84 @@ public class TelephonyRegistryManager {
* Unregisters a {@link CarrierPrivilegesListener}. * Unregisters a {@link CarrierPrivilegesListener}.
* *
* @param listener The callback to unregister * @param listener The callback to unregister
*
* @deprecated Use {@link #removeCarrierPrivilegesCallback} instead. The callback will prior
* to API finalization.
*/ */
@Deprecated
public void removeCarrierPrivilegesListener(@NonNull CarrierPrivilegesListener listener) { public void removeCarrierPrivilegesListener(@NonNull CarrierPrivilegesListener listener) {
if (listener == null) { if (listener == null) {
throw new IllegalArgumentException("listener must be non-null"); throw new IllegalArgumentException("listener must be non-null");
} }
synchronized (sCarrierPrivilegeListeners) { synchronized (sCarrierPrivilegeCallbacks) {
WeakReference<CarrierPrivilegesListenerWrapper> ref = WeakReference<CarrierPrivilegesCallbackWrapper> ref =
sCarrierPrivilegeListeners.remove(listener); sCarrierPrivilegeCallbacks.remove(listener);
if (ref == null) return; if (ref == null) return;
CarrierPrivilegesListenerWrapper wrapper = ref.get(); CarrierPrivilegesCallbackWrapper wrapper = ref.get();
if (wrapper == null) return; if (wrapper == null) return;
try { try {
sRegistry.removeCarrierPrivilegesListener(wrapper, mContext.getOpPackageName()); sRegistry.removeCarrierPrivilegesCallback(wrapper, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
/**
* 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
*/
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
*/
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) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
} }
@@ -1359,15 +1476,33 @@ public class TelephonyRegistryManager {
*/ */
public void notifyCarrierPrivilegesChanged( public void notifyCarrierPrivilegesChanged(
int logicalSlotIndex, int logicalSlotIndex,
@NonNull List<String> privilegedPackageNames, @NonNull Set<String> privilegedPackageNames,
@NonNull int[] privilegedUids) { @NonNull Set<Integer> privilegedUids) {
if (privilegedPackageNames == null || privilegedUids == null) { if (privilegedPackageNames == null || privilegedUids == null) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"privilegedPackageNames and privilegedUids must be non-null"); "privilegedPackageNames and privilegedUids must be non-null");
} }
try { try {
sRegistry.notifyCarrierPrivilegesChanged( // AIDL doesn't support Set yet. Convert Set to List/Array
logicalSlotIndex, privilegedPackageNames, privilegedUids); 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}
*/
public void notifyCarrierServiceChanged(int logicalSlotIndex, @Nullable String packageName,
int uid) {
try {
sRegistry.notifyCarrierServiceChanged(logicalSlotIndex, packageName, uid);
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
} }

View File

@@ -16,7 +16,8 @@
package com.android.internal.telephony; package com.android.internal.telephony;
oneway interface ICarrierPrivilegesListener { oneway interface ICarrierPrivilegesCallback {
void onCarrierPrivilegesChanged( void onCarrierPrivilegesChanged(
in List<String> privilegedPackageNames, in int[] privilegedUids); in List<String> privilegedPackageNames, in int[] privilegedUids);
void onCarrierServiceChanged(in String carrierServicePackageName, in int carrierServiceUid);
} }

View File

@@ -32,7 +32,7 @@ import android.telephony.PreciseDataConnectionState;
import android.telephony.ServiceState; import android.telephony.ServiceState;
import android.telephony.SignalStrength; import android.telephony.SignalStrength;
import android.telephony.emergency.EmergencyNumber; import android.telephony.emergency.EmergencyNumber;
import com.android.internal.telephony.ICarrierPrivilegesListener; import com.android.internal.telephony.ICarrierPrivilegesCallback;
import com.android.internal.telephony.IPhoneStateListener; import com.android.internal.telephony.IPhoneStateListener;
import com.android.internal.telephony.IOnSubscriptionsChangedListener; import com.android.internal.telephony.IOnSubscriptionsChangedListener;
@@ -102,9 +102,11 @@ interface ITelephonyRegistry {
void notifyLinkCapacityEstimateChanged(in int phoneId, in int subId, void notifyLinkCapacityEstimateChanged(in int phoneId, in int subId,
in List<LinkCapacityEstimate> linkCapacityEstimateList); in List<LinkCapacityEstimate> linkCapacityEstimateList);
void addCarrierPrivilegesListener( void addCarrierPrivilegesCallback(
int phoneId, ICarrierPrivilegesListener callback, String pkg, String featureId); int phoneId, ICarrierPrivilegesCallback callback, String pkg, String featureId);
void removeCarrierPrivilegesListener(ICarrierPrivilegesListener callback, String pkg); void removeCarrierPrivilegesCallback(ICarrierPrivilegesCallback callback, String pkg);
void notifyCarrierPrivilegesChanged( void notifyCarrierPrivilegesChanged(
int phoneId, in List<String> privilegedPackageNames, in int[] privilegedUids); int phoneId, in List<String> privilegedPackageNames, in int[] privilegedUids);
void notifyCarrierServiceChanged(int phoneId, in String packageName, int uid);
} }

View File

@@ -91,7 +91,7 @@ import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats; import com.android.internal.app.IBatteryStats;
import com.android.internal.telephony.ICarrierPrivilegesListener; import com.android.internal.telephony.ICarrierPrivilegesCallback;
import com.android.internal.telephony.IOnSubscriptionsChangedListener; import com.android.internal.telephony.IOnSubscriptionsChangedListener;
import com.android.internal.telephony.IPhoneStateListener; import com.android.internal.telephony.IPhoneStateListener;
import com.android.internal.telephony.ITelephonyRegistry; import com.android.internal.telephony.ITelephonyRegistry;
@@ -153,7 +153,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
IPhoneStateListener callback; IPhoneStateListener callback;
IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback; IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback;
IOnSubscriptionsChangedListener onOpportunisticSubscriptionsChangedListenerCallback; IOnSubscriptionsChangedListener onOpportunisticSubscriptionsChangedListenerCallback;
ICarrierPrivilegesListener carrierPrivilegesListener; ICarrierPrivilegesCallback carrierPrivilegesCallback;
int callerUid; int callerUid;
int callerPid; int callerPid;
@@ -178,8 +178,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
return (onOpportunisticSubscriptionsChangedListenerCallback != null); return (onOpportunisticSubscriptionsChangedListenerCallback != null);
} }
boolean matchCarrierPrivilegesListener() { boolean matchCarrierPrivilegesCallback() {
return carrierPrivilegesListener != null; return carrierPrivilegesCallback != null;
} }
boolean canReadCallLog() { boolean canReadCallLog() {
@@ -199,7 +199,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
+ onSubscriptionsChangedListenerCallback + onSubscriptionsChangedListenerCallback
+ " onOpportunisticSubscriptionsChangedListenererCallback=" + " onOpportunisticSubscriptionsChangedListenererCallback="
+ onOpportunisticSubscriptionsChangedListenerCallback + onOpportunisticSubscriptionsChangedListenerCallback
+ " carrierPrivilegesListener=" + carrierPrivilegesListener + " carrierPrivilegesCallback=" + carrierPrivilegesCallback
+ " subId=" + subId + " phoneId=" + phoneId + " events=" + eventList + "}"; + " subId=" + subId + " phoneId=" + phoneId + " events=" + eventList + "}";
} }
} }
@@ -414,7 +414,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mPreciseDataConnectionStates; mPreciseDataConnectionStates;
/** Per-phoneId snapshot of privileged packages (names + UIDs). */ /** Per-phoneId snapshot of privileged packages (names + UIDs). */
private List<Pair<List<String>, int[]>> mCarrierPrivilegeStates; @NonNull private List<Pair<List<String>, int[]>> mCarrierPrivilegeStates;
/** Per-phoneId of CarrierService (PackageName, UID) pair. */
@NonNull private List<Pair<String, Integer>> mCarrierServiceStates;
/** /**
* Support backward compatibility for {@link android.telephony.TelephonyDisplayInfo}. * Support backward compatibility for {@link android.telephony.TelephonyDisplayInfo}.
@@ -705,6 +707,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
cutListToSize(mPhysicalChannelConfigs, mNumPhones); cutListToSize(mPhysicalChannelConfigs, mNumPhones);
cutListToSize(mLinkCapacityEstimateLists, mNumPhones); cutListToSize(mLinkCapacityEstimateLists, mNumPhones);
cutListToSize(mCarrierPrivilegeStates, mNumPhones); cutListToSize(mCarrierPrivilegeStates, mNumPhones);
cutListToSize(mCarrierServiceStates, mNumPhones);
return; return;
} }
@@ -746,6 +749,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mAllowedNetworkTypeValue[i] = -1; mAllowedNetworkTypeValue[i] = -1;
mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST); mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST);
mCarrierPrivilegeStates.add(i, new Pair<>(Collections.emptyList(), new int[0])); mCarrierPrivilegeStates.add(i, new Pair<>(Collections.emptyList(), new int[0]));
mCarrierServiceStates.add(i, new Pair<>(null, Process.INVALID_UID));
} }
} }
} }
@@ -813,6 +817,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mDataEnabledReason = new int[numPhones]; mDataEnabledReason = new int[numPhones];
mLinkCapacityEstimateLists = new ArrayList<>(); mLinkCapacityEstimateLists = new ArrayList<>();
mCarrierPrivilegeStates = new ArrayList<>(); mCarrierPrivilegeStates = new ArrayList<>();
mCarrierServiceStates = new ArrayList<>();
for (int i = 0; i < numPhones; i++) { for (int i = 0; i < numPhones; i++) {
mCallState[i] = TelephonyManager.CALL_STATE_IDLE; mCallState[i] = TelephonyManager.CALL_STATE_IDLE;
@@ -851,6 +856,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mAllowedNetworkTypeValue[i] = -1; mAllowedNetworkTypeValue[i] = -1;
mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST); mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST);
mCarrierPrivilegeStates.add(i, new Pair<>(Collections.emptyList(), new int[0])); mCarrierPrivilegeStates.add(i, new Pair<>(Collections.emptyList(), new int[0]));
mCarrierServiceStates.add(i, new Pair<>(null, Process.INVALID_UID));
} }
mAppOps = mContext.getSystemService(AppOpsManager.class); mAppOps = mContext.getSystemService(AppOpsManager.class);
@@ -2784,16 +2790,16 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
} }
@Override @Override
public void addCarrierPrivilegesListener( public void addCarrierPrivilegesCallback(
int phoneId, int phoneId,
ICarrierPrivilegesListener callback, @NonNull ICarrierPrivilegesCallback callback,
String callingPackage, @NonNull String callingPackage,
String callingFeatureId) { @NonNull String callingFeatureId) {
int callerUserId = UserHandle.getCallingUserId(); int callerUserId = UserHandle.getCallingUserId();
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
mContext.enforceCallingOrSelfPermission( mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
"addCarrierPrivilegesListener"); "addCarrierPrivilegesCallback");
if (VDBG) { if (VDBG) {
log( log(
"listen carrier privs: E pkg=" + pii(callingPackage) + " phoneId=" + phoneId "listen carrier privs: E pkg=" + pii(callingPackage) + " phoneId=" + phoneId
@@ -2813,7 +2819,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
if (r == null) return; if (r == null) return;
r.context = mContext; r.context = mContext;
r.carrierPrivilegesListener = callback; r.carrierPrivilegesCallback = callback;
r.callingPackage = callingPackage; r.callingPackage = callingPackage;
r.callingFeatureId = callingFeatureId; r.callingFeatureId = callingFeatureId;
r.callerUid = Binder.getCallingUid(); r.callerUid = Binder.getCallingUid();
@@ -2825,10 +2831,18 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
} }
Pair<List<String>, int[]> state = mCarrierPrivilegeStates.get(phoneId); Pair<List<String>, int[]> state = mCarrierPrivilegeStates.get(phoneId);
Pair<String, Integer> carrierServiceState = mCarrierServiceStates.get(phoneId);
try { try {
r.carrierPrivilegesListener.onCarrierPrivilegesChanged( if (r.matchCarrierPrivilegesCallback()) {
Collections.unmodifiableList(state.first), // Here, two callbacks are triggered in quick succession on the same binder.
Arrays.copyOf(state.second, state.second.length)); // In typical case, we expect the callers to care about only one or the other.
r.carrierPrivilegesCallback.onCarrierPrivilegesChanged(
Collections.unmodifiableList(state.first),
Arrays.copyOf(state.second, state.second.length));
r.carrierPrivilegesCallback.onCarrierServiceChanged(carrierServiceState.first,
carrierServiceState.second);
}
} catch (RemoteException ex) { } catch (RemoteException ex) {
remove(r.binder); remove(r.binder);
} }
@@ -2836,12 +2850,12 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
} }
@Override @Override
public void removeCarrierPrivilegesListener( public void removeCarrierPrivilegesCallback(
ICarrierPrivilegesListener callback, String callingPackage) { @NonNull ICarrierPrivilegesCallback callback, @NonNull String callingPackage) {
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
mContext.enforceCallingOrSelfPermission( mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
"removeCarrierPrivilegesListener"); "removeCarrierPrivilegesCallback");
remove(callback.asBinder()); remove(callback.asBinder());
} }
@@ -2866,13 +2880,13 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
for (Record r : mRecords) { for (Record r : mRecords) {
// Listeners are per-slot, not per-subscription. This is to provide a stable // Listeners are per-slot, not per-subscription. This is to provide a stable
// view across SIM profile switches. // view across SIM profile switches.
if (!r.matchCarrierPrivilegesListener() if (!r.matchCarrierPrivilegesCallback()
|| !idMatch(r, SubscriptionManager.INVALID_SUBSCRIPTION_ID, phoneId)) { || !idMatch(r, SubscriptionManager.INVALID_SUBSCRIPTION_ID, phoneId)) {
continue; continue;
} }
try { try {
// Make sure even in-process listeners can't modify the values. // Make sure even in-process listeners can't modify the values.
r.carrierPrivilegesListener.onCarrierPrivilegesChanged( r.carrierPrivilegesCallback.onCarrierPrivilegesChanged(
Collections.unmodifiableList(privilegedPackageNames), Collections.unmodifiableList(privilegedPackageNames),
Arrays.copyOf(privilegedUids, privilegedUids.length)); Arrays.copyOf(privilegedUids, privilegedUids.length));
} catch (RemoteException ex) { } catch (RemoteException ex) {
@@ -2883,6 +2897,34 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
} }
} }
@Override
public void notifyCarrierServiceChanged(int phoneId, @Nullable String packageName, int uid) {
if (!checkNotifyPermission("notifyCarrierServiceChanged")) return;
if (!validatePhoneId(phoneId)) return;
if (VDBG) {
log("notifyCarrierServiceChanged: phoneId=" + phoneId
+ ", package=" + pii(packageName) + ", uid=" + uid);
}
synchronized (mRecords) {
mCarrierServiceStates.set(
phoneId, new Pair<>(packageName, uid));
for (Record r : mRecords) {
// Listeners are per-slot, not per-subscription.
if (!r.matchCarrierPrivilegesCallback()
|| !idMatch(r, SubscriptionManager.INVALID_SUBSCRIPTION_ID, phoneId)) {
continue;
}
try {
r.carrierPrivilegesCallback.onCarrierServiceChanged(packageName, uid);
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
}
handleRemoveListLocked();
}
}
@NeverCompile // Avoid size overhead of debugging code. @NeverCompile // Avoid size overhead of debugging code.
@Override @Override
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
@@ -2938,6 +2980,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
pw.println( pw.println(
"mCarrierPrivilegeState=<packages=" + pii(carrierPrivilegeState.first) "mCarrierPrivilegeState=<packages=" + pii(carrierPrivilegeState.first)
+ ", uids=" + Arrays.toString(carrierPrivilegeState.second) + ">"); + ", uids=" + Arrays.toString(carrierPrivilegeState.second) + ">");
Pair<String, Integer> carrierServiceState = mCarrierServiceStates.get(i);
pw.println("mCarrierServiceState=<package=" + pii(carrierServiceState.first)
+ ", uid=" + carrierServiceState.second + ">");
pw.decreaseIndent(); pw.decreaseIndent();
} }

View File

@@ -16790,7 +16790,10 @@ public class TelephonyManager {
* Callback to listen for when the set of packages with carrier privileges for a SIM changes. * Callback to listen for when the set of packages with carrier privileges for a SIM changes.
* *
* @hide * @hide
* @deprecated Use {@link CarrierPrivilegesCallback} instead. This API will be removed soon
* prior to API finalization.
*/ */
@Deprecated
@SystemApi @SystemApi
public interface CarrierPrivilegesListener { public interface CarrierPrivilegesListener {
/** /**
@@ -16809,6 +16812,54 @@ public class TelephonyManager {
@NonNull List<String> privilegedPackageNames, @NonNull int[] privilegedUids); @NonNull List<String> privilegedPackageNames, @NonNull int[] privilegedUids);
} }
/**
* Callbacks to listen for when the set of packages with carrier privileges for a SIM changes.
*
* <p>Of note, when multiple callbacks are registered, they may be triggered one after another.
* The ordering of them is not guaranteed and thus should not be depend on.
*
* @hide
*/
@SystemApi
public interface CarrierPrivilegesCallback {
/**
* Called when the set of packages with carrier privileges has changed.
*
* <p>Of note, this callback will <b>not</b> be fired if a carrier triggers a SIM profile
* switch and the same set of packages remains privileged after the switch.
*
* <p>At registration, the callback will receive the current set of privileged packages.
*
* @param privilegedPackageNames The updated set of package names that have carrier
* privileges
* @param privilegedUids The updated set of UIDs that have carrier privileges
*/
void onCarrierPrivilegesChanged(
@NonNull Set<String> privilegedPackageNames, @NonNull Set<Integer> privilegedUids);
/**
* Called when the {@link CarrierService} for the current user profile has changed.
*
* <p>This method does nothing by default. Clients that are interested in the carrier
* service change should override this method to get package name and UID info.
*
* <p>At registration, the callback will receive the current carrier service info.
*
* <p>Of note, this callback will <b>not</b> be fired if a carrier triggers a SIM profile
* switch and the same carrier service remains after switch.
*
* @param carrierServicePackageName package name of the {@link CarrierService}. May be
* {@code null} when no carrier service is detected.
* @param carrierServiceUid UID of the {@link CarrierService}. May be
* {@link android.os.Process#INVALID_UID} if no carrier
* service is detected.
*/
default void onCarrierServiceChanged(
@Nullable String carrierServicePackageName, int carrierServiceUid) {
// do nothing by default
}
}
/** /**
* Registers a {@link CarrierPrivilegesListener} on the given {@code logicalSlotIndex} to * Registers a {@link CarrierPrivilegesListener} on the given {@code logicalSlotIndex} to
* receive callbacks when the set of packages with carrier privileges changes. The callback will * receive callbacks when the set of packages with carrier privileges changes. The callback will
@@ -16818,7 +16869,10 @@ public class TelephonyManager {
* @param executor The executor where {@code listener} will be invoked * @param executor The executor where {@code listener} will be invoked
* @param listener The callback to register * @param listener The callback to register
* @hide * @hide
* @deprecated Use {@link #unregisterCarrierPrivilegesCallback} instead. This API will be
* removed prior to API finalization.
*/ */
@Deprecated
@SystemApi @SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void addCarrierPrivilegesListener( public void addCarrierPrivilegesListener(
@@ -16842,7 +16896,10 @@ public class TelephonyManager {
* Unregisters an existing {@link CarrierPrivilegesListener}. * Unregisters an existing {@link CarrierPrivilegesListener}.
* *
* @hide * @hide
* @deprecated Use {@link #unregisterCarrierPrivilegesCallback} instead. This API will be
* removed prior to API finalization.
*/ */
@Deprecated
@SystemApi @SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void removeCarrierPrivilegesListener(@NonNull CarrierPrivilegesListener listener) { public void removeCarrierPrivilegesListener(@NonNull CarrierPrivilegesListener listener) {
@@ -16890,4 +16947,53 @@ public class TelephonyManager {
ex.rethrowAsRuntimeException(); ex.rethrowAsRuntimeException();
} }
} }
/**
* 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 callback} will be invoked
* @param callback The callback to register
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void registerCarrierPrivilegesCallback(
int logicalSlotIndex,
@NonNull @CallbackExecutor Executor executor,
@NonNull CarrierPrivilegesCallback callback) {
if (mContext == null) {
throw new IllegalStateException("Telephony service is null");
} else if (executor == null || callback == null) {
throw new IllegalArgumentException(
"CarrierPrivilegesCallback and executor must be non-null");
}
mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class);
if (mTelephonyRegistryMgr == null) {
throw new IllegalStateException("Telephony registry service is null");
}
mTelephonyRegistryMgr.addCarrierPrivilegesCallback(logicalSlotIndex, executor, callback);
}
/**
* Unregisters an existing {@link CarrierPrivilegesCallback}.
*
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void unregisterCarrierPrivilegesCallback(@NonNull CarrierPrivilegesCallback callback) {
if (mContext == null) {
throw new IllegalStateException("Telephony service is null");
} else if (callback == null) {
throw new IllegalArgumentException("CarrierPrivilegesCallback must be non-null");
}
mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class);
if (mTelephonyRegistryMgr == null) {
throw new IllegalStateException("Telephony registry service is null");
}
mTelephonyRegistryMgr.removeCarrierPrivilegesCallback(callback);
}
} }