summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/telephony/TelephonyRegistryManager.java119
1 files changed, 119 insertions, 0 deletions
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index e7f89204c1ec..9eaaa91532d0 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -36,18 +36,24 @@ import android.telephony.Annotation.PreciseDisconnectCauses;
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SimActivationState;
import android.telephony.Annotation.SrvccState;
+import android.telephony.TelephonyManager.CarrierPrivilegesListener;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.ImsReasonInfo;
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.ICarrierPrivilegesListener;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
import com.android.internal.telephony.ITelephonyRegistry;
+import java.lang.ref.WeakReference;
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;
/**
@@ -1214,4 +1220,117 @@ public class TelephonyRegistryManager {
listenFromCallback(false, false, subId,
pkgName, attributionTag, callback, new int[0], notifyNow);
}
+
+ private static class CarrierPrivilegesListenerWrapper extends ICarrierPrivilegesListener.Stub
+ implements ListenerExecutor {
+ private final WeakReference<CarrierPrivilegesListener> mListener;
+ private final Executor mExecutor;
+
+ CarrierPrivilegesListenerWrapper(CarrierPrivilegesListener listener, Executor executor) {
+ mListener = new WeakReference<>(listener);
+ mExecutor = executor;
+ }
+
+ @Override
+ public void onCarrierPrivilegesChanged(
+ List<String> privilegedPackageNames, int[] privilegedUids) {
+ Binder.withCleanCallingIdentity(
+ () ->
+ executeSafely(
+ mExecutor,
+ mListener::get,
+ cpl ->
+ cpl.onCarrierPrivilegesChanged(
+ privilegedPackageNames, privilegedUids)));
+ }
+ }
+
+ @GuardedBy("sCarrierPrivilegeListeners")
+ private static final WeakHashMap<
+ CarrierPrivilegesListener, WeakReference<CarrierPrivilegesListenerWrapper>>
+ sCarrierPrivilegeListeners = new WeakHashMap<>();
+
+ /**
+ * Registers a {@link CarrierPrivilegesListener} 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 listener The callback to register
+ */
+ public void addCarrierPrivilegesListener(
+ int logicalSlotIndex,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull CarrierPrivilegesListener listener) {
+ if (listener == null || executor == null) {
+ throw new IllegalArgumentException("listener and executor must be non-null");
+ }
+ synchronized (sCarrierPrivilegeListeners) {
+ WeakReference<CarrierPrivilegesListenerWrapper> existing =
+ sCarrierPrivilegeListeners.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));
+ try {
+ sRegistry.addCarrierPrivilegesListener(
+ logicalSlotIndex,
+ wrapper,
+ mContext.getOpPackageName(),
+ mContext.getAttributionTag());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * Unregisters a {@link CarrierPrivilegesListener}.
+ *
+ * @param listener The callback to unregister
+ */
+ 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);
+ if (ref == null) return;
+ CarrierPrivilegesListenerWrapper wrapper = ref.get();
+ if (wrapper == null) return;
+ try {
+ sRegistry.removeCarrierPrivilegesListener(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
+ */
+ public void notifyCarrierPrivilegesChanged(
+ int logicalSlotIndex,
+ @NonNull List<String> privilegedPackageNames,
+ @NonNull int[] privilegedUids) {
+ if (privilegedPackageNames == null || privilegedUids == null) {
+ throw new IllegalArgumentException(
+ "privilegedPackageNames and privilegedUids must be non-null");
+ }
+ try {
+ sRegistry.notifyCarrierPrivilegesChanged(
+ logicalSlotIndex, privilegedPackageNames, privilegedUids);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}