Merge "Create CarrierPrivilegesListener callback." am: d54e1126ab am: e66c82b449

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1912993

Change-Id: Ia3a4afac2c703b6ff411dd981d4899be78d78281
This commit is contained in:
Hunter Knepshield
2021-12-16 19:40:11 +00:00
committed by Automerger Merge Worker
6 changed files with 353 additions and 2 deletions

View File

@@ -12001,6 +12001,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 @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);
@@ -12095,6 +12096,7 @@ 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 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio(); method @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.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>);
@@ -12270,6 +12272,10 @@ 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 {
method 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 {
method public int getErrorCode(); method public int getErrorCode();
field public static final int ERROR_INVALID_INFO_RECEIVED = 2; // 0x2 field public static final int ERROR_INVALID_INFO_RECEIVED = 2; // 0x2

View File

@@ -36,18 +36,24 @@ 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.CarrierPrivilegesListener;
import android.telephony.emergency.EmergencyNumber; import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.ImsReasonInfo; import android.telephony.ims.ImsReasonInfo;
import android.util.ArraySet; import android.util.ArraySet;
import android.util.Log; 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.IOnSubscriptionsChangedListener;
import com.android.internal.telephony.ITelephonyRegistry; import com.android.internal.telephony.ITelephonyRegistry;
import java.lang.ref.WeakReference;
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.concurrent.Executor; import java.util.concurrent.Executor;
/** /**
@@ -1214,4 +1220,117 @@ public class TelephonyRegistryManager {
listenFromCallback(false, false, subId, listenFromCallback(false, false, subId,
pkgName, attributionTag, callback, new int[0], notifyNow); 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();
}
}
} }

View File

@@ -0,0 +1,22 @@
/*
* Copyright (C) 2021 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 com.android.internal.telephony;
oneway interface ICarrierPrivilegesListener {
void onCarrierPrivilegesChanged(
in List<String> privilegedPackageNames, in int[] privilegedUids);
}

View File

@@ -32,6 +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.IPhoneStateListener; import com.android.internal.telephony.IPhoneStateListener;
import com.android.internal.telephony.IOnSubscriptionsChangedListener; import com.android.internal.telephony.IOnSubscriptionsChangedListener;
@@ -100,4 +101,10 @@ interface ITelephonyRegistry {
void notifyAllowedNetworkTypesChanged(in int phoneId, in int subId, in int reason, in long allowedNetworkType); void notifyAllowedNetworkTypesChanged(in int phoneId, in int subId, in int reason, in long allowedNetworkType);
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(
int phoneId, ICarrierPrivilegesListener callback, String pkg, String featureId);
void removeCarrierPrivilegesListener(ICarrierPrivilegesListener callback, String pkg);
void notifyCarrierPrivilegesChanged(
int phoneId, in List<String> privilegedPackageNames, in int[] privilegedUids);
} }

View File

@@ -91,6 +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.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;
@@ -106,6 +107,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@@ -149,6 +151,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
IPhoneStateListener callback; IPhoneStateListener callback;
IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback; IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback;
IOnSubscriptionsChangedListener onOpportunisticSubscriptionsChangedListenerCallback; IOnSubscriptionsChangedListener onOpportunisticSubscriptionsChangedListenerCallback;
ICarrierPrivilegesListener carrierPrivilegesListener;
int callerUid; int callerUid;
int callerPid; int callerPid;
@@ -173,6 +176,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
return (onOpportunisticSubscriptionsChangedListenerCallback != null); return (onOpportunisticSubscriptionsChangedListenerCallback != null);
} }
boolean matchCarrierPrivilegesListener() {
return carrierPrivilegesListener != null;
}
boolean canReadCallLog() { boolean canReadCallLog() {
try { try {
return TelephonyPermissions.checkReadCallLog( return TelephonyPermissions.checkReadCallLog(
@@ -189,8 +196,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
+ " onSubscriptionsChangedListenererCallback=" + " onSubscriptionsChangedListenererCallback="
+ onSubscriptionsChangedListenerCallback + onSubscriptionsChangedListenerCallback
+ " onOpportunisticSubscriptionsChangedListenererCallback=" + " onOpportunisticSubscriptionsChangedListenererCallback="
+ onOpportunisticSubscriptionsChangedListenerCallback + " subId=" + subId + onOpportunisticSubscriptionsChangedListenerCallback
+ " phoneId=" + phoneId + " events=" + eventList + "}"; + " carrierPrivilegesListener=" + carrierPrivilegesListener
+ " subId=" + subId + " phoneId=" + phoneId + " events=" + eventList + "}";
} }
} }
@@ -402,6 +410,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
*/ */
private List<Map<Pair<Integer, ApnSetting>, PreciseDataConnectionState>> private List<Map<Pair<Integer, ApnSetting>, PreciseDataConnectionState>>
mPreciseDataConnectionStates; mPreciseDataConnectionStates;
/** Per-phoneId snapshot of privileged packages (names + UIDs). */
private List<Pair<List<String>, int[]>> mCarrierPrivilegeStates;
/** /**
* Support backward compatibility for {@link android.telephony.TelephonyDisplayInfo}. * Support backward compatibility for {@link android.telephony.TelephonyDisplayInfo}.
*/ */
@@ -689,6 +701,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
cutListToSize(mBarringInfo, mNumPhones); cutListToSize(mBarringInfo, mNumPhones);
cutListToSize(mPhysicalChannelConfigs, mNumPhones); cutListToSize(mPhysicalChannelConfigs, mNumPhones);
cutListToSize(mLinkCapacityEstimateLists, mNumPhones); cutListToSize(mLinkCapacityEstimateLists, mNumPhones);
cutListToSize(mCarrierPrivilegeStates, mNumPhones);
return; return;
} }
@@ -729,6 +742,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mAllowedNetworkTypeReason[i] = -1; mAllowedNetworkTypeReason[i] = -1;
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]));
} }
} }
@@ -794,6 +808,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mIsDataEnabled = new boolean[numPhones]; mIsDataEnabled = new boolean[numPhones];
mDataEnabledReason = new int[numPhones]; mDataEnabledReason = new int[numPhones];
mLinkCapacityEstimateLists = new ArrayList<>(); mLinkCapacityEstimateLists = new ArrayList<>();
mCarrierPrivilegeStates = 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;
@@ -831,6 +846,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mAllowedNetworkTypeReason[i] = -1; mAllowedNetworkTypeReason[i] = -1;
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]));
} }
mAppOps = mContext.getSystemService(AppOpsManager.class); mAppOps = mContext.getSystemService(AppOpsManager.class);
@@ -2765,6 +2781,104 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
} }
} }
@Override
public void addCarrierPrivilegesListener(
int phoneId,
ICarrierPrivilegesListener callback,
String callingPackage,
String callingFeatureId) {
int callerUserId = UserHandle.getCallingUserId();
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
"addCarrierPrivilegesListener");
if (VDBG) {
log(
"listen carrier privs: E pkg=" + pii(callingPackage) + " phoneId=" + phoneId
+ " uid=" + Binder.getCallingUid()
+ " myUserId=" + UserHandle.myUserId() + " callerUserId=" + callerUserId
+ " callback=" + callback
+ " callback.asBinder=" + callback.asBinder());
}
if (!validatePhoneId(phoneId)) {
throw new IllegalArgumentException("Invalid slot index: " + phoneId);
}
synchronized (mRecords) {
Record r = add(
callback.asBinder(), Binder.getCallingUid(), Binder.getCallingPid(), false);
if (r == null) return;
r.context = mContext;
r.carrierPrivilegesListener = callback;
r.callingPackage = callingPackage;
r.callingFeatureId = callingFeatureId;
r.callerUid = Binder.getCallingUid();
r.callerPid = Binder.getCallingPid();
r.phoneId = phoneId;
r.eventList = new ArraySet<>();
if (DBG) {
log("listen carrier privs: Register r=" + r);
}
Pair<List<String>, int[]> state = mCarrierPrivilegeStates.get(phoneId);
try {
r.carrierPrivilegesListener.onCarrierPrivilegesChanged(
Collections.unmodifiableList(state.first),
Arrays.copyOf(state.second, state.second.length));
} catch (RemoteException ex) {
remove(r.binder);
}
}
}
@Override
public void removeCarrierPrivilegesListener(
ICarrierPrivilegesListener callback, String callingPackage) {
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
"removeCarrierPrivilegesListener");
remove(callback.asBinder());
}
@Override
public void notifyCarrierPrivilegesChanged(
int phoneId, List<String> privilegedPackageNames, int[] privilegedUids) {
if (!checkNotifyPermission("notifyCarrierPrivilegesChanged")) {
return;
}
if (!validatePhoneId(phoneId)) return;
if (VDBG) {
log(
"notifyCarrierPrivilegesChanged: phoneId=" + phoneId
+ ", <packages=" + pii(privilegedPackageNames)
+ ", uids=" + Arrays.toString(privilegedUids) + ">");
}
synchronized (mRecords) {
mCarrierPrivilegeStates.set(
phoneId, new Pair<>(privilegedPackageNames, privilegedUids));
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()
|| !idMatch(r, SubscriptionManager.INVALID_SUBSCRIPTION_ID, phoneId)) {
continue;
}
try {
// Make sure even in-process listeners can't modify the values.
r.carrierPrivilegesListener.onCarrierPrivilegesChanged(
Collections.unmodifiableList(privilegedPackageNames),
Arrays.copyOf(privilegedUids, privilegedUids.length));
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
}
handleRemoveListLocked();
}
}
@Override @Override
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
@@ -2814,6 +2928,11 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
pw.println("mAllowedNetworkTypeValue=" + mAllowedNetworkTypeValue[i]); pw.println("mAllowedNetworkTypeValue=" + mAllowedNetworkTypeValue[i]);
pw.println("mPhysicalChannelConfigs=" + mPhysicalChannelConfigs.get(i)); pw.println("mPhysicalChannelConfigs=" + mPhysicalChannelConfigs.get(i));
pw.println("mLinkCapacityEstimateList=" + mLinkCapacityEstimateLists.get(i)); pw.println("mLinkCapacityEstimateList=" + mLinkCapacityEstimateLists.get(i));
// We need to obfuscate package names, and primitive arrays' native toString is ugly
Pair<List<String>, int[]> carrierPrivilegeState = mCarrierPrivilegeStates.get(i);
pw.println(
"mCarrierPrivilegeState=<packages=" + pii(carrierPrivilegeState.first)
+ ", uids=" + Arrays.toString(carrierPrivilegeState.second) + ">");
pw.decreaseIndent(); pw.decreaseIndent();
} }
@@ -3540,4 +3659,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
private static String pii(String packageName) { private static String pii(String packageName) {
return Build.IS_DEBUGGABLE ? packageName : "***"; return Build.IS_DEBUGGABLE ? packageName : "***";
} }
/** Redacts an entire list of package names if necessary. */
private static String pii(List<String> packageNames) {
if (packageNames.isEmpty() || Build.IS_DEBUGGABLE) return packageNames.toString();
return "[***, size=" + packageNames.size() + "]";
}
} }

