Merge "Introduce CarrierConfigChangeListener API to monitor CC change"
This commit is contained in:
commit
e302b2a385
@ -41276,6 +41276,8 @@ package android.telephony {
|
||||
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_STATE, "carrier privileges"}) public android.os.PersistableBundle getConfigForSubId(int, @NonNull java.lang.String...);
|
||||
method public static boolean isConfigForIdentifiedCarrier(android.os.PersistableBundle);
|
||||
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyConfigChangedForSubId(int);
|
||||
method public void registerCarrierConfigChangeListener(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.CarrierConfigManager.CarrierConfigChangeListener);
|
||||
method public void unregisterCarrierConfigChangeListener(@NonNull android.telephony.CarrierConfigManager.CarrierConfigChangeListener);
|
||||
field public static final String ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED";
|
||||
field public static final int CARRIER_NR_AVAILABILITY_NSA = 1; // 0x1
|
||||
field public static final int CARRIER_NR_AVAILABILITY_SA = 2; // 0x2
|
||||
@ -41590,6 +41592,10 @@ package android.telephony {
|
||||
field public static final String KEY_PREFIX = "bsf.";
|
||||
}
|
||||
|
||||
public static interface CarrierConfigManager.CarrierConfigChangeListener {
|
||||
method public void onCarrierConfigChanged(int, int, int, int);
|
||||
}
|
||||
|
||||
public static final class CarrierConfigManager.Gps {
|
||||
field public static final String KEY_PERSIST_LPP_MODE_BOOL = "gps.persist_lpp_mode_bool";
|
||||
field public static final String KEY_PREFIX = "gps.";
|
||||
|
@ -45,6 +45,7 @@ import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.listeners.ListenerExecutor;
|
||||
import com.android.internal.telephony.ICarrierConfigChangeListener;
|
||||
import com.android.internal.telephony.ICarrierPrivilegesCallback;
|
||||
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
|
||||
import com.android.internal.telephony.ITelephonyRegistry;
|
||||
@ -54,8 +55,10 @@ import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -89,6 +92,14 @@ public class TelephonyRegistryManager {
|
||||
IOnSubscriptionsChangedListener> mOpportunisticSubscriptionChangedListenerMap
|
||||
= new HashMap<>();
|
||||
|
||||
/**
|
||||
* A mapping between {@link CarrierConfigManager.CarrierConfigChangeListener} and its callback
|
||||
* ICarrierConfigChangeListener.
|
||||
*/
|
||||
private final ConcurrentHashMap<CarrierConfigManager.CarrierConfigChangeListener,
|
||||
ICarrierConfigChangeListener>
|
||||
mCarrierConfigChangeListenerMap = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
/** @hide **/
|
||||
public TelephonyRegistryManager(@NonNull Context context) {
|
||||
@ -1409,4 +1420,94 @@ public class TelephonyRegistryManager {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link android.telephony.CarrierConfigManager.CarrierConfigChangeListener} to get
|
||||
* notification when carrier configurations have changed.
|
||||
*
|
||||
* @param executor The executor on which the callback will be executed.
|
||||
* @param listener The CarrierConfigChangeListener to be registered with.
|
||||
*/
|
||||
public void addCarrierConfigChangedListener(
|
||||
@NonNull @CallbackExecutor Executor executor,
|
||||
@NonNull CarrierConfigManager.CarrierConfigChangeListener listener) {
|
||||
Objects.requireNonNull(executor, "Executor should be non-null.");
|
||||
Objects.requireNonNull(listener, "Listener should be non-null.");
|
||||
if (mCarrierConfigChangeListenerMap.get(listener) != null) {
|
||||
Log.e(TAG, "registerCarrierConfigChangeListener: listener already present");
|
||||
return;
|
||||
}
|
||||
|
||||
ICarrierConfigChangeListener callback = new ICarrierConfigChangeListener.Stub() {
|
||||
@Override
|
||||
public void onCarrierConfigChanged(int slotIndex, int subId, int carrierId,
|
||||
int specificCarrierId) {
|
||||
Log.d(TAG, "onCarrierConfigChanged call in ICarrierConfigChangeListener callback");
|
||||
final long identify = Binder.clearCallingIdentity();
|
||||
try {
|
||||
executor.execute(() -> listener.onCarrierConfigChanged(slotIndex, subId,
|
||||
carrierId, specificCarrierId));
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identify);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
sRegistry.addCarrierConfigChangeListener(callback,
|
||||
mContext.getOpPackageName(), mContext.getAttributionTag());
|
||||
mCarrierConfigChangeListenerMap.put(listener, callback);
|
||||
} catch (RemoteException re) {
|
||||
// system server crashes
|
||||
throw re.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister to stop the notification when carrier configurations changed.
|
||||
*
|
||||
* @param listener The CarrierConfigChangeListener to be unregistered with.
|
||||
*/
|
||||
public void removeCarrierConfigChangedListener(
|
||||
@NonNull CarrierConfigManager.CarrierConfigChangeListener listener) {
|
||||
Objects.requireNonNull(listener, "Listener should be non-null.");
|
||||
if (mCarrierConfigChangeListenerMap.get(listener) == null) {
|
||||
Log.e(TAG, "removeCarrierConfigChangedListener: listener was not present");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
sRegistry.removeCarrierConfigChangeListener(
|
||||
mCarrierConfigChangeListenerMap.get(listener), mContext.getOpPackageName());
|
||||
mCarrierConfigChangeListenerMap.remove(listener);
|
||||
} catch (RemoteException re) {
|
||||
// System sever crashes
|
||||
throw re.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the registrants the carrier configurations have changed.
|
||||
*
|
||||
* @param slotIndex The SIM slot index on which to monitor and get notification.
|
||||
* @param subId The subscription on the SIM slot. May be
|
||||
* {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}.
|
||||
* @param carrierId The optional carrier Id, may be
|
||||
* {@link TelephonyManager#UNKNOWN_CARRIER_ID}.
|
||||
* @param specificCarrierId The optional specific carrier Id, may be {@link
|
||||
* TelephonyManager#UNKNOWN_CARRIER_ID}.
|
||||
*/
|
||||
public void notifyCarrierConfigChanged(int slotIndex, int subId, int carrierId,
|
||||
int specificCarrierId) {
|
||||
// Only validate slotIndex, all others are optional and allowed to be invalid
|
||||
if (!SubscriptionManager.isValidPhoneId(slotIndex)) {
|
||||
Log.e(TAG, "notifyCarrierConfigChanged, ignored: invalid slotIndex " + slotIndex);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
sRegistry.notifyCarrierConfigChanged(slotIndex, subId, carrierId, specificCarrierId);
|
||||
} catch (RemoteException re) {
|
||||
throw re.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 ICarrierConfigChangeListener {
|
||||
void onCarrierConfigChanged(int slotIndex, int subId, int carrierId, int specificCarrierId);
|
||||
}
|
@ -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.ICarrierConfigChangeListener;
|
||||
import com.android.internal.telephony.ICarrierPrivilegesCallback;
|
||||
import com.android.internal.telephony.IPhoneStateListener;
|
||||
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
|
||||
@ -109,4 +110,8 @@ interface ITelephonyRegistry {
|
||||
int phoneId, in List<String> privilegedPackageNames, in int[] privilegedUids);
|
||||
void notifyCarrierServiceChanged(int phoneId, in String packageName, int uid);
|
||||
|
||||
void addCarrierConfigChangeListener(ICarrierConfigChangeListener listener,
|
||||
String pkg, String featureId);
|
||||
void removeCarrierConfigChangeListener(ICarrierConfigChangeListener listener, String pkg);
|
||||
void notifyCarrierConfigChanged(int phoneId, int subId, int carrierId, int specificCarrierId);
|
||||
}
|
||||
|
@ -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.ICarrierConfigChangeListener;
|
||||
import com.android.internal.telephony.ICarrierPrivilegesCallback;
|
||||
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
|
||||
import com.android.internal.telephony.IPhoneStateListener;
|
||||
@ -154,6 +155,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
|
||||
IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback;
|
||||
IOnSubscriptionsChangedListener onOpportunisticSubscriptionsChangedListenerCallback;
|
||||
ICarrierPrivilegesCallback carrierPrivilegesCallback;
|
||||
ICarrierConfigChangeListener carrierConfigChangeListener;
|
||||
|
||||
int callerUid;
|
||||
int callerPid;
|
||||
@ -182,6 +184,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
|
||||
return carrierPrivilegesCallback != null;
|
||||
}
|
||||
|
||||
boolean matchCarrierConfigChangeListener() {
|
||||
return carrierConfigChangeListener != null;
|
||||
}
|
||||
|
||||
boolean canReadCallLog() {
|
||||
try {
|
||||
return TelephonyPermissions.checkReadCallLog(
|
||||
@ -200,6 +206,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
|
||||
+ " onOpportunisticSubscriptionsChangedListenererCallback="
|
||||
+ onOpportunisticSubscriptionsChangedListenerCallback
|
||||
+ " carrierPrivilegesCallback=" + carrierPrivilegesCallback
|
||||
+ " carrierConfigChangeListener=" + carrierConfigChangeListener
|
||||
+ " subId=" + subId + " phoneId=" + phoneId + " events=" + eventList + "}";
|
||||
}
|
||||
}
|
||||
@ -2955,6 +2962,82 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCarrierConfigChangeListener(ICarrierConfigChangeListener listener,
|
||||
String pkg, String featureId) {
|
||||
final int callerUserId = UserHandle.getCallingUserId();
|
||||
mAppOps.checkPackage(Binder.getCallingUid(), pkg);
|
||||
if (VDBG) {
|
||||
log("addCarrierConfigChangeListener pkg=" + pii(pkg) + " uid=" + Binder.getCallingUid()
|
||||
+ " myUserId=" + UserHandle.myUserId() + " callerUerId" + callerUserId
|
||||
+ " listener=" + listener + " listener.asBinder=" + listener.asBinder());
|
||||
}
|
||||
|
||||
synchronized (mRecords) {
|
||||
IBinder b = listener.asBinder();
|
||||
boolean doesLimitApply = doesLimitApplyForListeners(Binder.getCallingUid(),
|
||||
Process.myUid());
|
||||
Record r = add(b, Binder.getCallingUid(), Binder.getCallingPid(), doesLimitApply);
|
||||
|
||||
if (r == null) {
|
||||
loge("Can not create Record instance!");
|
||||
return;
|
||||
}
|
||||
|
||||
r.context = mContext;
|
||||
r.carrierConfigChangeListener = listener;
|
||||
r.callingPackage = pkg;
|
||||
r.callingFeatureId = featureId;
|
||||
r.callerUid = Binder.getCallingUid();
|
||||
r.callerPid = Binder.getCallingPid();
|
||||
r.eventList = new ArraySet<>();
|
||||
if (DBG) {
|
||||
log("addCarrierConfigChangeListener: Register r=" + r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCarrierConfigChangeListener(ICarrierConfigChangeListener listener,
|
||||
String pkg) {
|
||||
if (DBG) log("removeCarrierConfigChangeListener listener=" + listener + ", pkg=" + pkg);
|
||||
mAppOps.checkPackage(Binder.getCallingUid(), pkg);
|
||||
remove(listener.asBinder());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyCarrierConfigChanged(int phoneId, int subId, int carrierId,
|
||||
int specificCarrierId) {
|
||||
if (!validatePhoneId(phoneId)) {
|
||||
throw new IllegalArgumentException("Invalid phoneId: " + phoneId);
|
||||
}
|
||||
if (!checkNotifyPermission("notifyCarrierConfigChanged")) {
|
||||
loge("Caller has no notify permission!");
|
||||
return;
|
||||
}
|
||||
if (VDBG) {
|
||||
log("notifyCarrierConfigChanged: phoneId=" + phoneId + ", subId=" + subId
|
||||
+ ", carrierId=" + carrierId + ", specificCarrierId=" + specificCarrierId);
|
||||
}
|
||||
|
||||
synchronized (mRecords) {
|
||||
mRemoveList.clear();
|
||||
for (Record r : mRecords) {
|
||||
// Listeners are "global", neither per-slot nor per-sub, so no idMatch check here
|
||||
if (!r.matchCarrierConfigChangeListener()) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
r.carrierConfigChangeListener.onCarrierConfigChanged(phoneId, subId, carrierId,
|
||||
specificCarrierId);
|
||||
} catch (RemoteException re) {
|
||||
mRemoveList.add(r.binder);
|
||||
}
|
||||
}
|
||||
handleRemoveListLocked();
|
||||
}
|
||||
}
|
||||
|
||||
@NeverCompile // Avoid size overhead of debugging code.
|
||||
@Override
|
||||
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
|
||||
|
@ -17,6 +17,7 @@
|
||||
package android.telephony;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.CallbackExecutor;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
@ -53,6 +54,7 @@ import com.android.telephony.Rlog;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@ -9726,4 +9728,85 @@ public class CarrierConfigManager {
|
||||
configs.putPersistableBundle(key, (PersistableBundle) value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener interface to get a notification when the carrier configurations have changed.
|
||||
*
|
||||
* Use this listener to receive timely updates when the carrier configuration changes. System
|
||||
* components should prefer this listener over {@link #ACTION_CARRIER_CONFIG_CHANGED}
|
||||
* whenever possible.
|
||||
*
|
||||
* To register the listener, call
|
||||
* {@link #registerCarrierConfigChangeListener(Executor, CarrierConfigChangeListener)}.
|
||||
* To unregister, call
|
||||
* {@link #unregisterCarrierConfigChangeListener(CarrierConfigChangeListener)}.
|
||||
*
|
||||
* Note that on registration, registrants will NOT receive a notification on last carrier config
|
||||
* change. Only carrier configs change AFTER the registration will be sent to registrants. And
|
||||
* unlike {@link #ACTION_CARRIER_CONFIG_CHANGED}, notification wouldn't send when the device is
|
||||
* unlocked. Registrants only receive the notification when there has been real carrier config
|
||||
* changes.
|
||||
*
|
||||
* @see #registerCarrierConfigChangeListener(Executor, CarrierConfigChangeListener)
|
||||
* @see #unregisterCarrierConfigChangeListener(CarrierConfigChangeListener)
|
||||
* @see #ACTION_CARRIER_CONFIG_CHANGED
|
||||
* @see #getConfig(String...)
|
||||
* @see #getConfigForSubId(int, String...)
|
||||
*/
|
||||
public interface CarrierConfigChangeListener {
|
||||
/**
|
||||
* Called when carrier configurations have changed.
|
||||
*
|
||||
* @param logicalSlotIndex The logical SIM slot index on which to monitor and get
|
||||
* notification. It is guaranteed to be valid.
|
||||
* @param subscriptionId The subscription on the SIM slot. May be
|
||||
* {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}.
|
||||
* @param carrierId The optional carrier Id, may be
|
||||
* {@link TelephonyManager#UNKNOWN_CARRIER_ID}.
|
||||
* See {@link TelephonyManager#getSimCarrierId()}.
|
||||
* @param specificCarrierId The optional fine-grained carrierId, may be {@link
|
||||
* TelephonyManager#UNKNOWN_CARRIER_ID}. A specific carrierId may
|
||||
* be different from the carrierId above in a MVNO scenario. See
|
||||
* detail in {@link TelephonyManager#getSimSpecificCarrierId()}.
|
||||
*/
|
||||
void onCarrierConfigChanged(int logicalSlotIndex, int subscriptionId, int carrierId,
|
||||
int specificCarrierId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link CarrierConfigChangeListener} to get a notification when carrier
|
||||
* configurations have changed.
|
||||
*
|
||||
* @param executor The executor on which the listener will be called.
|
||||
* @param listener The CarrierConfigChangeListener called when carrier configs has changed.
|
||||
*/
|
||||
public void registerCarrierConfigChangeListener(@NonNull @CallbackExecutor Executor executor,
|
||||
@NonNull CarrierConfigChangeListener listener) {
|
||||
Objects.requireNonNull(executor, "Executor should be non-null.");
|
||||
Objects.requireNonNull(listener, "Listener should be non-null.");
|
||||
|
||||
TelephonyRegistryManager trm = mContext.getSystemService(TelephonyRegistryManager.class);
|
||||
if (trm == null) {
|
||||
throw new IllegalStateException("Telephony registry service is null");
|
||||
}
|
||||
trm.addCarrierConfigChangedListener(executor, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister the {@link CarrierConfigChangeListener} to stop notification on carrier
|
||||
* configurations change.
|
||||
*
|
||||
* @param listener The CarrierConfigChangeListener which was registered with method
|
||||
* {@link #registerCarrierConfigChangeListener(Executor, CarrierConfigChangeListener)}.
|
||||
*/
|
||||
public void unregisterCarrierConfigChangeListener(
|
||||
@NonNull CarrierConfigChangeListener listener) {
|
||||
Objects.requireNonNull(listener, "Listener should be non-null.");
|
||||
|
||||
TelephonyRegistryManager trm = mContext.getSystemService(TelephonyRegistryManager.class);
|
||||
if (trm == null) {
|
||||
throw new IllegalStateException("Telephony registry service is null");
|
||||
}
|
||||
trm.removeCarrierConfigChangedListener(listener);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user