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

Commit d922de0e authored by shuoq's avatar shuoq Committed by sqian
Browse files

Cache the getActiveSubscriptionInfoList() in SubscriptionController

To fast reading the active subscription info list (the subinfo list
currently in the phone slotes), a cache is created and maintained inside
the SubscriptionController.

To protect cache, refresh the content of the cache every time there
is an update on the database, populate/regenerate the cache with
the updated information and thereby the reference of the cache object
will be changed.

When getting an Active Subscription Info list, get a deep copy of the
cache instead of its reference.

Test: Manual
Bug: 29877775
Change-Id: Ib26c550d63d4befa6f71ef82dfd6d73579b17e24
Merged-In: Ib26c550d63d4befa6f71ef82dfd6d73579b17e24
parent 86efdde1
Loading
Loading
Loading
Loading
+95 −4
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
@@ -84,9 +85,13 @@ public class SubscriptionController extends ISub.Stub {
    static final String LOG_TAG = "SubscriptionController";
    static final boolean DBG = true;
    static final boolean VDBG = false;
    static final boolean DBG_CACHE = false;
    static final int MAX_LOCAL_LOG_LINES = 500; // TODO: Reduce to 100 when 17678050 is fixed
    private ScLocalLog mLocalLog = new ScLocalLog(MAX_LOCAL_LOG_LINES);

    /* The Cache of Active SubInfoRecord(s) list of currently in use SubInfoRecord(s) */
    private AtomicReference<List<SubscriptionInfo>> mCacheActiveSubInfoList = new AtomicReference();

    /**
     * Copied from android.util.LocalLog with flush() adding flush and line number
     * TODO: Update LocalLog
@@ -590,6 +595,43 @@ public class SubscriptionController extends ISub.Stub {
                return null;
            }

            // Get the active subscription info list from the cache if the cache is not null
            List<SubscriptionInfo> tmpCachedSubList = mCacheActiveSubInfoList.get();
            if (tmpCachedSubList != null) {
                if (DBG_CACHE) {
                    for (SubscriptionInfo si : tmpCachedSubList) {
                        logd("[getActiveSubscriptionInfoList] Getting Cached subInfo=" + si);
                    }
                }
                return new ArrayList<SubscriptionInfo>(tmpCachedSubList);
            } else {
                if (DBG_CACHE) {
                    logd("[getActiveSubscriptionInfoList] Cached subInfo is null");
                }
                return null;
            }
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    /**
     * Refresh the cache of SubInfoRecord(s) of the currently inserted SIM(s)
     */
    @VisibleForTesting
    protected void refreshCachedActiveSubscriptionInfoList() {

        // Now that all security checks passes, perform the operation as ourselves.
        final long identity = Binder.clearCallingIdentity();
        try {
            if (!isSubInfoReady()) {
                if (DBG_CACHE) {
                    logdl("[refreshCachedActiveSubscriptionInfoList] "
                            + "Sub Controller not ready ");
                }
                return;
            }

            List<SubscriptionInfo> subList = getSubInfo(
                    SubscriptionManager.SIM_SLOT_INDEX + ">=0", null);

@@ -597,12 +639,21 @@ public class SubscriptionController extends ISub.Stub {
                // FIXME: Unnecessary when an insertion sort is used!
                subList.sort(SUBSCRIPTION_INFO_COMPARATOR);

                if (VDBG) logdl("[getActiveSubInfoList]- " + subList.size() + " infos return");
                if (DBG_CACHE) {
                    logdl("[refreshCachedActiveSubscriptionInfoList]- " + subList.size()
                            + " infos return");
                }
            } else {
                if (DBG) logdl("[getActiveSubInfoList]- no info return");
                if (DBG_CACHE) logdl("[refreshCachedActiveSubscriptionInfoList]- no info return");
            }

            return subList;
            if (DBG_CACHE) {
                for (SubscriptionInfo si : subList) {
                    logd("[refreshCachedActiveSubscriptionInfoList] Setting Cached subInfo=" + si);
                }
            }
            mCacheActiveSubInfoList.set(subList);

        } finally {
            Binder.restoreCallingIdentity(identity);
        }
@@ -883,6 +934,9 @@ public class SubscriptionController extends ISub.Stub {
                        resolver.update(SubscriptionManager.CONTENT_URI, value,
                                SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID +
                                        "=" + Long.toString(subId), null);

                        // Refresh the Cache of Active Subscription Info List
                        refreshCachedActiveSubscriptionInfoList();
                    }

                    if (DBG) logdl("[addSubInfoRecord] Record already exists");
@@ -975,6 +1029,9 @@ public class SubscriptionController extends ISub.Stub {
                        SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID +
                                "=" + Long.toString(subId), null);

                // Refresh the Cache of Active Subscription Info List
                refreshCachedActiveSubscriptionInfoList();

                if (DBG) logdl("[addSubInfoRecord] sim name = " + nameToSet);
            }

@@ -1007,7 +1064,13 @@ public class SubscriptionController extends ISub.Stub {
        value.put(SubscriptionManager.COLOR, color);
        value.put(SubscriptionManager.SIM_SLOT_INDEX, slotIndex);
        value.put(SubscriptionManager.CARRIER_NAME, "");
        return resolver.insert(SubscriptionManager.CONTENT_URI, value);

        Uri uri = resolver.insert(SubscriptionManager.CONTENT_URI, value);

        // Refresh the Cache of Active Subscription Info List
        refreshCachedActiveSubscriptionInfoList();

        return uri;
    }

    /**
@@ -1073,6 +1136,10 @@ public class SubscriptionController extends ISub.Stub {
            int result = mContext.getContentResolver().update(SubscriptionManager.CONTENT_URI,
                    value, SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=" +
                    Long.toString(subId), null);

            // Refresh the Cache of Active Subscription Info List
            refreshCachedActiveSubscriptionInfoList();

            notifySubscriptionInfoChanged();

            return result;
@@ -1104,6 +1171,10 @@ public class SubscriptionController extends ISub.Stub {
            int result = mContext.getContentResolver().update(SubscriptionManager.CONTENT_URI,
                    value, SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=" +
                            Long.toString(subId), null);

            // Refresh the Cache of Active Subscription Info List
            refreshCachedActiveSubscriptionInfoList();

            notifySubscriptionInfoChanged();

            return result;
@@ -1164,6 +1235,10 @@ public class SubscriptionController extends ISub.Stub {
            int result = mContext.getContentResolver().update(SubscriptionManager.CONTENT_URI,
                    value, SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=" +
                    Long.toString(subId), null);

            // Refresh the Cache of Active Subscription Info List
            refreshCachedActiveSubscriptionInfoList();

            notifySubscriptionInfoChanged();

            return result;
@@ -1206,6 +1281,10 @@ public class SubscriptionController extends ISub.Stub {
            result = mContext.getContentResolver().update(SubscriptionManager.CONTENT_URI, value,
                    SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID
                            + "=" + Long.toString(subId), null);

            // Refresh the Cache of Active Subscription Info List
            refreshCachedActiveSubscriptionInfoList();

            if (DBG) logd("[setDisplayNumber]- update result :" + result);
            notifySubscriptionInfoChanged();

@@ -1242,6 +1321,10 @@ public class SubscriptionController extends ISub.Stub {
            int result = mContext.getContentResolver().update(SubscriptionManager.CONTENT_URI,
                    value, SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=" +
                    Long.toString(subId), null);

            // Refresh the Cache of Active Subscription Info List
            refreshCachedActiveSubscriptionInfoList();

            notifySubscriptionInfoChanged();

            return result;
@@ -1272,6 +1355,10 @@ public class SubscriptionController extends ISub.Stub {

        int result = mContext.getContentResolver().update(SubscriptionManager.CONTENT_URI, value,
                SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=" + Long.toString(subId), null);

        // Refresh the Cache of Active Subscription Info List
        refreshCachedActiveSubscriptionInfoList();

        notifySubscriptionInfoChanged();

        return result;
@@ -1918,6 +2005,10 @@ public class SubscriptionController extends ISub.Stub {
        resolver.update(SubscriptionManager.CONTENT_URI, value,
                SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID +
                        "=" + Integer.toString(subId), null);

        // Refresh the Cache of Active Subscription Info List
        refreshCachedActiveSubscriptionInfoList();

        Binder.restoreCallingIdentity(token);
    }

+18 −0
Original line number Diff line number Diff line
@@ -425,6 +425,9 @@ public class SubscriptionInfoUpdater extends Handler {
                    contentResolver.update(SubscriptionManager.CONTENT_URI, number,
                            SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "="
                                    + Long.toString(subId), null);

                    // refresh Cached Active Subscription Info List
                    SubscriptionController.getInstance().refreshCachedActiveSubscriptionInfoList();
                }

                SubscriptionInfo subInfo = mSubscriptionManager.getActiveSubscriptionInfo(subId);
@@ -444,6 +447,9 @@ public class SubscriptionInfoUpdater extends Handler {
                    contentResolver.update(SubscriptionManager.CONTENT_URI, name,
                            SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID
                                    + "=" + Long.toString(subId), null);

                    // refresh Cached Active Subscription Info List
                    SubscriptionController.getInstance().refreshCachedActiveSubscriptionInfoList();
                }

                /* Update preferred network type and network selection mode on SIM change.
@@ -570,6 +576,9 @@ public class SubscriptionInfoUpdater extends Handler {
                    contentResolver.update(SubscriptionManager.CONTENT_URI, value,
                            SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "="
                            + Integer.toString(oldSubInfo.get(0).getSubscriptionId()), null);

                    // refresh Cached Active Subscription Info List
                    SubscriptionController.getInstance().refreshCachedActiveSubscriptionInfoList();
                }
            } else {
                if (mInsertSimState[i] == SIM_NOT_CHANGE) {
@@ -647,6 +656,9 @@ public class SubscriptionInfoUpdater extends Handler {
                contentResolver.update(SubscriptionManager.CONTENT_URI, value,
                        SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "="
                        + Integer.toString(temp.getSubscriptionId()), null);

                // refresh Cached Active Subscription Info List
                SubscriptionController.getInstance().refreshCachedActiveSubscriptionInfoList();
            }
        }

@@ -719,6 +731,9 @@ public class SubscriptionInfoUpdater extends Handler {
            values.put(SubscriptionManager.NAME_SOURCE, SubscriptionManager.NAME_SOURCE_USER_INPUT);
            contentResolver.update(SubscriptionManager.CONTENT_URI, values,
                    SubscriptionManager.ICC_ID + "=\"" + embeddedProfile.iccid + "\"", null);

            // refresh Cached Active Subscription Info List
            SubscriptionController.getInstance().refreshCachedActiveSubscriptionInfoList();
        }

        // Remove all remaining subscriptions which have embedded = true. We set embedded to false
@@ -738,6 +753,9 @@ public class SubscriptionInfoUpdater extends Handler {
            ContentValues values = new ContentValues();
            values.put(SubscriptionManager.IS_EMBEDDED, 0);
            contentResolver.update(SubscriptionManager.CONTENT_URI, values, whereClause, null);

            // refresh Cached Active Subscription Info List
            SubscriptionController.getInstance().refreshCachedActiveSubscriptionInfoList();
        }
    }

+27 −0
Original line number Diff line number Diff line
@@ -242,6 +242,33 @@ public class SubscriptionControllerTest extends TelephonyTest {
                captorIntent.getValue().getAction());
    }

    @Test @SmallTest
    public void testSetGetDisplayNameSrc() {
        testInsertSim();

        /* Get SUB ID */
        int[] subIds = mSubscriptionControllerUT.getActiveSubIdList();
        assertTrue(subIds != null && subIds.length != 0);
        int subID = subIds[0];

        /* Setting */
        String disName = "TESTING";
        long nameSource = 1;
        mSubscriptionControllerUT.setDisplayNameUsingSrc(disName, subID, nameSource);
        SubscriptionInfo subInfo = mSubscriptionControllerUT
                .getActiveSubscriptionInfo(subID, mCallingPackage);
        assertNotNull(subInfo);
        assertEquals(disName, subInfo.getDisplayName());
        assertEquals(nameSource, subInfo.getNameSource());

        /* verify broadcast intent */
        ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class);
        verify(mContext, atLeast(1)).sendBroadcast(captorIntent.capture());
        assertEquals(TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED,
                captorIntent.getValue().getAction());

    }

    @Test @SmallTest
    public void testCleanUpSIM() {
        testInsertSim();