Merge "Create CarrierPrivilegesListener callback."
This commit is contained in:
@@ -12001,6 +12001,7 @@ package android.telephony {
|
||||
}
|
||||
|
||||
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 @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);
|
||||
@@ -12095,6 +12096,7 @@ package android.telephony {
|
||||
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.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(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>);
|
||||
@@ -12270,6 +12272,10 @@ package android.telephony {
|
||||
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 {
|
||||
method public int getErrorCode();
|
||||
field public static final int ERROR_INVALID_INFO_RECEIVED = 2; // 0x2
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -32,6 +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.IPhoneStateListener;
|
||||
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 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 notifyCarrierPrivilegesChanged(
|
||||
int phoneId, in List<String> privilegedPackageNames, in int[] privilegedUids);
|
||||
}
|
||||
|
||||
@@ -91,6 +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.IOnSubscriptionsChangedListener;
|
||||
import com.android.internal.telephony.IPhoneStateListener;
|
||||
import com.android.internal.telephony.ITelephonyRegistry;
|
||||
@@ -106,6 +107,7 @@ import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -149,6 +151,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
|
||||
IPhoneStateListener callback;
|
||||
IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback;
|
||||
IOnSubscriptionsChangedListener onOpportunisticSubscriptionsChangedListenerCallback;
|
||||
ICarrierPrivilegesListener carrierPrivilegesListener;
|
||||
|
||||
int callerUid;
|
||||
int callerPid;
|
||||
@@ -173,6 +176,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
|
||||
return (onOpportunisticSubscriptionsChangedListenerCallback != null);
|
||||
}
|
||||
|
||||
boolean matchCarrierPrivilegesListener() {
|
||||
return carrierPrivilegesListener != null;
|
||||
}
|
||||
|
||||
boolean canReadCallLog() {
|
||||
try {
|
||||
return TelephonyPermissions.checkReadCallLog(
|
||||
@@ -189,8 +196,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
|
||||
+ " onSubscriptionsChangedListenererCallback="
|
||||
+ onSubscriptionsChangedListenerCallback
|
||||
+ " onOpportunisticSubscriptionsChangedListenererCallback="
|
||||
+ onOpportunisticSubscriptionsChangedListenerCallback + " subId=" + subId
|
||||
+ " phoneId=" + phoneId + " events=" + eventList + "}";
|
||||
+ onOpportunisticSubscriptionsChangedListenerCallback
|
||||
+ " 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>>
|
||||
mPreciseDataConnectionStates;
|
||||
|
||||
/** Per-phoneId snapshot of privileged packages (names + UIDs). */
|
||||
private List<Pair<List<String>, int[]>> mCarrierPrivilegeStates;
|
||||
|
||||
/**
|
||||
* Support backward compatibility for {@link android.telephony.TelephonyDisplayInfo}.
|
||||
*/
|
||||
@@ -689,6 +701,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
|
||||
cutListToSize(mBarringInfo, mNumPhones);
|
||||
cutListToSize(mPhysicalChannelConfigs, mNumPhones);
|
||||
cutListToSize(mLinkCapacityEstimateLists, mNumPhones);
|
||||
cutListToSize(mCarrierPrivilegeStates, mNumPhones);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -729,6 +742,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
|
||||
mAllowedNetworkTypeReason[i] = -1;
|
||||
mAllowedNetworkTypeValue[i] = -1;
|
||||
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];
|
||||
mDataEnabledReason = new int[numPhones];
|
||||
mLinkCapacityEstimateLists = new ArrayList<>();
|
||||
mCarrierPrivilegeStates = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < numPhones; i++) {
|
||||
mCallState[i] = TelephonyManager.CALL_STATE_IDLE;
|
||||
@@ -831,6 +846,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
|
||||
mAllowedNetworkTypeReason[i] = -1;
|
||||
mAllowedNetworkTypeValue[i] = -1;
|
||||
mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST);
|
||||
mCarrierPrivilegeStates.add(i, new Pair<>(Collections.emptyList(), new int[0]));
|
||||
}
|
||||
|
||||
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
|
||||
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
|
||||
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
|
||||
@@ -2814,6 +2928,11 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
|
||||
pw.println("mAllowedNetworkTypeValue=" + mAllowedNetworkTypeValue[i]);
|
||||
pw.println("mPhysicalChannelConfigs=" + mPhysicalChannelConfigs.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();
|
||||
}
|
||||
|
||||
@@ -3540,4 +3659,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
|
||||
private static String pii(String 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() + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16028,4 +16028,76 @@ public class TelephonyManager {
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user