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

Commit 18cce100 authored by d34d's avatar d34d Committed by Clark Scheff
Browse files

APN: Filter MVNOs by SPN, GID1 and IMSI

This extends filtering of MVNOs by checking for matches of GID1 and
IMSI.

Change-Id: I7327e0effe30fbec1b3f419f78dcff4061bf13d0
CYNGNOS-670
parent d108c690
Loading
Loading
Loading
Loading
+135 −24
Original line number Diff line number Diff line
@@ -219,10 +219,20 @@ public class ApnSettings extends SettingsPreferenceFragment implements

    private void fillList() {
        String where = getOperatorNumericSelection();
        String[] projection = {
                "_id", "name",
                "apn", "type",
                "read_only",
                "mvno_type",
                "mvno_match_data"
        };
        Cursor cursor = getContentResolver().query(getUri(Telephony.Carriers.CONTENT_URI),
                new String[] {"_id", "name", "apn", "type", "read_only", "mvno_type", "mvno_match_data" }, where, null,
                Telephony.Carriers.DEFAULT_SORT_ORDER);
        String simOperatorName = TelephonyManager.getDefault().getSimOperatorNameForSubscription(mSubId);
                projection, where, null, Telephony.Carriers.DEFAULT_SORT_ORDER);

        final TelephonyManager tm = TelephonyManager.getDefault();
        String simOperatorName = tm.getSimOperatorNameForSubscription(mSubId);
        String imsiSIM = tm.getSubscriberId(mSubId);
        String gid1 = tm.getGroupIdLevel1(mSubId);

        if (cursor != null) {
            PreferenceGroup apnList = (PreferenceGroup) findPreference("apn_list");
@@ -230,9 +240,12 @@ public class ApnSettings extends SettingsPreferenceFragment implements

            ArrayList<Preference> mmsApnList = new ArrayList<Preference>();

            ArrayList<ApnInfo> mvnoSpnList = new ArrayList<ApnInfo>();
            ArrayList<ApnInfo> mvnoGid1List = new ArrayList<ApnInfo>();
            ArrayList<ApnInfo> mvnoImsiList = new ArrayList<ApnInfo>();

            mSelectedKey = getSelectedApnKey();
            cursor.moveToFirst();
            while (!cursor.isAfterLast()) {
            while (cursor.moveToNext()) {
                String name = cursor.getString(NAME_INDEX);
                String apn = cursor.getString(APN_INDEX);
                String key = cursor.getString(ID_INDEX);
@@ -242,28 +255,24 @@ public class ApnSettings extends SettingsPreferenceFragment implements
                String mvnoData = cursor.getString(MVNODATA_INDEX);
                boolean isMvno = !TextUtils.isEmpty(mvnoType) && !TextUtils.isEmpty(mvnoData);

                // Incomplete set of skip rules for MVNOs. We still need
                // something for IMSI and GID mismatches, but those rules
                // are a bit more complex. Still... spn-type is 93% of what
                // we support...
                if (isMvno &&
                  (mvnoType.equalsIgnoreCase("spn") && !mvnoData.equalsIgnoreCase(simOperatorName))) {
                    cursor.moveToNext();
                if (isMvno) {
                    if (!mvnoMatches(mvnoType, mvnoData, simOperatorName, imsiSIM, gid1)) {
                    } else {
                        ApnInfo apnInfo = new ApnInfo(name, apn, key, type, mvnoType, readOnly);
                        if ("sbn".equals(mvnoType)) {
                            mvnoSpnList.add(apnInfo);
                        } else if ("gid".equals(mvnoType)) {
                            mvnoGid1List.add(apnInfo);
                        } else if ("imsi".equals(mvnoType)) {
                            mvnoImsiList.add(apnInfo);
                        }
                    }
                    continue;
                }

                ApnPreference pref = new ApnPreference(getActivity());

                pref.setApnReadOnly(readOnly);
                pref.setKey(key);
                pref.setTitle(name);
                pref.setSummary(apn);
                pref.setPersistent(false);
                pref.setOnPreferenceChangeListener(this);
                ApnPreference pref = createApnPreference(name, key, apn, type, readOnly);

                boolean selectable = ((type == null) || !type.equals("mms"));
                pref.setSelectable(selectable);
                if (selectable) {
                if (pref.getSelectable()) {
                    if ((mSelectedKey != null) && mSelectedKey.equals(key)) {
                        pref.setChecked();
                        Log.d(TAG, "find select key = " + mSelectedKey);
@@ -272,16 +281,98 @@ public class ApnSettings extends SettingsPreferenceFragment implements
                } else {
                    mmsApnList.add(pref);
                }
                cursor.moveToNext();
            }
            cursor.close();

            ArrayList<ApnInfo> mvnoList = null;
            if (mvnoImsiList.size() > 0) {
                mvnoList = mvnoImsiList;
            } else if (mvnoGid1List.size() > 0) {
                mvnoList = mvnoGid1List;
            } else if (mvnoSpnList.size() > 0) {
                mvnoList = mvnoSpnList;
            }
            if (mvnoList != null) {
                for (ApnInfo apnInfo : mvnoList) {
                    ApnPreference pref = createApnPreference(apnInfo.name, apnInfo.key, apnInfo.apn,
                            apnInfo.type, apnInfo.readOnly);
                    if (apnInfo.selectable) {
                        if ((mSelectedKey != null) && mSelectedKey.equals(apnInfo.key)) {
                            pref.setChecked();
                            Log.d(TAG, "find select key = " + mSelectedKey);
                        }
                        apnList.addPreference(pref);
                    } else {
                        mmsApnList.add(pref);
                    }
                }
            }

            for (Preference preference : mmsApnList) {
                apnList.addPreference(preference);
            }
        }
    }

    private ApnPreference createApnPreference(String name, String key,
            String apn, String type, boolean readOnly) {
        ApnPreference pref = new ApnPreference(getActivity());

        pref.setApnReadOnly(readOnly);
        pref.setKey(key);
        pref.setTitle(name);
        pref.setSummary(apn);
        pref.setPersistent(false);
        pref.setOnPreferenceChangeListener(this);

        pref.setSelectable(((type == null) || !type.equals("mms")));
        return pref;
    }

    private static boolean imsiMatches(String imsiDB, String imsiSIM) {
        // Note: imsiDB value has digit number or 'x' character for seperating USIM information
        // for MVNO operator. And then digit number is matched at same order and 'x' character
        // could replace by any digit number.
        // ex) if imsiDB inserted '310260x10xxxxxx' for GG Operator,
        //     that means first 6 digits, 8th and 9th digit
        //     should be set in USIM for GG Operator.
        int len = imsiDB.length();

        if (len <= 0) return false;
        if (len > imsiSIM.length()) return false;

        for (int idx=0; idx<len; idx++) {
            char c = imsiDB.charAt(idx);
            if ((c == 'x') || (c == 'X') || (c == imsiSIM.charAt(idx))) {
                continue;
            } else {
                return false;
            }
        }
        return true;
    }

    private static boolean mvnoMatches(String mvnoType, String mvnoMatchData,
            String serviceProviderName, String imsiSIM, String gid1) {
        if (mvnoType.equalsIgnoreCase("spn")) {
            if ((serviceProviderName != null) &&
                    serviceProviderName.equalsIgnoreCase(mvnoMatchData)) {
                return true;
            }
        } else if (mvnoType.equalsIgnoreCase("imsi")) {
            if ((imsiSIM != null) && imsiMatches(mvnoMatchData, imsiSIM)) {
                return true;
            }
        } else if (mvnoType.equalsIgnoreCase("gid")) {
            int mvno_match_data_length = mvnoMatchData.length();
            if ((gid1 != null) && (gid1.length() >= mvno_match_data_length) &&
                    gid1.substring(0, mvno_match_data_length).equalsIgnoreCase(mvnoMatchData)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        if (!mUnavailable) {
@@ -425,6 +516,26 @@ public class ApnSettings extends SettingsPreferenceFragment implements
        }
    }

    private class ApnInfo {
        String name;
        String apn;
        String key;
        String type;
        String mvnoType;
        boolean readOnly;
        boolean selectable;

        public ApnInfo(String name, String apn, String key, String type, String mvnoType,
                boolean readOnly) {
            this.name = name;
            this.apn = apn;
            this.key = key;
            this.mvnoType = mvnoType;
            this.readOnly = readOnly;
            this.selectable = ((type == null) || !type.equals("mms"));
        }
    }

    @Override
    public Dialog onCreateDialog(int id) {
        if (id == DIALOG_RESTORE_DEFAULTAPN) {