View File

@@ -16028,4 +16028,76 @@ public class TelephonyManager {
} }
return null; return null;
} }
/**
* Callback to listen for when the set of packages with carrier privileges for a SIM changes.
*
* @hide
*/
@SystemApi
public interface CarrierPrivilegesListener {
/**
* 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 List<String> privilegedPackageNames, @NonNull int[] privilegedUids);
}
/**
* 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
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void addCarrierPrivilegesListener(
int logicalSlotIndex,
@NonNull @CallbackExecutor Executor executor,
@NonNull CarrierPrivilegesListener listener) {
if (mContext == null) {
throw new IllegalStateException("Telephony service is null");
} else if (executor == null || listener == null) {
throw new IllegalArgumentException(
"CarrierPrivilegesListener and executor must be non-null");
}
mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class);
if (mTelephonyRegistryMgr == null) {
throw new IllegalStateException("Telephony registry service is null");
}
mTelephonyRegistryMgr.addCarrierPrivilegesListener(logicalSlotIndex, executor, listener);
}
/**
* Unregisters an existing {@link CarrierPrivilegesListener}.
*
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void removeCarrierPrivilegesListener(@NonNull CarrierPrivilegesListener listener) {
if (mContext == null) {
throw new IllegalStateException("Telephony service is null");
} else if (listener == null) {
throw new IllegalArgumentException("CarrierPrivilegesListener must be non-null");
}
mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class);
if (mTelephonyRegistryMgr == null) {
throw new IllegalStateException("Telephony registry service is null");
}
mTelephonyRegistryMgr.removeCarrierPrivilegesListener(listener);
}
} }