Support subscription for CarrierService#onLoadConfig

CarrierService#onLoadConfig is called from platform to carrier service
to load carrier-specific configuration values.

In case when the multiple subscriptions are supported for the same
carrier (e.g. Fi on pSIM + Fi on eSIM case), the current API is not
able to distinguish on which subscription the carrier config should
be loaded. The subscription parameter introduced in the API can
resolve the problem.

If carrier app has no need to distinguish configs by subscriptions,
it can simply ignore overriding the new version of the API.

Bug: 131697791
Test: atest CarrierServiceTest
CTS-Coverage-Bug: 210143342
Change-Id: Id7cd75c24f01119749cb5bf31d4335c638547aaf
This commit is contained in:
Rambo Wang 2021-11-23 08:02:59 -08:00
parent e908851af5
commit bbec7b6a5f
3 changed files with 69 additions and 6 deletions

View File

@ -38283,7 +38283,8 @@ package android.service.carrier {
ctor public CarrierService();
method public final void notifyCarrierNetworkChange(boolean);
method @CallSuper public android.os.IBinder onBind(android.content.Intent);
method public abstract android.os.PersistableBundle onLoadConfig(android.service.carrier.CarrierIdentifier);
method @Deprecated public abstract android.os.PersistableBundle onLoadConfig(android.service.carrier.CarrierIdentifier);
method @Nullable public android.os.PersistableBundle onLoadConfig(int, @Nullable android.service.carrier.CarrierIdentifier);
field public static final String CARRIER_SERVICE_INTERFACE = "android.service.carrier.CarrierService";
}

View File

@ -15,6 +15,8 @@
package android.service.carrier;
import android.annotation.CallSuper;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
@ -22,9 +24,12 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.PersistableBundle;
import android.os.ResultReceiver;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyRegistryManager;
import android.util.Log;
import com.android.internal.util.ArrayUtils;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@ -87,7 +92,54 @@ public abstract class CarrierService extends Service {
* PersistableBundle} may be overridden by the system's default configuration service.
* </p>
*
* @param id contains details about the current carrier that can be used do decide what
* @param id contains details about the current carrier that can be used to decide what
* configuration values to return. Instead of using details like MCCMNC to decide
* current carrier, it also contains subscription carrier id
* {@link android.telephony.TelephonyManager#getSimCarrierId()}, a platform-wide
* unique identifier for each carrier, CarrierConfigService can directly use carrier
* id as the key to look up the carrier info.
* @return a {@link PersistableBundle} object containing the configuration or null if default
* values should be used.
* @deprecated use {@link #onLoadConfig(int, CarrierIdentifier)} instead.
*/
@Deprecated
public abstract PersistableBundle onLoadConfig(CarrierIdentifier id);
/**
* Override this method to set carrier configuration on the given {@code subscriptionId}.
* <p>
* This method will be called by telephony services to get carrier-specific configuration
* values. The returned config will be saved by the system until,
* <ol>
* <li>The carrier app package is updated, or</li>
* <li>The carrier app requests a reload with
* {@link android.telephony.CarrierConfigManager#notifyConfigChangedForSubId
* notifyConfigChangedForSubId}.</li>
* </ol>
* This method can be called after a SIM card loads, which may be before or after boot.
* </p>
* <p>
* This method should not block for a long time. If expensive operations (e.g. network access)
* are required, this method can schedule the work and return null. Then, use
* {@link android.telephony.CarrierConfigManager#notifyConfigChangedForSubId
* notifyConfigChangedForSubId} to trigger a reload when the config is ready.
* </p>
* <p>
* Implementations should use the keys defined in {@link android.telephony.CarrierConfigManager
* CarrierConfigManager}. Any configuration values not set in the returned {@link
* PersistableBundle} may be overridden by the system's default configuration service.
* </p>
* <p>
* By default, this method just calls {@link #onLoadConfig(CarrierIdentifier)} with specified
* CarrierIdentifier {@code id}. Carrier app with target SDK
* {@link android.os.Build.VERSION_CODES#TIRAMISU} and above should override this method to
* load carrier configuration on the given {@code subscriptionId}.
* Note that {@link #onLoadConfig(CarrierIdentifier)} is still called prior to
* {@link android.os.Build.VERSION_CODES#TIRAMISU}.
* </p>
*
* @param subscriptionId the subscription on which the carrier app should load configuration
* @param id contains details about the current carrier that can be used to decide what
* configuration values to return. Instead of using details like MCCMNC to decide
* current carrier, it also contains subscription carrier id
* {@link android.telephony.TelephonyManager#getSimCarrierId()}, a platform-wide
@ -96,7 +148,11 @@ public abstract class CarrierService extends Service {
* @return a {@link PersistableBundle} object containing the configuration or null if default
* values should be used.
*/
public abstract PersistableBundle onLoadConfig(CarrierIdentifier id);
@SuppressLint("NullableCollection")
@Nullable
public PersistableBundle onLoadConfig(int subscriptionId, @Nullable CarrierIdentifier id) {
return onLoadConfig(id);
}
/**
* Informs the system of an intentional upcoming carrier network change by
@ -149,10 +205,16 @@ public abstract class CarrierService extends Service {
public static final String KEY_CONFIG_BUNDLE = "config_bundle";
@Override
public void getCarrierConfig(CarrierIdentifier id, ResultReceiver result) {
public void getCarrierConfig(int phoneId, CarrierIdentifier id, ResultReceiver result) {
try {
int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
int[] subIds = SubscriptionManager.getSubId(phoneId);
if (!ArrayUtils.isEmpty(subIds)) {
// There should be at most one active subscription mapping to the phoneId.
subId = subIds[0];
}
Bundle data = new Bundle();
data.putParcelable(KEY_CONFIG_BUNDLE, CarrierService.this.onLoadConfig(id));
data.putParcelable(KEY_CONFIG_BUNDLE, CarrierService.this.onLoadConfig(subId, id));
result.send(RESULT_OK, data);
} catch (Exception e) {
Log.e(LOG_TAG, "Error in onLoadConfig: " + e.getMessage(), e);

View File

@ -29,5 +29,5 @@ import android.service.carrier.CarrierIdentifier;
interface ICarrierService {
/** @see android.service.carrier.CarrierService#onLoadConfig */
oneway void getCarrierConfig(in CarrierIdentifier id, in ResultReceiver result);
oneway void getCarrierConfig(in int phoneId, in CarrierIdentifier id, in ResultReceiver result);
}