Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f933006c authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge changes from topic "sub_restore" into main am: cfa47674

parents 5d5021a3 cfa47674
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -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;
@@ -42,6 +43,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;
@@ -4951,6 +4953,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
     */
+4 −2
Original line number Diff line number Diff line
@@ -688,8 +688,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) {
+72 −37
Original line number Diff line number Diff line
@@ -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}.
@@ -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.
@@ -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();
    }

    /**
@@ -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.
@@ -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.
@@ -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);
            }
        }
    }

@@ -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(
+54 −6
Original line number Diff line number Diff line
@@ -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;
@@ -220,7 +223,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
@@ -461,8 +464,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);
@@ -542,6 +545,7 @@ public class SubscriptionManagerService extends ISub.Stub {

        SubscriptionManager.invalidateSubscriptionManagerServiceCaches();
        SubscriptionManager.invalidateSubscriptionManagerServiceEnabledCaches();
        logl("created");
    }

    /**
@@ -1310,7 +1314,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);
@@ -2829,7 +2837,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);
@@ -3462,7 +3470,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.
@@ -3561,6 +3569,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}.
     *
@@ -3690,6 +3734,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()));
    }
+7 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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