diff options
13 files changed, 133 insertions, 103 deletions
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 13a48993f68f..6a4c67b71250 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -90,6 +90,7 @@ package android.content { public abstract class Context { method @NonNull public android.os.UserHandle getUser(); field public static final String PAC_PROXY_SERVICE = "pac_proxy"; + field public static final String REMOTE_AUTH_SERVICE = "remote_auth"; field public static final String TEST_NETWORK_SERVICE = "test_network"; } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 7de7c676706b..21d4b6461214 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -6059,6 +6059,18 @@ public abstract class Context { /** * Use with {@link #getSystemService(String)} to retrieve a + * {@link android.remoteauth.RemoteAuthManager} to discover, + * register and authenticate via remote authenticator devices. + * + * @see #getSystemService(String) + * @see android.remoteauth.RemoteAuthManager + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final String REMOTE_AUTH_SERVICE = "remote_auth"; + + /** + * Use with {@link #getSystemService(String)} to retrieve a * {@link android.app.ambientcontext.AmbientContextManager}. * * @see #getSystemService(String) diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index d738d9eec4cb..db4a684b667e 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1561,6 +1561,14 @@ public abstract class PackageManager { */ public static final int INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK = 0x01000000; + /** + * Flag parameter for {@link #installPackage} to force a non-staged update of an APEX. This is + * a development-only feature and should not be used on end user devices. + * + * @hide + */ + public static final int INSTALL_FORCE_NON_STAGED_APEX_UPDATE = 0x02000000; + /** @hide */ @IntDef(flag = true, value = { DONT_KILL_APP, diff --git a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java index 02e7f6036b34..c8e2cccfd2f6 100644 --- a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java @@ -221,7 +221,7 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes List<CameraOutputConfig> outputConfigs = sessionConfig.outputConfigs; ArrayList<OutputConfiguration> outputList = new ArrayList<>(); for (CameraOutputConfig output : outputConfigs) { - Surface outputSurface = initializeSurfrace(output); + Surface outputSurface = initializeSurface(output); if (outputSurface == null) { continue; } @@ -234,7 +234,7 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes if ((output.sharedSurfaceConfigs != null) && !output.sharedSurfaceConfigs.isEmpty()) { cameraOutput.enableSurfaceSharing(); for (CameraOutputConfig sharedOutputConfig : output.sharedSurfaceConfigs) { - Surface sharedSurface = initializeSurfrace(sharedOutputConfig); + Surface sharedSurface = initializeSurface(sharedOutputConfig); if (sharedSurface == null) { continue; } @@ -989,7 +989,7 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes return ret; } - private Surface initializeSurfrace(CameraOutputConfig output) { + private Surface initializeSurface(CameraOutputConfig output) { switch(output.type) { case CameraOutputConfig.TYPE_SURFACE: if (output.surface == null) { diff --git a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java index 2156c1220a52..efb3510dfebf 100644 --- a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java @@ -1942,10 +1942,10 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { HashMap<Integer, Pair<Image, TotalCaptureResult>> captureMap, Integer jpegOrientation, Byte jpegQuality) { ArrayList<CaptureBundle> ret = new ArrayList<>(); - for (Integer stagetId : captureMap.keySet()) { - Pair<Image, TotalCaptureResult> entry = captureMap.get(stagetId); + for (Integer stageId : captureMap.keySet()) { + Pair<Image, TotalCaptureResult> entry = captureMap.get(stageId); CaptureBundle bundle = new CaptureBundle(); - bundle.stage = stagetId; + bundle.stage = stageId; bundle.captureImage = initializeParcelImage(entry.first); bundle.sequenceId = entry.second.getSequenceId(); bundle.captureResult = entry.second.getNativeMetadata(); diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java index 1a6155b43f6b..a085b95d8e77 100644 --- a/services/core/java/com/android/server/pm/ApexManager.java +++ b/services/core/java/com/android/server/pm/ApexManager.java @@ -424,7 +424,7 @@ public abstract class ApexManager { /** * Performs a non-staged install of the given {@code apexFile}. */ - abstract void installPackage(File apexFile, PackageParser2 packageParser) + abstract void installPackage(File apexFile, PackageParser2 packageParser, boolean force) throws PackageManagerException; /** @@ -1136,7 +1136,7 @@ public abstract class ApexManager { } @Override - void installPackage(File apexFile, PackageParser2 packageParser) + void installPackage(File apexFile, PackageParser2 packageParser, boolean force) throws PackageManagerException { try { final int flags = PackageManager.GET_META_DATA @@ -1159,7 +1159,7 @@ public abstract class ApexManager { } checkApexSignature(existingApexPkg, newApexPkg); ApexInfo apexInfo = waitForApexService().installAndActivatePackage( - apexFile.getAbsolutePath()); + apexFile.getAbsolutePath(), force); final ParsedPackage parsedPackage2 = packageParser.parsePackage( new File(apexInfo.modulePath), flags, /* useCaches= */ false); final PackageInfo finalApexPkg = PackageInfoWithoutStateUtils.generate( @@ -1505,7 +1505,7 @@ public abstract class ApexManager { } @Override - void installPackage(File apexFile, PackageParser2 packageParser) { + void installPackage(File apexFile, PackageParser2 packageParser, boolean force) { throw new UnsupportedOperationException("APEX updates are not supported"); } diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index 293f7e9941e3..703ae11ae99b 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -872,8 +872,10 @@ final class InstallPackageHelper { "Expected exactly one .apex file under " + dir.getAbsolutePath() + " got: " + apexes.length); } + boolean force = (request.mArgs.mInstallFlags + & PackageManager.INSTALL_FORCE_NON_STAGED_APEX_UPDATE) != 0; try (PackageParser2 packageParser = mPm.mInjector.getScanningPackageParser()) { - mApexManager.installPackage(apexes[0], packageParser); + mApexManager.installPackage(apexes[0], packageParser, force); } } catch (PackageManagerException e) { request.mInstallResult.setError("APEX installation failed", e); diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index be842b96843c..38b79e5612ef 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -86,7 +86,6 @@ import android.os.ServiceManager; import android.os.ServiceSpecificException; import android.os.ShellCommand; import android.os.SystemClock; -import android.os.SystemProperties; import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; @@ -3053,6 +3052,13 @@ class PackageManagerShellCommand extends ShellCommand { // Set package source to other by default sessionParams.setPackageSource(PackageInstaller.PACKAGE_SOURCE_OTHER); + // Encodes one of the states: + // 1. Install request explicitly specified --staged, then value will be true. + // 2. Install request explicitly specified --non-staged, then value will be false. + // 3. Install request did not specify either --staged or --non-staged, then for APEX + // installs the value will be true, and for apk installs it will be false. + Boolean staged = null; + String opt; boolean replaceExisting = true; boolean forceNonStaged = false; @@ -3151,7 +3157,6 @@ class PackageManagerShellCommand extends ShellCommand { break; case "--apex": sessionParams.setInstallAsApex(); - sessionParams.setStaged(); break; case "--force-non-staged": forceNonStaged = true; @@ -3160,7 +3165,10 @@ class PackageManagerShellCommand extends ShellCommand { sessionParams.setMultiPackage(); break; case "--staged": - sessionParams.setStaged(); + staged = true; + break; + case "--non-staged": + staged = false; break; case "--force-queryable": sessionParams.setForceQueryable(); @@ -3192,11 +3200,17 @@ class PackageManagerShellCommand extends ShellCommand { throw new IllegalArgumentException("Unknown option " + opt); } } + if (staged == null) { + staged = (sessionParams.installFlags & PackageManager.INSTALL_APEX) != 0; + } if (replaceExisting) { sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; } if (forceNonStaged) { sessionParams.isStaged = false; + sessionParams.installFlags |= PackageManager.INSTALL_FORCE_NON_STAGED_APEX_UPDATE; + } else if (staged) { + sessionParams.setStaged(); } return params; } @@ -3978,7 +3992,8 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" [--preload] [--instant] [--full] [--dont-kill]"); pw.println(" [--enable-rollback]"); pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]"); - pw.println(" [--apex] [--force-non-staged] [--staged-ready-timeout TIMEOUT]"); + pw.println(" [--apex] [--non-staged] [--force-non-staged]"); + pw.println(" [--staged-ready-timeout TIMEOUT]"); pw.println(" [PATH [SPLIT...]|-]"); pw.println(" Install an application. Must provide the apk data to install, either as"); pw.println(" file path(s) or '-' to read from stdin. Options are:"); @@ -4006,6 +4021,9 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" 3=device setup, 4=user request"); pw.println(" --force-uuid: force install on to disk volume with given UUID"); pw.println(" --apex: install an .apex file, not an .apk"); + pw.println(" --non-staged: explicitly set this installation to be non-staged."); + pw.println(" This flag is only useful for APEX installs that are implicitly"); + pw.println(" assumed to be staged."); pw.println(" --force-non-staged: force the installation to run under a non-staged"); pw.println(" session, which may complete without requiring a reboot"); pw.println(" --staged-ready-timeout: By default, staged sessions wait " diff --git a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java index ca4a32f553ae..099c9ae33bfb 100644 --- a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java +++ b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java @@ -16,9 +16,6 @@ package com.android.server.vcn; -import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED; -import static android.telephony.CarrierConfigManager.EXTRA_SLOT_INDEX; -import static android.telephony.CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX; import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static android.telephony.TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED; @@ -48,7 +45,6 @@ import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting.Visibility; import com.android.internal.util.IndentingPrintWriter; -import com.android.server.vcn.util.PersistableBundleUtils; import com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper; import java.util.ArrayList; @@ -109,6 +105,12 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { @NonNull private TelephonySubscriptionSnapshot mCurrentSnapshot; + @NonNull + private final CarrierConfigManager.CarrierConfigChangeListener mCarrierConfigChangeListener = + (int logicalSlotIndex, int subscriptionId, int carrierId, int specificCarrierId) -> + handleActionCarrierConfigChanged(logicalSlotIndex, subscriptionId); + + public TelephonySubscriptionTracker( @NonNull Context context, @NonNull Handler handler, @@ -149,13 +151,14 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { public void register() { final HandlerExecutor executor = new HandlerExecutor(mHandler); final IntentFilter filter = new IntentFilter(); - filter.addAction(ACTION_CARRIER_CONFIG_CHANGED); filter.addAction(ACTION_MULTI_SIM_CONFIG_CHANGED); mContext.registerReceiver(this, filter, null, mHandler); mSubscriptionManager.addOnSubscriptionsChangedListener( executor, mSubscriptionChangedListener); mTelephonyManager.registerTelephonyCallback(executor, mActiveDataSubIdListener); + mCarrierConfigManager.registerCarrierConfigChangeListener(executor, + mCarrierConfigChangeListener); registerCarrierPrivilegesCallbacks(); } @@ -197,6 +200,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { mContext.unregisterReceiver(this); mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionChangedListener); mTelephonyManager.unregisterTelephonyCallback(mActiveDataSubIdListener); + mCarrierConfigManager.unregisterCarrierConfigChangeListener(mCarrierConfigChangeListener); unregisterCarrierPrivilegesCallbacks(); } @@ -273,7 +277,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { } /** - * Broadcast receiver for ACTION_CARRIER_CONFIG_CHANGED + * Broadcast receiver for ACTION_MULTI_SIM_CONFIG_CHANGED * * <p>The broadcast receiver is registered with mHandler, so callbacks & broadcasts are all * serialized on mHandler, avoiding the need for locking. @@ -281,9 +285,6 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { switch (intent.getAction()) { - case ACTION_CARRIER_CONFIG_CHANGED: - handleActionCarrierConfigChanged(context, intent); - break; case ACTION_MULTI_SIM_CONFIG_CHANGED: handleActionMultiSimConfigChanged(context, intent); break; @@ -310,26 +311,21 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { handleSubscriptionsChanged(); } - private void handleActionCarrierConfigChanged(Context context, Intent intent) { - // Accept sticky broadcasts; if CARRIER_CONFIG_CHANGED was previously broadcast and it - // already was for an identified carrier, we can stop waiting for initial load to complete - final int subId = intent.getIntExtra(EXTRA_SUBSCRIPTION_INDEX, INVALID_SUBSCRIPTION_ID); - final int slotId = intent.getIntExtra(EXTRA_SLOT_INDEX, INVALID_SIM_SLOT_INDEX); - + private void handleActionCarrierConfigChanged(int slotId, int subId) { if (slotId == INVALID_SIM_SLOT_INDEX) { return; } if (SubscriptionManager.isValidSubscriptionId(subId)) { - final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId); + // Get only configs as needed to save memory. + final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId, + VcnManager.VCN_RELATED_CARRIER_CONFIG_KEYS); if (mDeps.isConfigForIdentifiedCarrier(carrierConfig)) { mReadySubIdsBySlotId.put(slotId, subId); - final PersistableBundle minimized = - PersistableBundleUtils.minimizeBundle( - carrierConfig, VcnManager.VCN_RELATED_CARRIER_CONFIG_KEYS); - if (minimized != null) { - mSubIdToCarrierConfigMap.put(subId, new PersistableBundleWrapper(minimized)); + if (!carrierConfig.isEmpty()) { + mSubIdToCarrierConfigMap.put(subId, + new PersistableBundleWrapper(carrierConfig)); } handleSubscriptionsChanged(); } diff --git a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java index ab292ab5381e..872e438c6b8d 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java @@ -19,6 +19,7 @@ package com.android.server.pm; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doAnswer; @@ -362,7 +363,7 @@ public class ApexManagerTest { File apex = extractResource("test.apex_rebootless_v1", "test.rebootless_apex_v1.apex"); PackageManagerException e = expectThrows(PackageManagerException.class, - () -> mApexManager.installPackage(apex, mPackageParser2)); + () -> mApexManager.installPackage(apex, mPackageParser2, /* force= */ false)); assertThat(e).hasMessageThat().contains("It is forbidden to install new APEX packages"); } @@ -378,10 +379,11 @@ public class ApexManagerTest { File finalApex = extractResource("test.rebootles_apex_v2", "test.rebootless_apex_v2.apex"); ApexInfo newApexInfo = createApexInfo("test.apex_rebootless", 2, /* isActive= */ true, /* isFactory= */ false, finalApex); - when(mApexService.installAndActivatePackage(anyString())).thenReturn(newApexInfo); + when(mApexService.installAndActivatePackage(anyString(), anyBoolean())).thenReturn( + newApexInfo); File installedApex = extractResource("installed", "test.rebootless_apex_v2.apex"); - mApexManager.installPackage(installedApex, mPackageParser2); + mApexManager.installPackage(installedApex, mPackageParser2, /* force= */ false); PackageInfo newInfo = mApexManager.getPackageInfo("test.apex.rebootless", ApexManager.MATCH_ACTIVE_PACKAGE); @@ -416,10 +418,11 @@ public class ApexManagerTest { File finalApex = extractResource("test.rebootles_apex_v2", "test.rebootless_apex_v2.apex"); ApexInfo newApexInfo = createApexInfo("test.apex_rebootless", 2, /* isActive= */ true, /* isFactory= */ false, finalApex); - when(mApexService.installAndActivatePackage(anyString())).thenReturn(newApexInfo); + when(mApexService.installAndActivatePackage(anyString(), anyBoolean())).thenReturn( + newApexInfo); File installedApex = extractResource("installed", "test.rebootless_apex_v2.apex"); - mApexManager.installPackage(installedApex, mPackageParser2); + mApexManager.installPackage(installedApex, mPackageParser2, /* force= */ false); PackageInfo newInfo = mApexManager.getPackageInfo("test.apex.rebootless", ApexManager.MATCH_ACTIVE_PACKAGE); @@ -447,13 +450,14 @@ public class ApexManagerTest { mApexManager.scanApexPackagesTraced(mPackageParser2, ParallelPackageParser.makeExecutorService()); - when(mApexService.installAndActivatePackage(anyString())).thenThrow( + when(mApexService.installAndActivatePackage(anyString(), anyBoolean())).thenThrow( new RuntimeException("install failed :(")); File installedApex = extractResource("test.apex_rebootless_v1", "test.rebootless_apex_v1.apex"); assertThrows(PackageManagerException.class, - () -> mApexManager.installPackage(installedApex, mPackageParser2)); + () -> mApexManager.installPackage(installedApex, mPackageParser2, /* force= */ + false)); } @Test @@ -468,7 +472,8 @@ public class ApexManagerTest { File installedApex = extractResource("shim_different_certificate", "com.android.apex.cts.shim.v2_different_certificate.apex"); PackageManagerException e = expectThrows(PackageManagerException.class, - () -> mApexManager.installPackage(installedApex, mPackageParser2)); + () -> mApexManager.installPackage(installedApex, mPackageParser2, /* force= */ + false)); assertThat(e).hasMessageThat().contains("APK container signature of "); assertThat(e).hasMessageThat().contains( "is not compatible with currently installed on device"); @@ -486,7 +491,8 @@ public class ApexManagerTest { File installedApex = extractResource("shim_unsigned_apk_container", "com.android.apex.cts.shim.v2_unsigned_apk_container.apex"); PackageManagerException e = expectThrows(PackageManagerException.class, - () -> mApexManager.installPackage(installedApex, mPackageParser2)); + () -> mApexManager.installPackage(installedApex, mPackageParser2, /* force= */ + false)); assertThat(e).hasMessageThat().contains("Failed to collect certificates from "); } diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index 59a5b7ea7847..96dc44a5f9fa 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -3628,17 +3628,10 @@ public class SubscriptionManager { } /** - * Enables or disables a subscription. This is currently used in the settings page. It will - * fail and return false if operation is not supported or failed. + * Enable or disable a subscription. This method is same as + * {@link #setUiccApplicationsEnabled(int, boolean)}. * - * To disable an active subscription on a physical (non-Euicc) SIM, - * {@link #canDisablePhysicalSubscription} needs to be true. - * - * <p> - * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required - * - * @param subscriptionId Subscription to be enabled or disabled. It could be a eSIM or pSIM - * subscription. + * @param subscriptionId Subscription to be enabled or disabled. * @param enable whether user is turning it on or off. * * @return whether the operation is successful. @@ -3648,19 +3641,15 @@ public class SubscriptionManager { @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setSubscriptionEnabled(int subscriptionId, boolean enable) { - if (VDBG) { - logd("setSubscriptionActivated subId= " + subscriptionId + " enable " + enable); - } try { ISub iSub = TelephonyManager.getSubscriptionService(); if (iSub != null) { - return iSub.setSubscriptionEnabled(enable, subscriptionId); + iSub.setUiccApplicationsEnabled(enable, subscriptionId); } } catch (RemoteException ex) { - // ignore it + return false; } - - return false; + return true; } /** @@ -3683,11 +3672,7 @@ public class SubscriptionManager { logd("setUiccApplicationsEnabled subId= " + subscriptionId + " enable " + enabled); } try { - ISub iSub = ISub.Stub.asInterface( - TelephonyFrameworkInitializer - .getTelephonyServiceManager() - .getSubscriptionServiceRegisterer() - .get()); + ISub iSub = TelephonyManager.getSubscriptionService(); if (iSub != null) { iSub.setUiccApplicationsEnabled(enabled, subscriptionId); } @@ -3715,11 +3700,7 @@ public class SubscriptionManager { logd("canDisablePhysicalSubscription"); } try { - ISub iSub = ISub.Stub.asInterface( - TelephonyFrameworkInitializer - .getTelephonyServiceManager() - .getSubscriptionServiceRegisterer() - .get()); + ISub iSub = TelephonyManager.getSubscriptionService(); if (iSub != null) { return iSub.canDisablePhysicalSubscription(); } @@ -3843,10 +3824,15 @@ public class SubscriptionManager { } /** - * DO NOT USE. - * This API is designed for features that are not finished at this point. Do not call this API. + * Get the active subscription id by logical SIM slot index. + * + * @param slotIndex The logical SIM slot index. + * @return The active subscription id. + * + * @throws IllegalArgumentException if the provided slot index is invalid. + * @throws SecurityException if callers do not hold the required permission. + * * @hide - * TODO b/135547512: further clean up */ @SystemApi @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl index 632a6874b5f5..6a5380ddb36e 100644 --- a/telephony/java/com/android/internal/telephony/ISub.aidl +++ b/telephony/java/com/android/internal/telephony/ISub.aidl @@ -265,8 +265,6 @@ interface ISub { String getSubscriptionProperty(int subId, String propKey, String callingPackage, String callingFeatureId); - boolean setSubscriptionEnabled(boolean enable, int subId); - boolean isSubscriptionEnabled(int subId); int getEnabledSubscriptionId(int slotIndex); @@ -277,7 +275,7 @@ interface ISub { boolean canDisablePhysicalSubscription(); - int setUiccApplicationsEnabled(boolean enabled, int subscriptionId); + void setUiccApplicationsEnabled(boolean enabled, int subscriptionId); int setDeviceToDeviceStatusSharing(int sharing, int subId); diff --git a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java index 965b073ff0db..34f884b94296 100644 --- a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java +++ b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java @@ -19,9 +19,6 @@ package com.android.server.vcn; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.vcn.VcnManager.VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY; -import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED; -import static android.telephony.CarrierConfigManager.EXTRA_SLOT_INDEX; -import static android.telephony.CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX; import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener; @@ -143,6 +140,8 @@ public class TelephonySubscriptionTrackerTest { @NonNull private TelephonySubscriptionTrackerCallback mCallback; @NonNull private TelephonySubscriptionTracker mTelephonySubscriptionTracker; + @NonNull private CarrierConfigManager.CarrierConfigChangeListener mCarrierConfigChangeListener; + public TelephonySubscriptionTrackerTest() { mContext = mock(Context.class); mTestLooper = new TestLooper(); @@ -173,7 +172,7 @@ public class TelephonySubscriptionTrackerTest { .getSystemService(Context.CARRIER_CONFIG_SERVICE); doReturn(TEST_CARRIER_CONFIG) .when(mCarrierConfigManager) - .getConfigForSubId(eq(TEST_SUBSCRIPTION_ID_1)); + .getConfigForSubId(eq(TEST_SUBSCRIPTION_ID_1), any()); // subId 1, 2 are in same subGrp, only subId 1 is active doReturn(TEST_PARCEL_UUID).when(TEST_SUBINFO_1).getGroupUuid(); @@ -189,9 +188,15 @@ public class TelephonySubscriptionTrackerTest { doReturn(2).when(mTelephonyManager).getActiveModemCount(); mCallback = mock(TelephonySubscriptionTrackerCallback.class); + // Capture CarrierConfigChangeListener to emulate the carrier config change notification + ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerArgumentCaptor = + ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class); mTelephonySubscriptionTracker = new TelephonySubscriptionTracker(mContext, mHandler, mCallback, mDeps); mTelephonySubscriptionTracker.register(); + verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(), + listenerArgumentCaptor.capture()); + mCarrierConfigChangeListener = listenerArgumentCaptor.getAllValues().get(0); doReturn(true).when(mDeps).isConfigForIdentifiedCarrier(any()); doReturn(Arrays.asList(TEST_SUBINFO_1, TEST_SUBINFO_2)) @@ -239,14 +244,11 @@ public class TelephonySubscriptionTrackerTest { return intent; } - private Intent buildTestBroadcastIntent(boolean hasValidSubscription) { - Intent intent = new Intent(ACTION_CARRIER_CONFIG_CHANGED); - intent.putExtra(EXTRA_SLOT_INDEX, TEST_SIM_SLOT_INDEX); - intent.putExtra( - EXTRA_SUBSCRIPTION_INDEX, - hasValidSubscription ? TEST_SUBSCRIPTION_ID_1 : INVALID_SUBSCRIPTION_ID); - - return intent; + private void sendCarrierConfigChange(boolean hasValidSubscription) { + mCarrierConfigChangeListener.onCarrierConfigChanged( + TEST_SIM_SLOT_INDEX, + hasValidSubscription ? TEST_SUBSCRIPTION_ID_1 : INVALID_SUBSCRIPTION_ID, + TelephonyManager.UNKNOWN_CARRIER_ID, TelephonyManager.UNKNOWN_CARRIER_ID); } private TelephonySubscriptionSnapshot buildExpectedSnapshot( @@ -302,14 +304,15 @@ public class TelephonySubscriptionTrackerTest { any(), eq(mHandler)); final IntentFilter filter = getIntentFilter(); - assertEquals(2, filter.countActions()); - assertTrue(filter.hasAction(ACTION_CARRIER_CONFIG_CHANGED)); + assertEquals(1, filter.countActions()); assertTrue(filter.hasAction(ACTION_MULTI_SIM_CONFIG_CHANGED)); verify(mSubscriptionManager) .addOnSubscriptionsChangedListener(any(HandlerExecutor.class), any()); assertNotNull(getOnSubscriptionsChangedListener()); + verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(), any()); + verify(mTelephonyManager, times(2)) .registerCarrierPrivilegesCallback(anyInt(), any(HandlerExecutor.class), any()); verify(mTelephonyManager) @@ -442,7 +445,7 @@ public class TelephonySubscriptionTrackerTest { @Test public void testReceiveBroadcast_ConfigReadyWithSubscriptions() throws Exception { - mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true)); + sendCarrierConfigChange(true /* hasValidSubscription */); mTestLooper.dispatchAll(); verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES))); @@ -454,7 +457,7 @@ public class TelephonySubscriptionTrackerTest { .when(mSubscriptionManager) .getAllSubscriptionInfoList(); - mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true)); + sendCarrierConfigChange(true /* hasValidSubscription */); mTestLooper.dispatchAll(); // Expect an empty snapshot @@ -465,7 +468,7 @@ public class TelephonySubscriptionTrackerTest { public void testReceiveBroadcast_SlotCleared() throws Exception { setupReadySubIds(); - mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(false)); + sendCarrierConfigChange(false /* hasValidSubscription */); mTestLooper.dispatchAll(); verifyNoActiveSubscriptions(); @@ -476,7 +479,7 @@ public class TelephonySubscriptionTrackerTest { public void testReceiveBroadcast_ConfigNotReady() throws Exception { doReturn(false).when(mDeps).isConfigForIdentifiedCarrier(any()); - mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true)); + sendCarrierConfigChange(true /* hasValidSubscription */); mTestLooper.dispatchAll(); // No interactions expected; config was not loaded @@ -485,21 +488,21 @@ public class TelephonySubscriptionTrackerTest { @Test public void testSubscriptionsClearedAfterValidTriggersCallbacks() throws Exception { - mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true)); + sendCarrierConfigChange(true /* hasValidSubscription */); mTestLooper.dispatchAll(); verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES))); assertNotNull( mTelephonySubscriptionTracker.getReadySubIdsBySlotId().get(TEST_SIM_SLOT_INDEX)); doReturn(Collections.emptyList()).when(mSubscriptionManager).getAllSubscriptionInfoList(); - mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true)); + sendCarrierConfigChange(true /* hasValidSubscription */); mTestLooper.dispatchAll(); verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(emptyMap(), emptyMap()))); } @Test public void testCarrierConfigUpdatedAfterValidTriggersCallbacks() throws Exception { - mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true)); + sendCarrierConfigChange(true /* hasValidSubscription */); mTestLooper.dispatchAll(); verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES))); reset(mCallback); @@ -510,12 +513,12 @@ public class TelephonySubscriptionTrackerTest { new int[] {TRANSPORT_WIFI, TRANSPORT_CELLULAR}); doReturn(updatedConfig) .when(mCarrierConfigManager) - .getConfigForSubId(eq(TEST_SUBSCRIPTION_ID_1)); + .getConfigForSubId(eq(TEST_SUBSCRIPTION_ID_1), any()); Map<Integer, PersistableBundleWrapper> subIdToCarrierConfigMap = new HashMap<>(); subIdToCarrierConfigMap.put( TEST_SUBSCRIPTION_ID_1, new PersistableBundleWrapper(updatedConfig)); - mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true)); + sendCarrierConfigChange(true /* hasValidSubscription */); mTestLooper.dispatchAll(); verify(mCallback) @@ -530,13 +533,13 @@ public class TelephonySubscriptionTrackerTest { @Test public void testSlotClearedAfterValidTriggersCallbacks() throws Exception { - mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true)); + sendCarrierConfigChange(true /* hasValidSubscription */); mTestLooper.dispatchAll(); verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES))); assertNotNull( mTelephonySubscriptionTracker.getReadySubIdsBySlotId().get(TEST_SIM_SLOT_INDEX)); - mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(false)); + sendCarrierConfigChange(false /* hasValidSubscription */); mTestLooper.dispatchAll(); verify(mCallback) .onNewSnapshot( |