Loading core/java/android/telephony/TelephonyRegistryManager.java +169 −34 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ 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; Loading @@ -36,6 +37,7 @@ import android.telephony.Annotation.PreciseDisconnectCauses; import android.telephony.Annotation.RadioPowerState; import android.telephony.Annotation.SimActivationState; import android.telephony.Annotation.SrvccState; import android.telephony.TelephonyManager.CarrierPrivilegesCallback; import android.telephony.TelephonyManager.CarrierPrivilegesListener; import android.telephony.emergency.EmergencyNumber; import android.telephony.ims.ImsReasonInfo; Loading @@ -44,17 +46,19 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; 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.ITelephonyRegistry; import java.lang.ref.WeakReference; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.WeakHashMap; import java.util.concurrent.Executor; import java.util.stream.Collectors; /** * A centralized place to notify telephony related status changes, e.g, {@link ServiceState} update Loading Loading @@ -1258,19 +1262,32 @@ public class TelephonyRegistryManager { 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 { private final WeakReference<CarrierPrivilegesListener> mListener; private final Executor mExecutor; // Either mListener or mCallback may be null, never both @Nullable private final WeakReference<CarrierPrivilegesListener> mListener; @Nullable private final WeakReference<CarrierPrivilegesCallback> mCallback; @NonNull private final Executor mExecutor; CarrierPrivilegesCallbackWrapper( @NonNull CarrierPrivilegesCallback callback, @NonNull Executor executor) { mListener = null; mCallback = new WeakReference<>(callback); mExecutor = executor; } CarrierPrivilegesListenerWrapper(CarrierPrivilegesListener listener, Executor executor) { CarrierPrivilegesCallbackWrapper( @NonNull CarrierPrivilegesListener listener, @NonNull Executor executor) { mListener = new WeakReference<>(listener); mCallback = null; mExecutor = executor; } @Override public void onCarrierPrivilegesChanged( List<String> privilegedPackageNames, int[] privilegedUids) { @NonNull List<String> privilegedPackageNames, @NonNull int[] privilegedUids) { if (mListener != null) { Binder.withCleanCallingIdentity( () -> executeSafely( Loading @@ -1280,12 +1297,43 @@ public class TelephonyRegistryManager { 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") private static final WeakHashMap< CarrierPrivilegesListener, WeakReference<CarrierPrivilegesListenerWrapper>> sCarrierPrivilegeListeners = new WeakHashMap<>(); // TODO(b/216549778): Change the map key to CarrierPrivilegesCallback once all clients switch to // CarrierPrivilegesCallback. Before that, the key is either CarrierPrivilegesCallback or // CarrierPrivilegesListener, no logic actually depends on the type. @NonNull @GuardedBy("sCarrierPrivilegeCallbacks") private static final WeakHashMap<Object, WeakReference<CarrierPrivilegesCallbackWrapper>> sCarrierPrivilegeCallbacks = new WeakHashMap<>(); /** * Registers a {@link CarrierPrivilegesListener} on the given {@code logicalSlotIndex} to Loading @@ -1295,7 +1343,11 @@ public class TelephonyRegistryManager { * @param logicalSlotIndex The SIM slot to listen on * @param executor The executor where {@code listener} will be invoked * @param listener The callback to register * * @deprecated Use {@link #addCarrierPrivilegesCallback} instead. This API will be removed * prior to API finalization. */ @Deprecated public void addCarrierPrivilegesListener( int logicalSlotIndex, @NonNull @CallbackExecutor Executor executor, Loading @@ -1303,18 +1355,18 @@ public class TelephonyRegistryManager { if (listener == null || executor == null) { throw new IllegalArgumentException("listener and executor must be non-null"); } synchronized (sCarrierPrivilegeListeners) { WeakReference<CarrierPrivilegesListenerWrapper> existing = sCarrierPrivilegeListeners.get(listener); synchronized (sCarrierPrivilegeCallbacks) { WeakReference<CarrierPrivilegesCallbackWrapper> existing = sCarrierPrivilegeCallbacks.get(listener); if (existing != null && existing.get() != null) { Log.d(TAG, "addCarrierPrivilegesListener: listener already registered"); return; } CarrierPrivilegesListenerWrapper wrapper = new CarrierPrivilegesListenerWrapper(listener, executor); sCarrierPrivilegeListeners.put(listener, new WeakReference<>(wrapper)); CarrierPrivilegesCallbackWrapper wrapper = new CarrierPrivilegesCallbackWrapper(listener, executor); sCarrierPrivilegeCallbacks.put(listener, new WeakReference<>(wrapper)); try { sRegistry.addCarrierPrivilegesListener( sRegistry.addCarrierPrivilegesCallback( logicalSlotIndex, wrapper, mContext.getOpPackageName(), Loading @@ -1329,19 +1381,84 @@ public class TelephonyRegistryManager { * Unregisters a {@link CarrierPrivilegesListener}. * * @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) { if (listener == null) { throw new IllegalArgumentException("listener must be non-null"); } synchronized (sCarrierPrivilegeListeners) { WeakReference<CarrierPrivilegesListenerWrapper> ref = sCarrierPrivilegeListeners.remove(listener); synchronized (sCarrierPrivilegeCallbacks) { WeakReference<CarrierPrivilegesCallbackWrapper> ref = sCarrierPrivilegeCallbacks.remove(listener); if (ref == null) return; CarrierPrivilegesListenerWrapper wrapper = ref.get(); CarrierPrivilegesCallbackWrapper wrapper = ref.get(); if (wrapper == null) return; 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) { throw e.rethrowFromSystemServer(); } Loading @@ -1357,15 +1474,33 @@ public class TelephonyRegistryManager { */ public void notifyCarrierPrivilegesChanged( int logicalSlotIndex, @NonNull List<String> privilegedPackageNames, @NonNull int[] privilegedUids) { @NonNull Set<String> privilegedPackageNames, @NonNull Set<Integer> privilegedUids) { if (privilegedPackageNames == null || privilegedUids == null) { throw new IllegalArgumentException( "privilegedPackageNames and privilegedUids must be non-null"); } try { sRegistry.notifyCarrierPrivilegesChanged( logicalSlotIndex, privilegedPackageNames, privilegedUids); // 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} */ public void notifyCarrierServiceChanged(int logicalSlotIndex, @Nullable String packageName, int uid) { try { sRegistry.notifyCarrierServiceChanged(logicalSlotIndex, packageName, uid); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading core/java/com/android/internal/telephony/ICarrierPrivilegesListener.aidl→core/java/com/android/internal/telephony/ICarrierPrivilegesCallback.aidl +2 −1 Original line number Diff line number Diff line Loading @@ -16,7 +16,8 @@ package com.android.internal.telephony; oneway interface ICarrierPrivilegesListener { oneway interface ICarrierPrivilegesCallback { void onCarrierPrivilegesChanged( in List<String> privilegedPackageNames, in int[] privilegedUids); void onCarrierServiceChanged(in String carrierServicePackageName, in int carrierServiceUid); } core/java/com/android/internal/telephony/ITelephonyRegistry.aidl +6 −4 Original line number Diff line number Diff line Loading @@ -32,7 +32,7 @@ import android.telephony.PreciseDataConnectionState; import android.telephony.ServiceState; import android.telephony.SignalStrength; 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.IOnSubscriptionsChangedListener; Loading Loading @@ -102,9 +102,11 @@ interface ITelephonyRegistry { void notifyLinkCapacityEstimateChanged(in int phoneId, in int subId, in List<LinkCapacityEstimate> linkCapacityEstimateList); void addCarrierPrivilegesListener( int phoneId, ICarrierPrivilegesListener callback, String pkg, String featureId); void removeCarrierPrivilegesListener(ICarrierPrivilegesListener callback, String pkg); void addCarrierPrivilegesCallback( int phoneId, ICarrierPrivilegesCallback callback, String pkg, String featureId); void removeCarrierPrivilegesCallback(ICarrierPrivilegesCallback callback, String pkg); void notifyCarrierPrivilegesChanged( int phoneId, in List<String> privilegedPackageNames, in int[] privilegedUids); void notifyCarrierServiceChanged(int phoneId, in String packageName, int uid); } services/core/java/com/android/server/TelephonyRegistry.java +71 −26 Original line number Diff line number Diff line Loading @@ -91,7 +91,7 @@ import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; 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.IPhoneStateListener; import com.android.internal.telephony.ITelephonyRegistry; Loading Loading @@ -151,7 +151,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { IPhoneStateListener callback; IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback; IOnSubscriptionsChangedListener onOpportunisticSubscriptionsChangedListenerCallback; ICarrierPrivilegesListener carrierPrivilegesListener; ICarrierPrivilegesCallback carrierPrivilegesCallback; int callerUid; int callerPid; Loading @@ -176,8 +176,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { return (onOpportunisticSubscriptionsChangedListenerCallback != null); } boolean matchCarrierPrivilegesListener() { return carrierPrivilegesListener != null; boolean matchCarrierPrivilegesCallback() { return carrierPrivilegesCallback != null; } boolean canReadCallLog() { Loading @@ -197,7 +197,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { + onSubscriptionsChangedListenerCallback + " onOpportunisticSubscriptionsChangedListenererCallback=" + onOpportunisticSubscriptionsChangedListenerCallback + " carrierPrivilegesListener=" + carrierPrivilegesListener + " carrierPrivilegesCallback=" + carrierPrivilegesCallback + " subId=" + subId + " phoneId=" + phoneId + " events=" + eventList + "}"; } } Loading Loading @@ -412,7 +412,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mPreciseDataConnectionStates; /** 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}. Loading Loading @@ -702,6 +704,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { cutListToSize(mPhysicalChannelConfigs, mNumPhones); cutListToSize(mLinkCapacityEstimateLists, mNumPhones); cutListToSize(mCarrierPrivilegeStates, mNumPhones); cutListToSize(mCarrierServiceStates, mNumPhones); return; } Loading Loading @@ -743,6 +746,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mAllowedNetworkTypeValue[i] = -1; mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST); mCarrierPrivilegeStates.add(i, new Pair<>(Collections.emptyList(), new int[0])); mCarrierServiceStates.add(i, new Pair<>(null, Process.INVALID_UID)); } } Loading Loading @@ -809,6 +813,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mDataEnabledReason = new int[numPhones]; mLinkCapacityEstimateLists = new ArrayList<>(); mCarrierPrivilegeStates = new ArrayList<>(); mCarrierServiceStates = new ArrayList<>(); for (int i = 0; i < numPhones; i++) { mCallState[i] = TelephonyManager.CALL_STATE_IDLE; Loading Loading @@ -847,6 +852,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mAllowedNetworkTypeValue[i] = -1; mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST); mCarrierPrivilegeStates.add(i, new Pair<>(Collections.emptyList(), new int[0])); mCarrierServiceStates.add(i, new Pair<>(null, Process.INVALID_UID)); } mAppOps = mContext.getSystemService(AppOpsManager.class); Loading Loading @@ -2780,16 +2786,16 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } @Override public void addCarrierPrivilegesListener( public void addCarrierPrivilegesCallback( int phoneId, ICarrierPrivilegesListener callback, String callingPackage, String callingFeatureId) { @NonNull ICarrierPrivilegesCallback callback, @NonNull String callingPackage, @NonNull String callingFeatureId) { int callerUserId = UserHandle.getCallingUserId(); mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); mContext.enforceCallingOrSelfPermission( android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, "addCarrierPrivilegesListener"); "addCarrierPrivilegesCallback"); if (VDBG) { log( "listen carrier privs: E pkg=" + pii(callingPackage) + " phoneId=" + phoneId Loading @@ -2809,7 +2815,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { if (r == null) return; r.context = mContext; r.carrierPrivilegesListener = callback; r.carrierPrivilegesCallback = callback; r.callingPackage = callingPackage; r.callingFeatureId = callingFeatureId; r.callerUid = Binder.getCallingUid(); Loading @@ -2821,10 +2827,18 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } Pair<List<String>, int[]> state = mCarrierPrivilegeStates.get(phoneId); Pair<String, Integer> carrierServiceState = mCarrierServiceStates.get(phoneId); try { r.carrierPrivilegesListener.onCarrierPrivilegesChanged( if (r.matchCarrierPrivilegesCallback()) { // Here, two callbacks are triggered in quick succession on the same binder. // 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) { remove(r.binder); } Loading @@ -2832,12 +2846,12 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } @Override public void removeCarrierPrivilegesListener( ICarrierPrivilegesListener callback, String callingPackage) { public void removeCarrierPrivilegesCallback( @NonNull ICarrierPrivilegesCallback callback, @NonNull String callingPackage) { mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); mContext.enforceCallingOrSelfPermission( android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, "removeCarrierPrivilegesListener"); "removeCarrierPrivilegesCallback"); remove(callback.asBinder()); } Loading @@ -2860,13 +2874,13 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { for (Record r : mRecords) { // Listeners are per-slot, not per-subscription. This is to provide a stable // view across SIM profile switches. if (!r.matchCarrierPrivilegesListener() if (!r.matchCarrierPrivilegesCallback() || !idMatch(r, SubscriptionManager.INVALID_SUBSCRIPTION_ID, phoneId)) { continue; } try { // Make sure even in-process listeners can't modify the values. r.carrierPrivilegesListener.onCarrierPrivilegesChanged( r.carrierPrivilegesCallback.onCarrierPrivilegesChanged( Collections.unmodifiableList(privilegedPackageNames), Arrays.copyOf(privilegedUids, privilegedUids.length)); } catch (RemoteException ex) { Loading @@ -2877,6 +2891,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(); } } @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); Loading Loading @@ -2931,6 +2973,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { pw.println( "mCarrierPrivilegeState=<packages=" + pii(carrierPrivilegeState.first) + ", uids=" + Arrays.toString(carrierPrivilegeState.second) + ">"); Pair<String, Integer> carrierServiceState = mCarrierServiceStates.get(i); pw.println("mCarrierServiceState=<package=" + pii(carrierServiceState.first) + ", uid=" + carrierServiceState.second + ">"); pw.decreaseIndent(); } Loading telephony/java/android/telephony/TelephonyManager.java +22 −4 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
core/java/android/telephony/TelephonyRegistryManager.java +169 −34 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ 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; Loading @@ -36,6 +37,7 @@ import android.telephony.Annotation.PreciseDisconnectCauses; import android.telephony.Annotation.RadioPowerState; import android.telephony.Annotation.SimActivationState; import android.telephony.Annotation.SrvccState; import android.telephony.TelephonyManager.CarrierPrivilegesCallback; import android.telephony.TelephonyManager.CarrierPrivilegesListener; import android.telephony.emergency.EmergencyNumber; import android.telephony.ims.ImsReasonInfo; Loading @@ -44,17 +46,19 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; 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.ITelephonyRegistry; import java.lang.ref.WeakReference; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.WeakHashMap; import java.util.concurrent.Executor; import java.util.stream.Collectors; /** * A centralized place to notify telephony related status changes, e.g, {@link ServiceState} update Loading Loading @@ -1258,19 +1262,32 @@ public class TelephonyRegistryManager { 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 { private final WeakReference<CarrierPrivilegesListener> mListener; private final Executor mExecutor; // Either mListener or mCallback may be null, never both @Nullable private final WeakReference<CarrierPrivilegesListener> mListener; @Nullable private final WeakReference<CarrierPrivilegesCallback> mCallback; @NonNull private final Executor mExecutor; CarrierPrivilegesCallbackWrapper( @NonNull CarrierPrivilegesCallback callback, @NonNull Executor executor) { mListener = null; mCallback = new WeakReference<>(callback); mExecutor = executor; } CarrierPrivilegesListenerWrapper(CarrierPrivilegesListener listener, Executor executor) { CarrierPrivilegesCallbackWrapper( @NonNull CarrierPrivilegesListener listener, @NonNull Executor executor) { mListener = new WeakReference<>(listener); mCallback = null; mExecutor = executor; } @Override public void onCarrierPrivilegesChanged( List<String> privilegedPackageNames, int[] privilegedUids) { @NonNull List<String> privilegedPackageNames, @NonNull int[] privilegedUids) { if (mListener != null) { Binder.withCleanCallingIdentity( () -> executeSafely( Loading @@ -1280,12 +1297,43 @@ public class TelephonyRegistryManager { 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") private static final WeakHashMap< CarrierPrivilegesListener, WeakReference<CarrierPrivilegesListenerWrapper>> sCarrierPrivilegeListeners = new WeakHashMap<>(); // TODO(b/216549778): Change the map key to CarrierPrivilegesCallback once all clients switch to // CarrierPrivilegesCallback. Before that, the key is either CarrierPrivilegesCallback or // CarrierPrivilegesListener, no logic actually depends on the type. @NonNull @GuardedBy("sCarrierPrivilegeCallbacks") private static final WeakHashMap<Object, WeakReference<CarrierPrivilegesCallbackWrapper>> sCarrierPrivilegeCallbacks = new WeakHashMap<>(); /** * Registers a {@link CarrierPrivilegesListener} on the given {@code logicalSlotIndex} to Loading @@ -1295,7 +1343,11 @@ public class TelephonyRegistryManager { * @param logicalSlotIndex The SIM slot to listen on * @param executor The executor where {@code listener} will be invoked * @param listener The callback to register * * @deprecated Use {@link #addCarrierPrivilegesCallback} instead. This API will be removed * prior to API finalization. */ @Deprecated public void addCarrierPrivilegesListener( int logicalSlotIndex, @NonNull @CallbackExecutor Executor executor, Loading @@ -1303,18 +1355,18 @@ public class TelephonyRegistryManager { if (listener == null || executor == null) { throw new IllegalArgumentException("listener and executor must be non-null"); } synchronized (sCarrierPrivilegeListeners) { WeakReference<CarrierPrivilegesListenerWrapper> existing = sCarrierPrivilegeListeners.get(listener); synchronized (sCarrierPrivilegeCallbacks) { WeakReference<CarrierPrivilegesCallbackWrapper> existing = sCarrierPrivilegeCallbacks.get(listener); if (existing != null && existing.get() != null) { Log.d(TAG, "addCarrierPrivilegesListener: listener already registered"); return; } CarrierPrivilegesListenerWrapper wrapper = new CarrierPrivilegesListenerWrapper(listener, executor); sCarrierPrivilegeListeners.put(listener, new WeakReference<>(wrapper)); CarrierPrivilegesCallbackWrapper wrapper = new CarrierPrivilegesCallbackWrapper(listener, executor); sCarrierPrivilegeCallbacks.put(listener, new WeakReference<>(wrapper)); try { sRegistry.addCarrierPrivilegesListener( sRegistry.addCarrierPrivilegesCallback( logicalSlotIndex, wrapper, mContext.getOpPackageName(), Loading @@ -1329,19 +1381,84 @@ public class TelephonyRegistryManager { * Unregisters a {@link CarrierPrivilegesListener}. * * @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) { if (listener == null) { throw new IllegalArgumentException("listener must be non-null"); } synchronized (sCarrierPrivilegeListeners) { WeakReference<CarrierPrivilegesListenerWrapper> ref = sCarrierPrivilegeListeners.remove(listener); synchronized (sCarrierPrivilegeCallbacks) { WeakReference<CarrierPrivilegesCallbackWrapper> ref = sCarrierPrivilegeCallbacks.remove(listener); if (ref == null) return; CarrierPrivilegesListenerWrapper wrapper = ref.get(); CarrierPrivilegesCallbackWrapper wrapper = ref.get(); if (wrapper == null) return; 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) { throw e.rethrowFromSystemServer(); } Loading @@ -1357,15 +1474,33 @@ public class TelephonyRegistryManager { */ public void notifyCarrierPrivilegesChanged( int logicalSlotIndex, @NonNull List<String> privilegedPackageNames, @NonNull int[] privilegedUids) { @NonNull Set<String> privilegedPackageNames, @NonNull Set<Integer> privilegedUids) { if (privilegedPackageNames == null || privilegedUids == null) { throw new IllegalArgumentException( "privilegedPackageNames and privilegedUids must be non-null"); } try { sRegistry.notifyCarrierPrivilegesChanged( logicalSlotIndex, privilegedPackageNames, privilegedUids); // 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} */ public void notifyCarrierServiceChanged(int logicalSlotIndex, @Nullable String packageName, int uid) { try { sRegistry.notifyCarrierServiceChanged(logicalSlotIndex, packageName, uid); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading
core/java/com/android/internal/telephony/ICarrierPrivilegesListener.aidl→core/java/com/android/internal/telephony/ICarrierPrivilegesCallback.aidl +2 −1 Original line number Diff line number Diff line Loading @@ -16,7 +16,8 @@ package com.android.internal.telephony; oneway interface ICarrierPrivilegesListener { oneway interface ICarrierPrivilegesCallback { void onCarrierPrivilegesChanged( in List<String> privilegedPackageNames, in int[] privilegedUids); void onCarrierServiceChanged(in String carrierServicePackageName, in int carrierServiceUid); }
core/java/com/android/internal/telephony/ITelephonyRegistry.aidl +6 −4 Original line number Diff line number Diff line Loading @@ -32,7 +32,7 @@ import android.telephony.PreciseDataConnectionState; import android.telephony.ServiceState; import android.telephony.SignalStrength; 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.IOnSubscriptionsChangedListener; Loading Loading @@ -102,9 +102,11 @@ interface ITelephonyRegistry { void notifyLinkCapacityEstimateChanged(in int phoneId, in int subId, in List<LinkCapacityEstimate> linkCapacityEstimateList); void addCarrierPrivilegesListener( int phoneId, ICarrierPrivilegesListener callback, String pkg, String featureId); void removeCarrierPrivilegesListener(ICarrierPrivilegesListener callback, String pkg); void addCarrierPrivilegesCallback( int phoneId, ICarrierPrivilegesCallback callback, String pkg, String featureId); void removeCarrierPrivilegesCallback(ICarrierPrivilegesCallback callback, String pkg); void notifyCarrierPrivilegesChanged( int phoneId, in List<String> privilegedPackageNames, in int[] privilegedUids); void notifyCarrierServiceChanged(int phoneId, in String packageName, int uid); }
services/core/java/com/android/server/TelephonyRegistry.java +71 −26 Original line number Diff line number Diff line Loading @@ -91,7 +91,7 @@ import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; 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.IPhoneStateListener; import com.android.internal.telephony.ITelephonyRegistry; Loading Loading @@ -151,7 +151,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { IPhoneStateListener callback; IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback; IOnSubscriptionsChangedListener onOpportunisticSubscriptionsChangedListenerCallback; ICarrierPrivilegesListener carrierPrivilegesListener; ICarrierPrivilegesCallback carrierPrivilegesCallback; int callerUid; int callerPid; Loading @@ -176,8 +176,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { return (onOpportunisticSubscriptionsChangedListenerCallback != null); } boolean matchCarrierPrivilegesListener() { return carrierPrivilegesListener != null; boolean matchCarrierPrivilegesCallback() { return carrierPrivilegesCallback != null; } boolean canReadCallLog() { Loading @@ -197,7 +197,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { + onSubscriptionsChangedListenerCallback + " onOpportunisticSubscriptionsChangedListenererCallback=" + onOpportunisticSubscriptionsChangedListenerCallback + " carrierPrivilegesListener=" + carrierPrivilegesListener + " carrierPrivilegesCallback=" + carrierPrivilegesCallback + " subId=" + subId + " phoneId=" + phoneId + " events=" + eventList + "}"; } } Loading Loading @@ -412,7 +412,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mPreciseDataConnectionStates; /** 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}. Loading Loading @@ -702,6 +704,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { cutListToSize(mPhysicalChannelConfigs, mNumPhones); cutListToSize(mLinkCapacityEstimateLists, mNumPhones); cutListToSize(mCarrierPrivilegeStates, mNumPhones); cutListToSize(mCarrierServiceStates, mNumPhones); return; } Loading Loading @@ -743,6 +746,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mAllowedNetworkTypeValue[i] = -1; mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST); mCarrierPrivilegeStates.add(i, new Pair<>(Collections.emptyList(), new int[0])); mCarrierServiceStates.add(i, new Pair<>(null, Process.INVALID_UID)); } } Loading Loading @@ -809,6 +813,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mDataEnabledReason = new int[numPhones]; mLinkCapacityEstimateLists = new ArrayList<>(); mCarrierPrivilegeStates = new ArrayList<>(); mCarrierServiceStates = new ArrayList<>(); for (int i = 0; i < numPhones; i++) { mCallState[i] = TelephonyManager.CALL_STATE_IDLE; Loading Loading @@ -847,6 +852,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mAllowedNetworkTypeValue[i] = -1; mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST); mCarrierPrivilegeStates.add(i, new Pair<>(Collections.emptyList(), new int[0])); mCarrierServiceStates.add(i, new Pair<>(null, Process.INVALID_UID)); } mAppOps = mContext.getSystemService(AppOpsManager.class); Loading Loading @@ -2780,16 +2786,16 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } @Override public void addCarrierPrivilegesListener( public void addCarrierPrivilegesCallback( int phoneId, ICarrierPrivilegesListener callback, String callingPackage, String callingFeatureId) { @NonNull ICarrierPrivilegesCallback callback, @NonNull String callingPackage, @NonNull String callingFeatureId) { int callerUserId = UserHandle.getCallingUserId(); mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); mContext.enforceCallingOrSelfPermission( android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, "addCarrierPrivilegesListener"); "addCarrierPrivilegesCallback"); if (VDBG) { log( "listen carrier privs: E pkg=" + pii(callingPackage) + " phoneId=" + phoneId Loading @@ -2809,7 +2815,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { if (r == null) return; r.context = mContext; r.carrierPrivilegesListener = callback; r.carrierPrivilegesCallback = callback; r.callingPackage = callingPackage; r.callingFeatureId = callingFeatureId; r.callerUid = Binder.getCallingUid(); Loading @@ -2821,10 +2827,18 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } Pair<List<String>, int[]> state = mCarrierPrivilegeStates.get(phoneId); Pair<String, Integer> carrierServiceState = mCarrierServiceStates.get(phoneId); try { r.carrierPrivilegesListener.onCarrierPrivilegesChanged( if (r.matchCarrierPrivilegesCallback()) { // Here, two callbacks are triggered in quick succession on the same binder. // 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) { remove(r.binder); } Loading @@ -2832,12 +2846,12 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } @Override public void removeCarrierPrivilegesListener( ICarrierPrivilegesListener callback, String callingPackage) { public void removeCarrierPrivilegesCallback( @NonNull ICarrierPrivilegesCallback callback, @NonNull String callingPackage) { mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); mContext.enforceCallingOrSelfPermission( android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, "removeCarrierPrivilegesListener"); "removeCarrierPrivilegesCallback"); remove(callback.asBinder()); } Loading @@ -2860,13 +2874,13 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { for (Record r : mRecords) { // Listeners are per-slot, not per-subscription. This is to provide a stable // view across SIM profile switches. if (!r.matchCarrierPrivilegesListener() if (!r.matchCarrierPrivilegesCallback() || !idMatch(r, SubscriptionManager.INVALID_SUBSCRIPTION_ID, phoneId)) { continue; } try { // Make sure even in-process listeners can't modify the values. r.carrierPrivilegesListener.onCarrierPrivilegesChanged( r.carrierPrivilegesCallback.onCarrierPrivilegesChanged( Collections.unmodifiableList(privilegedPackageNames), Arrays.copyOf(privilegedUids, privilegedUids.length)); } catch (RemoteException ex) { Loading @@ -2877,6 +2891,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(); } } @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); Loading Loading @@ -2931,6 +2973,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { pw.println( "mCarrierPrivilegeState=<packages=" + pii(carrierPrivilegeState.first) + ", uids=" + Arrays.toString(carrierPrivilegeState.second) + ">"); Pair<String, Integer> carrierServiceState = mCarrierServiceStates.get(i); pw.println("mCarrierServiceState=<package=" + pii(carrierServiceState.first) + ", uid=" + carrierServiceState.second + ">"); pw.decreaseIndent(); } Loading
telephony/java/android/telephony/TelephonyManager.java +22 −4 File changed.Preview size limit exceeded, changes collapsed. Show changes