Loading src/java/com/android/internal/telephony/SubscriptionController.java +34 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static android.telephony.UiccSlotInfo.CARD_STATE_INFO_PRESENT; import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.app.AppOpsManager; import android.app.PendingIntent; import android.app.compat.CompatChanges; Loading @@ -43,6 +44,7 @@ import android.database.Cursor; import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.ParcelUuid; import android.os.PersistableBundle; Loading Loading @@ -4965,6 +4967,38 @@ public class SubscriptionController extends ISub.Stub { return false; } /** * Called during setup wizard restore flow to attempt to restore the backed up sim-specific * configs to device for all existing SIMs in the subscription database {@link SimInfo}. * Internally, it will store the backup data in an internal file. This file will persist on * device for device's lifetime and will be used later on when a SIM is inserted to restore that * specific SIM's settings. End result is subscription database is modified to match any backed * up configs for the appropriate inserted SIMs. * * <p> * The {@link Uri} {@link SubscriptionManager#SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI} is * notified if any {@link SimInfo} entry is updated as the result of this method call. * * @param data with the sim specific configs to be backed up. */ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) @Override public void restoreAllSimSpecificSettingsFromBackup(@NonNull byte[] data) { enforceModifyPhoneState("restoreAllSimSpecificSettingsFromBackup"); long token = Binder.clearCallingIdentity(); try { Bundle bundle = new Bundle(); bundle.putByteArray(SubscriptionManager.KEY_SIM_SPECIFIC_SETTINGS_DATA, data); mContext.getContentResolver().call( SubscriptionManager.SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI, SubscriptionManager.RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME, null, bundle); } finally { Binder.restoreCallingIdentity(token); } } /** * @hide */ Loading src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java +4 −2 Original line number Diff line number Diff line Loading @@ -717,8 +717,10 @@ public class SubscriptionInfoUpdater extends Handler { } private void restoreSimSpecificSettingsForPhone(int phoneId) { SubscriptionManager subManager = SubscriptionManager.from(sContext); subManager.restoreSimSpecificSettingsForIccIdFromBackup(sIccId[phoneId]); sContext.getContentResolver().call( SubscriptionManager.SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI, SubscriptionManager.RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME, sIccId[phoneId], null); } private void updateCarrierServices(int phoneId, String simState) { Loading src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java +72 −37 Original line number Diff line number Diff line Loading @@ -505,8 +505,9 @@ public class SubscriptionDatabaseManager extends Handler { private final Map<Integer, SubscriptionInfoInternal> mAllSubscriptionInfoInternalCache = new HashMap<>(16); /** Whether database has been loaded into the cache after boot up. */ private boolean mDatabaseLoaded = false; /** Whether database has been initialized after boot up. */ @GuardedBy("mDatabaseInitialized") private Boolean mDatabaseInitialized = false; /** * This is the callback used for listening events from {@link SubscriptionDatabaseManager}. Loading Loading @@ -542,9 +543,9 @@ public class SubscriptionDatabaseManager extends Handler { } /** * Called when database has been loaded into the cache. * Called when database has been initialized. */ public abstract void onDatabaseLoaded(); public abstract void onInitialized(); /** * Called when subscription changed. Loading Loading @@ -578,7 +579,7 @@ public class SubscriptionDatabaseManager extends Handler { mUiccController = UiccController.getInstance(); mAsyncMode = mContext.getResources().getBoolean( com.android.internal.R.bool.config_subscription_database_async_update); loadFromDatabase(); initializeDatabase(); } /** Loading Loading @@ -757,10 +758,13 @@ public class SubscriptionDatabaseManager extends Handler { + "insert. subInfo=" + subInfo); } if (!mDatabaseLoaded) { throw new IllegalStateException("Database has not been loaded. Can't insert new " synchronized (mDatabaseInitialized) { if (!mDatabaseInitialized) { throw new IllegalStateException( "Database has not been initialized. Can't insert new " + "record at this point."); } } int subId; // Grab the write lock so no other threads can read or write the cache. Loading Loading @@ -826,11 +830,13 @@ public class SubscriptionDatabaseManager extends Handler { private int updateDatabase(int subId, @NonNull ContentValues contentValues) { logv("updateDatabase: prepare to update sub " + subId); if (!mDatabaseLoaded) { logel("updateDatabase: Database has not been loaded. Can't update database at this " + "point. contentValues=" + contentValues); synchronized (mDatabaseInitialized) { if (!mDatabaseInitialized) { logel("updateDatabase: Database has not been initialized. Can't update database at " + "this point. contentValues=" + contentValues); return 0; } } if (mAsyncMode) { // Perform the update in the handler thread asynchronously. Loading Loading @@ -1794,39 +1800,68 @@ public class SubscriptionDatabaseManager extends Handler { } /** * Load the entire database into the cache. * Reload the database from content provider to the cache. */ private void loadFromDatabase() { // Perform the task in the handler thread. Runnable r = () -> { public void reloadDatabase() { if (mAsyncMode) { post(this::loadDatabaseInternal); } else { loadDatabaseInternal(); } } /** * Load the database from content provider to the cache. */ private void loadDatabaseInternal() { logl("loadDatabaseInternal"); try (Cursor cursor = mContext.getContentResolver().query( SimInfo.CONTENT_URI, null, null, null, null)) { mReadWriteLock.writeLock().lock(); try { mAllSubscriptionInfoInternalCache.clear(); Map<Integer, SubscriptionInfoInternal> newAllSubscriptionInfoInternalCache = new HashMap<>(); while (cursor != null && cursor.moveToNext()) { SubscriptionInfoInternal subInfo = createSubscriptionInfoFromCursor(cursor); if (subInfo != null) { mAllSubscriptionInfoInternalCache .put(subInfo.getSubscriptionId(), subInfo); newAllSubscriptionInfoInternalCache.put(subInfo.getSubscriptionId(), subInfo); if (!Objects.equals(mAllSubscriptionInfoInternalCache .get(subInfo.getSubscriptionId()), subInfo)) { mCallback.invokeFromExecutor(() -> mCallback.onSubscriptionChanged( subInfo.getSubscriptionId())); } } mDatabaseLoaded = true; mCallback.invokeFromExecutor(mCallback::onDatabaseLoaded); log("Loaded " + mAllSubscriptionInfoInternalCache.size() mAllSubscriptionInfoInternalCache.clear(); mAllSubscriptionInfoInternalCache.putAll(newAllSubscriptionInfoInternalCache); logl("Loaded " + mAllSubscriptionInfoInternalCache.size() + " records from the subscription database."); } finally { mReadWriteLock.writeLock().unlock(); } } }; } /** * Initialize the database cache. Load the entire database into the cache. */ private void initializeDatabase() { if (mAsyncMode) { // Load the database asynchronously. post(r); post(() -> { synchronized (mDatabaseInitialized) { loadDatabaseInternal(); mDatabaseInitialized = true; mCallback.invokeFromExecutor(mCallback::onInitialized); } }); } else { // Load the database synchronously. r.run(); synchronized (mDatabaseInitialized) { loadDatabaseInternal(); mDatabaseInitialized = true; mCallback.invokeFromExecutor(mCallback::onInitialized); } } } Loading @@ -1837,7 +1872,7 @@ public class SubscriptionDatabaseManager extends Handler { * * @return The subscription info from a single database record. */ @Nullable @NonNull private SubscriptionInfoInternal createSubscriptionInfoFromCursor(@NonNull Cursor cursor) { SubscriptionInfoInternal.Builder builder = new SubscriptionInfoInternal.Builder(); int id = cursor.getInt(cursor.getColumnIndexOrThrow( Loading src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java +54 −6 Original line number Diff line number Diff line Loading @@ -33,13 +33,16 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.res.Resources; import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.ParcelUuid; import android.os.PersistableBundle; import android.os.Process; import android.os.RemoteException; import android.os.TelephonyServiceManager; import android.os.UserHandle; Loading Loading @@ -221,7 +224,7 @@ public class SubscriptionManagerService extends ISub.Stub { /** Local log for most important debug messages. */ @NonNull private final LocalLog mLocalLog = new LocalLog(128); private final LocalLog mLocalLog = new LocalLog(256); /** The subscription database manager. */ @NonNull Loading Loading @@ -476,8 +479,8 @@ public class SubscriptionManagerService extends ISub.Stub { * Called when database has been loaded into the cache. */ @Override public void onDatabaseLoaded() { log("Subscription database has been loaded."); public void onInitialized() { log("Subscription database has been initialized."); for (int phoneId = 0; phoneId < mTelephonyManager.getActiveModemCount() ; phoneId++) { markSubscriptionsInactive(phoneId); Loading Loading @@ -557,6 +560,7 @@ public class SubscriptionManagerService extends ISub.Stub { SubscriptionManager.invalidateSubscriptionManagerServiceCaches(); SubscriptionManager.invalidateSubscriptionManagerServiceEnabledCaches(); logl("created"); } /** Loading Loading @@ -1335,7 +1339,11 @@ public class SubscriptionManagerService extends ISub.Stub { } // Attempt to restore SIM specific settings when SIM is loaded. mSubscriptionManager.restoreSimSpecificSettingsForIccIdFromBackup(iccId); mContext.getContentResolver().call( SubscriptionManager.SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI, SubscriptionManager.RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME, iccId, null); mSubscriptionDatabaseManager.reloadDatabase(); } } else { log("updateSubscriptions: No ICCID available for phone " + phoneId); Loading Loading @@ -2854,7 +2862,7 @@ public class SubscriptionManagerService extends ISub.Stub { final long token = Binder.clearCallingIdentity(); try { logl("setSubscriptionProperty: subId=" + subId + ", columnName=" + columnName + ", value=" + value); + ", value=" + value + ", calling package=" + getCallingPackage()); if (!SimInfo.getAllColumns().contains(columnName)) { throw new IllegalArgumentException("Invalid column name " + columnName); Loading Loading @@ -3486,7 +3494,7 @@ public class SubscriptionManagerService extends ISub.Stub { * @param subscriptionId the subId of the subscription * @param userHandle user handle of the user * @return {@code true} if subscription is associated with user * {code true} if there are no subscriptions on device * {@code true} if there are no subscriptions on device * else {@code false} if subscription is not associated with user. * * @throws SecurityException if the caller doesn't have permissions required. Loading Loading @@ -3593,6 +3601,42 @@ public class SubscriptionManagerService extends ISub.Stub { return true; } /** * Called during setup wizard restore flow to attempt to restore the backed up sim-specific * configs to device for all existing SIMs in the subscription database {@link SimInfo}. * Internally, it will store the backup data in an internal file. This file will persist on * device for device's lifetime and will be used later on when a SIM is inserted to restore that * specific SIM's settings. End result is subscription database is modified to match any backed * up configs for the appropriate inserted SIMs. * * <p> * The {@link Uri} {@link SubscriptionManager#SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI} is * notified if any {@link SimInfo} entry is updated as the result of this method call. * * @param data with the sim specific configs to be backed up. */ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) @Override public void restoreAllSimSpecificSettingsFromBackup(@NonNull byte[] data) { enforcePermissions("restoreAllSimSpecificSettingsFromBackup", Manifest.permission.MODIFY_PHONE_STATE); long token = Binder.clearCallingIdentity(); try { Bundle bundle = new Bundle(); bundle.putByteArray(SubscriptionManager.KEY_SIM_SPECIFIC_SETTINGS_DATA, data); logl("restoreAllSimSpecificSettingsFromBackup"); mContext.getContentResolver().call( SubscriptionManager.SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI, SubscriptionManager.RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME, null, bundle); // After restoring, we need to reload the content provider into the cache. mSubscriptionDatabaseManager.reloadDatabase(); } finally { Binder.restoreCallingIdentity(token); } } /** * Register the callback for receiving information from {@link SubscriptionManagerService}. * Loading Loading @@ -3737,6 +3781,10 @@ public class SubscriptionManagerService extends ISub.Stub { */ @NonNull private String getCallingPackage() { if (Binder.getCallingUid() == Process.PHONE_UID) { // Too many packages running with phone uid. Just return one here. return "com.android.phone"; } return Arrays.toString(mContext.getPackageManager().getPackagesForUid( Binder.getCallingUid())); } Loading tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java +7 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.annotation.Nullable; import android.content.ContentProvider; import android.content.ContentValues; import android.content.Context; Loading @@ -40,6 +41,7 @@ import android.content.Intent; import android.content.pm.IPackageManager; import android.content.pm.UserInfo; import android.net.Uri; import android.os.Bundle; import android.os.Looper; import android.os.ParcelUuid; import android.os.PersistableBundle; Loading Loading @@ -107,6 +109,11 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest { public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { return mContentProvider.update(uri, values, selection, selectionArgs); } @Override public Bundle call(String method, @Nullable String args, @Nullable Bundle bundle) { return new Bundle(); } } @Before Loading Loading
src/java/com/android/internal/telephony/SubscriptionController.java +34 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static android.telephony.UiccSlotInfo.CARD_STATE_INFO_PRESENT; import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.app.AppOpsManager; import android.app.PendingIntent; import android.app.compat.CompatChanges; Loading @@ -43,6 +44,7 @@ import android.database.Cursor; import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.ParcelUuid; import android.os.PersistableBundle; Loading Loading @@ -4965,6 +4967,38 @@ public class SubscriptionController extends ISub.Stub { return false; } /** * Called during setup wizard restore flow to attempt to restore the backed up sim-specific * configs to device for all existing SIMs in the subscription database {@link SimInfo}. * Internally, it will store the backup data in an internal file. This file will persist on * device for device's lifetime and will be used later on when a SIM is inserted to restore that * specific SIM's settings. End result is subscription database is modified to match any backed * up configs for the appropriate inserted SIMs. * * <p> * The {@link Uri} {@link SubscriptionManager#SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI} is * notified if any {@link SimInfo} entry is updated as the result of this method call. * * @param data with the sim specific configs to be backed up. */ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) @Override public void restoreAllSimSpecificSettingsFromBackup(@NonNull byte[] data) { enforceModifyPhoneState("restoreAllSimSpecificSettingsFromBackup"); long token = Binder.clearCallingIdentity(); try { Bundle bundle = new Bundle(); bundle.putByteArray(SubscriptionManager.KEY_SIM_SPECIFIC_SETTINGS_DATA, data); mContext.getContentResolver().call( SubscriptionManager.SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI, SubscriptionManager.RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME, null, bundle); } finally { Binder.restoreCallingIdentity(token); } } /** * @hide */ Loading
src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java +4 −2 Original line number Diff line number Diff line Loading @@ -717,8 +717,10 @@ public class SubscriptionInfoUpdater extends Handler { } private void restoreSimSpecificSettingsForPhone(int phoneId) { SubscriptionManager subManager = SubscriptionManager.from(sContext); subManager.restoreSimSpecificSettingsForIccIdFromBackup(sIccId[phoneId]); sContext.getContentResolver().call( SubscriptionManager.SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI, SubscriptionManager.RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME, sIccId[phoneId], null); } private void updateCarrierServices(int phoneId, String simState) { Loading
src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java +72 −37 Original line number Diff line number Diff line Loading @@ -505,8 +505,9 @@ public class SubscriptionDatabaseManager extends Handler { private final Map<Integer, SubscriptionInfoInternal> mAllSubscriptionInfoInternalCache = new HashMap<>(16); /** Whether database has been loaded into the cache after boot up. */ private boolean mDatabaseLoaded = false; /** Whether database has been initialized after boot up. */ @GuardedBy("mDatabaseInitialized") private Boolean mDatabaseInitialized = false; /** * This is the callback used for listening events from {@link SubscriptionDatabaseManager}. Loading Loading @@ -542,9 +543,9 @@ public class SubscriptionDatabaseManager extends Handler { } /** * Called when database has been loaded into the cache. * Called when database has been initialized. */ public abstract void onDatabaseLoaded(); public abstract void onInitialized(); /** * Called when subscription changed. Loading Loading @@ -578,7 +579,7 @@ public class SubscriptionDatabaseManager extends Handler { mUiccController = UiccController.getInstance(); mAsyncMode = mContext.getResources().getBoolean( com.android.internal.R.bool.config_subscription_database_async_update); loadFromDatabase(); initializeDatabase(); } /** Loading Loading @@ -757,10 +758,13 @@ public class SubscriptionDatabaseManager extends Handler { + "insert. subInfo=" + subInfo); } if (!mDatabaseLoaded) { throw new IllegalStateException("Database has not been loaded. Can't insert new " synchronized (mDatabaseInitialized) { if (!mDatabaseInitialized) { throw new IllegalStateException( "Database has not been initialized. Can't insert new " + "record at this point."); } } int subId; // Grab the write lock so no other threads can read or write the cache. Loading Loading @@ -826,11 +830,13 @@ public class SubscriptionDatabaseManager extends Handler { private int updateDatabase(int subId, @NonNull ContentValues contentValues) { logv("updateDatabase: prepare to update sub " + subId); if (!mDatabaseLoaded) { logel("updateDatabase: Database has not been loaded. Can't update database at this " + "point. contentValues=" + contentValues); synchronized (mDatabaseInitialized) { if (!mDatabaseInitialized) { logel("updateDatabase: Database has not been initialized. Can't update database at " + "this point. contentValues=" + contentValues); return 0; } } if (mAsyncMode) { // Perform the update in the handler thread asynchronously. Loading Loading @@ -1794,39 +1800,68 @@ public class SubscriptionDatabaseManager extends Handler { } /** * Load the entire database into the cache. * Reload the database from content provider to the cache. */ private void loadFromDatabase() { // Perform the task in the handler thread. Runnable r = () -> { public void reloadDatabase() { if (mAsyncMode) { post(this::loadDatabaseInternal); } else { loadDatabaseInternal(); } } /** * Load the database from content provider to the cache. */ private void loadDatabaseInternal() { logl("loadDatabaseInternal"); try (Cursor cursor = mContext.getContentResolver().query( SimInfo.CONTENT_URI, null, null, null, null)) { mReadWriteLock.writeLock().lock(); try { mAllSubscriptionInfoInternalCache.clear(); Map<Integer, SubscriptionInfoInternal> newAllSubscriptionInfoInternalCache = new HashMap<>(); while (cursor != null && cursor.moveToNext()) { SubscriptionInfoInternal subInfo = createSubscriptionInfoFromCursor(cursor); if (subInfo != null) { mAllSubscriptionInfoInternalCache .put(subInfo.getSubscriptionId(), subInfo); newAllSubscriptionInfoInternalCache.put(subInfo.getSubscriptionId(), subInfo); if (!Objects.equals(mAllSubscriptionInfoInternalCache .get(subInfo.getSubscriptionId()), subInfo)) { mCallback.invokeFromExecutor(() -> mCallback.onSubscriptionChanged( subInfo.getSubscriptionId())); } } mDatabaseLoaded = true; mCallback.invokeFromExecutor(mCallback::onDatabaseLoaded); log("Loaded " + mAllSubscriptionInfoInternalCache.size() mAllSubscriptionInfoInternalCache.clear(); mAllSubscriptionInfoInternalCache.putAll(newAllSubscriptionInfoInternalCache); logl("Loaded " + mAllSubscriptionInfoInternalCache.size() + " records from the subscription database."); } finally { mReadWriteLock.writeLock().unlock(); } } }; } /** * Initialize the database cache. Load the entire database into the cache. */ private void initializeDatabase() { if (mAsyncMode) { // Load the database asynchronously. post(r); post(() -> { synchronized (mDatabaseInitialized) { loadDatabaseInternal(); mDatabaseInitialized = true; mCallback.invokeFromExecutor(mCallback::onInitialized); } }); } else { // Load the database synchronously. r.run(); synchronized (mDatabaseInitialized) { loadDatabaseInternal(); mDatabaseInitialized = true; mCallback.invokeFromExecutor(mCallback::onInitialized); } } } Loading @@ -1837,7 +1872,7 @@ public class SubscriptionDatabaseManager extends Handler { * * @return The subscription info from a single database record. */ @Nullable @NonNull private SubscriptionInfoInternal createSubscriptionInfoFromCursor(@NonNull Cursor cursor) { SubscriptionInfoInternal.Builder builder = new SubscriptionInfoInternal.Builder(); int id = cursor.getInt(cursor.getColumnIndexOrThrow( Loading
src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java +54 −6 Original line number Diff line number Diff line Loading @@ -33,13 +33,16 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.res.Resources; import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.ParcelUuid; import android.os.PersistableBundle; import android.os.Process; import android.os.RemoteException; import android.os.TelephonyServiceManager; import android.os.UserHandle; Loading Loading @@ -221,7 +224,7 @@ public class SubscriptionManagerService extends ISub.Stub { /** Local log for most important debug messages. */ @NonNull private final LocalLog mLocalLog = new LocalLog(128); private final LocalLog mLocalLog = new LocalLog(256); /** The subscription database manager. */ @NonNull Loading Loading @@ -476,8 +479,8 @@ public class SubscriptionManagerService extends ISub.Stub { * Called when database has been loaded into the cache. */ @Override public void onDatabaseLoaded() { log("Subscription database has been loaded."); public void onInitialized() { log("Subscription database has been initialized."); for (int phoneId = 0; phoneId < mTelephonyManager.getActiveModemCount() ; phoneId++) { markSubscriptionsInactive(phoneId); Loading Loading @@ -557,6 +560,7 @@ public class SubscriptionManagerService extends ISub.Stub { SubscriptionManager.invalidateSubscriptionManagerServiceCaches(); SubscriptionManager.invalidateSubscriptionManagerServiceEnabledCaches(); logl("created"); } /** Loading Loading @@ -1335,7 +1339,11 @@ public class SubscriptionManagerService extends ISub.Stub { } // Attempt to restore SIM specific settings when SIM is loaded. mSubscriptionManager.restoreSimSpecificSettingsForIccIdFromBackup(iccId); mContext.getContentResolver().call( SubscriptionManager.SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI, SubscriptionManager.RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME, iccId, null); mSubscriptionDatabaseManager.reloadDatabase(); } } else { log("updateSubscriptions: No ICCID available for phone " + phoneId); Loading Loading @@ -2854,7 +2862,7 @@ public class SubscriptionManagerService extends ISub.Stub { final long token = Binder.clearCallingIdentity(); try { logl("setSubscriptionProperty: subId=" + subId + ", columnName=" + columnName + ", value=" + value); + ", value=" + value + ", calling package=" + getCallingPackage()); if (!SimInfo.getAllColumns().contains(columnName)) { throw new IllegalArgumentException("Invalid column name " + columnName); Loading Loading @@ -3486,7 +3494,7 @@ public class SubscriptionManagerService extends ISub.Stub { * @param subscriptionId the subId of the subscription * @param userHandle user handle of the user * @return {@code true} if subscription is associated with user * {code true} if there are no subscriptions on device * {@code true} if there are no subscriptions on device * else {@code false} if subscription is not associated with user. * * @throws SecurityException if the caller doesn't have permissions required. Loading Loading @@ -3593,6 +3601,42 @@ public class SubscriptionManagerService extends ISub.Stub { return true; } /** * Called during setup wizard restore flow to attempt to restore the backed up sim-specific * configs to device for all existing SIMs in the subscription database {@link SimInfo}. * Internally, it will store the backup data in an internal file. This file will persist on * device for device's lifetime and will be used later on when a SIM is inserted to restore that * specific SIM's settings. End result is subscription database is modified to match any backed * up configs for the appropriate inserted SIMs. * * <p> * The {@link Uri} {@link SubscriptionManager#SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI} is * notified if any {@link SimInfo} entry is updated as the result of this method call. * * @param data with the sim specific configs to be backed up. */ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) @Override public void restoreAllSimSpecificSettingsFromBackup(@NonNull byte[] data) { enforcePermissions("restoreAllSimSpecificSettingsFromBackup", Manifest.permission.MODIFY_PHONE_STATE); long token = Binder.clearCallingIdentity(); try { Bundle bundle = new Bundle(); bundle.putByteArray(SubscriptionManager.KEY_SIM_SPECIFIC_SETTINGS_DATA, data); logl("restoreAllSimSpecificSettingsFromBackup"); mContext.getContentResolver().call( SubscriptionManager.SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI, SubscriptionManager.RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME, null, bundle); // After restoring, we need to reload the content provider into the cache. mSubscriptionDatabaseManager.reloadDatabase(); } finally { Binder.restoreCallingIdentity(token); } } /** * Register the callback for receiving information from {@link SubscriptionManagerService}. * Loading Loading @@ -3737,6 +3781,10 @@ public class SubscriptionManagerService extends ISub.Stub { */ @NonNull private String getCallingPackage() { if (Binder.getCallingUid() == Process.PHONE_UID) { // Too many packages running with phone uid. Just return one here. return "com.android.phone"; } return Arrays.toString(mContext.getPackageManager().getPackagesForUid( Binder.getCallingUid())); } Loading
tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java +7 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.annotation.Nullable; import android.content.ContentProvider; import android.content.ContentValues; import android.content.Context; Loading @@ -40,6 +41,7 @@ import android.content.Intent; import android.content.pm.IPackageManager; import android.content.pm.UserInfo; import android.net.Uri; import android.os.Bundle; import android.os.Looper; import android.os.ParcelUuid; import android.os.PersistableBundle; Loading Loading @@ -107,6 +109,11 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest { public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { return mContentProvider.update(uri, values, selection, selectionArgs); } @Override public Bundle call(String method, @Nullable String args, @Nullable Bundle bundle) { return new Bundle(); } } @Before Loading