Merge "Add dispatcher activity to forward privileged euicc intents." am: 0cad33a5bc
am: 6c1f9973df

Change-Id: I1e0b704a9415ec9dca3e5c1a4f862c33c422a0ad
diff --git a/res/layout/emergency_shortcut_buttons_group.xml b/res/layout/emergency_shortcut_buttons_group.xml
index 54563c9..7911f30 100644
--- a/res/layout/emergency_shortcut_buttons_group.xml
+++ b/res/layout/emergency_shortcut_buttons_group.xml
@@ -77,4 +77,4 @@
         android:divider="@drawable/emergency_shortcuts_divider"
         android:showDividers="middle">
     </LinearLayout>
-</LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index cce7ebc..bf152c9 100644
--- a/res/values-en-rCA/strings.xml
+++ b/res/values-en-rCA/strings.xml
@@ -245,7 +245,7 @@
     <string name="data_usage_title" msgid="8759619109516889802">"Data usage"</string>
     <string name="data_usage_template" msgid="8526428824844656364">"<xliff:g id="ID_1">%1$s</xliff:g> mobile data used <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="advanced_options_title" msgid="8074895510265488035">"Advanced"</string>
-    <string name="carrier_settings_euicc" msgid="6714062862127226405">"Operator"</string>
+    <string name="carrier_settings_euicc" msgid="6714062862127226405">"Carrier"</string>
     <string name="keywords_carrier_settings_euicc" msgid="6861505396475991277">"operator, esim, sim, euicc, switch operators, add operator"</string>
     <string name="carrier_settings_euicc_summary" msgid="5115001942761995457">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g> — <xliff:g id="PHONE_NUMBER">%2$s</xliff:g>"</string>
     <string name="mobile_data_settings_title" msgid="4661165467914727157">"Mobile data"</string>
diff --git a/src/com/android/phone/ecc/CountryEccInfo.java b/src/com/android/phone/ecc/CountryEccInfo.java
deleted file mode 100644
index 969901d..0000000
--- a/src/com/android/phone/ecc/CountryEccInfo.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.phone.ecc;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.util.Collection;
-
-/**
- * ECC info of a country.
- */
-public class CountryEccInfo {
-    private final String mFallbackEcc;
-    private final EccInfo[] mEccInfoList;
-
-    public CountryEccInfo(String eccFallback, @NonNull Collection<EccInfo> eccInfoList) {
-        mFallbackEcc = eccFallback;
-        mEccInfoList = eccInfoList.toArray(new EccInfo[eccInfoList.size()]);
-    }
-
-    /**
-     * @return fallback ECC, null if not available.
-     */
-    public @Nullable String getFallbackEcc() {
-        return mFallbackEcc;
-    }
-
-    public @NonNull EccInfo[] getEccInfoList() {
-        return mEccInfoList.clone();
-    }
-}
diff --git a/src/com/android/phone/ecc/EccInfo.java b/src/com/android/phone/ecc/EccInfo.java
deleted file mode 100644
index fb41370..0000000
--- a/src/com/android/phone/ecc/EccInfo.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.phone.ecc;
-
-import androidx.annotation.NonNull;
-
-import java.util.Collection;
-
-/**
- * Emergency call code info.
- */
-public class EccInfo {
-    /**
-     * ECC Types.
-     */
-    public enum Type {
-        POLICE,
-        AMBULANCE,
-        FIRE,
-    }
-
-    private final String mNumber;
-    private final Type[] mTypes;
-
-    public EccInfo(@NonNull String number, @NonNull Type type) {
-        mNumber = number;
-        mTypes = new Type[]{ type };
-    }
-
-    public EccInfo(@NonNull String number, @NonNull Collection<Type> types) {
-        mNumber = number;
-        mTypes = types.toArray(new Type[types.size()]);
-    }
-
-    /**
-     * @return ECC number.
-     */
-    public @NonNull String getNumber() {
-        return mNumber;
-    }
-
-    /**
-     * Check whether the ECC number has any matches to the target type.
-     *
-     * @param target The target type to check.
-     * @return true if the target matches.
-     */
-    public boolean containsType(@NonNull Type target) {
-        for (Type type : mTypes) {
-            if (target.equals(type)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Get the types of the ECC number.
-     *
-     * @return Copied types array.
-     */
-    public Type[] getTypes() {
-        return mTypes.clone();
-    }
-
-    /**
-     * Get how many types the ECC number is.
-     *
-     * @return Count of types.
-     */
-    public int getTypesCount() {
-        return mTypes.length;
-    }
-}
diff --git a/src/com/android/phone/ecc/EccInfoHelper.java b/src/com/android/phone/ecc/EccInfoHelper.java
deleted file mode 100644
index c471c4b..0000000
--- a/src/com/android/phone/ecc/EccInfoHelper.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.phone.ecc;
-
-import android.content.Context;
-import android.os.AsyncTask;
-import android.provider.Settings;
-import android.telephony.CellIdentityGsm;
-import android.telephony.CellIdentityLte;
-import android.telephony.CellIdentityWcdma;
-import android.telephony.CellInfo;
-import android.telephony.CellInfoGsm;
-import android.telephony.CellInfoLte;
-import android.telephony.CellInfoWcdma;
-import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.Pair;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.internal.telephony.MccTable;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Helper for retrieve ECC info for current country.
- */
-public class EccInfoHelper {
-    // Debug constants.
-    private static final boolean DBG = false;
-    private static final String LOG_TAG = "EccInfoHelper";
-
-    /**
-     * Check if current CountryEccInfo is available for current environment.
-     */
-    public static boolean isCountryEccInfoAvailable(Context context, String countryIso) {
-        CountryEccInfo countryEccInfo;
-        try {
-            countryEccInfo = IsoToEccProtobufRepository.getInstance()
-                    .getCountryEccInfo(context, countryIso);
-        } catch (IOException e) {
-            Log.e(LOG_TAG, "Failed to retrieve ECC: ", e);
-            return false;
-        }
-
-        if (countryEccInfo == null) {
-            return false;
-        }
-        for (EccInfo entry : countryEccInfo.getEccInfoList()) {
-            if (!PhoneNumberUtils.isEmergencyNumber(entry.getNumber())) {
-                // The CountryEccInfo is unavailable if any ecc number in the local table was
-                // declined.
-                return false;
-            }
-        }
-        return true;
-    }
-
-    // country ISO to ECC list data source
-    private IsoToEccRepository mEccRepo;
-
-    /**
-     * Callback for {@link #getCountryEccInfoAsync}.
-     */
-    public interface CountryEccInfoResultCallback {
-        /**
-         * Called if successfully get country ECC info.
-         *
-         * @param iso Detected current country ISO.
-         * @param countryEccInfo The EccInfo of current country.
-         */
-        void onSuccess(@NonNull String iso, @NonNull CountryEccInfo countryEccInfo);
-
-        /**
-         * Called if failed to get country ISO.
-         */
-        void onDetectCountryFailed();
-
-        /**
-         * Called if failed to get ECC info for given country ISO.
-         *
-         * @param iso Detected current country ISO.
-         */
-        void onRetrieveCountryEccInfoFailed(@NonNull String iso);
-    }
-
-    /**
-     * Constructor of EccInfoHelper
-     *
-     * @param eccRepository A repository for ECC info, indexed by country ISO.
-     */
-    public EccInfoHelper(@NonNull IsoToEccRepository eccRepository) {
-        mEccRepo = eccRepository;
-    }
-
-    /**
-     * Get ECC info for current location, base on detected country ISO.
-     * It's possible we cannot detect current country, ex. device is in airplane mode,
-     * or there's no available base station near by.
-     *
-     * @param context The context used to access resources.
-     * @param callback Callback for result.
-     */
-    public void getCountryEccInfoAsync(final @NonNull Context context,
-            final CountryEccInfoResultCallback callback) {
-        new AsyncTask<Void, Void, Pair<String, CountryEccInfo>>() {
-            @Override
-            protected Pair<String, CountryEccInfo> doInBackground(Void... voids) {
-                String iso = getCurrentCountryIso(context);
-                if (TextUtils.isEmpty(iso)) {
-                    return null;
-                }
-
-                CountryEccInfo dialableCountryEccInfo;
-                try {
-                    // access data source in background thread to avoid possible file IO caused ANR.
-                    CountryEccInfo rawEccInfo = mEccRepo.getCountryEccInfo(context, iso);
-                    dialableCountryEccInfo = getDialableCountryEccInfo(rawEccInfo);
-                } catch (IOException e) {
-                    Log.e(LOG_TAG, "Failed to retrieve ECC: " + e.getMessage());
-                    dialableCountryEccInfo = null;
-                }
-                return new Pair<>(iso, dialableCountryEccInfo);
-            }
-
-            @Override
-            protected void onPostExecute(Pair<String, CountryEccInfo> result) {
-                if (callback != null) {
-                    if (result == null) {
-                        callback.onDetectCountryFailed();
-                    } else {
-                        String iso = result.first;
-                        CountryEccInfo countryEccInfo = result.second;
-                        if (countryEccInfo == null) {
-                            callback.onRetrieveCountryEccInfoFailed(iso);
-                        } else {
-                            callback.onSuccess(iso, countryEccInfo);
-                        }
-                    }
-                }
-            }
-        }.execute();
-    }
-
-    @NonNull
-    private CountryEccInfo getDialableCountryEccInfo(CountryEccInfo countryEccInfo) {
-        ArrayList<EccInfo> dialableECCList = new ArrayList<>();
-        String dialableFallback = null;
-
-        // filter out non-dialable ECC
-        if (countryEccInfo != null) {
-            for (EccInfo entry : countryEccInfo.getEccInfoList()) {
-                if (PhoneNumberUtils.isEmergencyNumber(entry.getNumber())) {
-                    dialableECCList.add(entry);
-                }
-            }
-            String defaultFallback = countryEccInfo.getFallbackEcc();
-            if (PhoneNumberUtils.isEmergencyNumber(defaultFallback)) {
-                dialableFallback = defaultFallback;
-            }
-        }
-        return new CountryEccInfo(dialableFallback, dialableECCList);
-    }
-
-    @Nullable
-    private String getCurrentCountryIso(@NonNull Context context) {
-        // Do not detect country ISO if airplane mode is on
-        int airplaneMode = Settings.System.getInt(context.getContentResolver(),
-                Settings.Global.AIRPLANE_MODE_ON, 0);
-        if (airplaneMode != 0) {
-            Log.d(LOG_TAG, "Airplane mode is on, do not get country ISO.");
-            return null;
-        }
-
-        TelephonyManager tm = (TelephonyManager) context.getSystemService(
-                Context.TELEPHONY_SERVICE);
-        String iso = tm.getNetworkCountryIso();
-        if (DBG) Log.d(LOG_TAG, "Current country ISO is " + Rlog.pii(LOG_TAG, iso));
-
-        if (TextUtils.isEmpty(iso)) {
-            // XXX: according to ServiceStateTracker's implementation, retrieve cell info in a
-            // thread other than TelephonyManager's main thread.
-            String mcc = getCurrentMccFromCellInfo(context);
-            iso = MccTable.countryCodeForMcc(mcc);
-            if (DBG) {
-                Log.d(LOG_TAG, "Current mcc is " + Rlog.pii(LOG_TAG, mcc) + ", mapping to ISO: "
-                        + Rlog.pii(LOG_TAG, iso));
-            }
-        }
-        return iso;
-    }
-
-    // XXX: According to ServiceStateTracker implementation, to actually get current cell info,
-    // this method must be called in a separate thread from ServiceStateTracker, which is the
-    // main thread of Telephony service.
-    @Nullable
-    private String getCurrentMccFromCellInfo(@NonNull Context context) {
-        // retrieve mcc info from base station even no SIM present.
-        TelephonyManager tm = (TelephonyManager) context.getSystemService(
-                Context.TELEPHONY_SERVICE);
-        List<CellInfo> cellInfos = tm.getAllCellInfo();
-        String mcc = null;
-        if (cellInfos != null) {
-            for (CellInfo ci : cellInfos) {
-                if (ci instanceof CellInfoGsm) {
-                    CellInfoGsm cellInfoGsm = (CellInfoGsm) ci;
-                    CellIdentityGsm cellIdentityGsm = cellInfoGsm.getCellIdentity();
-                    mcc = cellIdentityGsm.getMccString();
-                    break;
-                } else if (ci instanceof CellInfoWcdma) {
-                    CellInfoWcdma cellInfoWcdma = (CellInfoWcdma) ci;
-                    CellIdentityWcdma cellIdentityWcdma = cellInfoWcdma.getCellIdentity();
-                    mcc = cellIdentityWcdma.getMccString();
-                    break;
-                } else if (ci instanceof CellInfoLte) {
-                    CellInfoLte cellInfoLte = (CellInfoLte) ci;
-                    CellIdentityLte cellIdentityLte = cellInfoLte.getCellIdentity();
-                    mcc = cellIdentityLte.getMccString();
-                    break;
-                }
-            }
-            if (DBG) Log.d(LOG_TAG, "Retrieve MCC from cell info list: " + Rlog.pii(LOG_TAG, mcc));
-        } else {
-            Log.w(LOG_TAG, "Cannot get cell info list.");
-        }
-        return mcc;
-    }
-}
diff --git a/src/com/android/phone/ecc/IsoToEccProtobufRepository.java b/src/com/android/phone/ecc/IsoToEccProtobufRepository.java
deleted file mode 100644
index 7d9b4f0..0000000
--- a/src/com/android/phone/ecc/IsoToEccProtobufRepository.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.phone.ecc;
-
-import android.content.Context;
-import android.os.SystemClock;
-import android.text.TextUtils;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.zip.GZIPInputStream;
-
-/**
- * Provides a mapping table from country ISO to ECC info. The data is stored in Protocol Buffers
- * binary format, compressed with GZIP.
- */
-public class IsoToEccProtobufRepository implements IsoToEccRepository {
-    private static final String LOG_TAG = "EccRepository";
-
-    private static IsoToEccProtobufRepository sInstance;
-
-    /**
-     * Returns the singleton instance of IsoToEccProtobufRepository
-     */
-    public static synchronized IsoToEccProtobufRepository getInstance() {
-        if (sInstance == null) {
-            sInstance = new IsoToEccProtobufRepository();
-        }
-        return sInstance;
-    }
-
-    private final Map<String, CountryEccInfo> mEccTable = new HashMap<>();
-
-    private IsoToEccProtobufRepository() {
-    }
-
-    @Override
-    @Nullable
-    public CountryEccInfo getCountryEccInfo(@NonNull Context context, String iso)
-            throws IOException {
-        if (TextUtils.isEmpty(iso)) {
-            return null;
-        }
-
-        synchronized (mEccTable) {
-            return mEccTable.get(iso.toUpperCase());
-        }
-    }
-
-    /**
-     * Loads the mapping table.
-     */
-    public void loadMappingTable(@NonNull Context context) {
-        ProtobufEccData.AllInfo allEccData = null;
-
-        long startTime = SystemClock.uptimeMillis();
-        try {
-            allEccData = parseEccData(new BufferedInputStream(
-                    context.getAssets().open("eccdata")));
-        } catch (IOException e) {
-            Log.e(LOG_TAG, "Failed to retrieve ECC: ", e);
-        }
-        long endTime = SystemClock.uptimeMillis();
-
-        if (allEccData == null) {
-            return;
-        }
-
-        if (Log.isLoggable(LOG_TAG, Log.DEBUG)) {
-            Log.d(LOG_TAG, "Loading time = " + (endTime - startTime) + "ms"
-                    + ", Country Count = " + allEccData.getCountriesCount()
-                    + ", initialized = " + allEccData.isInitialized());
-        }
-
-        // Converts to run-time data from Protobuf data.
-        synchronized (mEccTable) {
-            mEccTable.clear();
-            for (ProtobufEccData.CountryInfo countryData : allEccData.getCountriesList()) {
-                if (countryData.hasIsoCode()) {
-                    CountryEccInfo countryInfo = loadCountryEccInfo(countryData);
-                    if (countryInfo != null) {
-                        mEccTable.put(countryData.getIsoCode().toUpperCase(), countryInfo);
-                    }
-                }
-            }
-        }
-    }
-
-    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
-    Map<String, CountryEccInfo> getEccTable() {
-        return mEccTable;
-    }
-
-    private ProtobufEccData.AllInfo parseEccData(InputStream input) throws IOException {
-        return ProtobufEccData.AllInfo.parseFrom(new GZIPInputStream(input));
-    }
-
-    private EccInfo loadEccInfo(String isoCode, ProtobufEccData.EccInfo eccData) {
-        String phoneNumber = eccData.getPhoneNumber().trim();
-        if (phoneNumber.isEmpty()) {
-            Log.i(LOG_TAG, "Discard ecc " + phoneNumber
-                    + " for " + isoCode + " due to empty phone number");
-            return null;
-        }
-
-        ArraySet<EccInfo.Type> eccTypes = new ArraySet<>(eccData.getTypesCount());
-        for (ProtobufEccData.EccInfo.Type typeData : eccData.getTypesList()) {
-            switch (typeData) {
-                case POLICE:
-                    eccTypes.add(EccInfo.Type.POLICE);
-                    break;
-                case AMBULANCE:
-                    eccTypes.add(EccInfo.Type.AMBULANCE);
-                    break;
-                case FIRE:
-                    eccTypes.add(EccInfo.Type.FIRE);
-                    break;
-                default:
-                    // Ignores unknown types.
-            }
-        }
-
-        if (eccTypes.isEmpty()) {
-            Log.i(LOG_TAG, "Discard ecc " + phoneNumber
-                    + " for " + isoCode + " due to no valid type");
-            return null;
-        }
-        return new EccInfo(phoneNumber, eccTypes);
-    }
-
-    private CountryEccInfo loadCountryEccInfo(ProtobufEccData.CountryInfo countryData) {
-        ArrayMap<String, EccInfo> eccInfoMap = new ArrayMap<>(countryData.getEccsCount());
-        for (ProtobufEccData.EccInfo eccData : countryData.getEccsList()) {
-            EccInfo eccInfo = loadEccInfo(countryData.getIsoCode(), eccData);
-            String key = eccInfo.getNumber().trim();
-            EccInfo existentEccInfo = eccInfoMap.get(key);
-            if (existentEccInfo == null) {
-                eccInfoMap.put(key, eccInfo);
-            } else {
-                // Merges types of duplicated ECC info objects.
-                ArraySet<EccInfo.Type> eccTypes = new ArraySet<>(
-                        eccInfo.getTypesCount() + existentEccInfo.getTypesCount());
-                for (EccInfo.Type type : eccInfo.getTypes()) {
-                    eccTypes.add(type);
-                }
-                for (EccInfo.Type type : existentEccInfo.getTypes()) {
-                    eccTypes.add(type);
-                }
-                eccInfoMap.put(key, new EccInfo(eccInfo.getNumber(), eccTypes));
-            }
-        }
-
-        if (eccInfoMap.isEmpty() && !countryData.hasEccFallback()) {
-            Log.i(LOG_TAG, "Discard empty data for " + countryData.getIsoCode());
-            return null;
-        }
-        return new CountryEccInfo(countryData.getEccFallback(), eccInfoMap.values());
-    }
-}
diff --git a/src/com/android/phone/ecc/IsoToEccRepository.java b/src/com/android/phone/ecc/IsoToEccRepository.java
deleted file mode 100644
index 6d95af4..0000000
--- a/src/com/android/phone/ecc/IsoToEccRepository.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.phone.ecc;
-
-import android.content.Context;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.io.IOException;
-
-/**
- * Data source for country ISO to ECC info list mapping.
- */
-public interface IsoToEccRepository {
-    /**
-     * Get available emergency numbers for given country ISO. Because the possible of IO wait
-     * (depends on the implementation), this method should not be called in the main thread.
-     *
-     * @param context The context used to access resources.
-     * @param iso For which ECC info list is returned.
-     * @return The ECC info of given ISO. Null if no match.
-     * @throws IOException if an error occurs while initialize the repository or retrieving
-     * the {@link CountryEccInfo}.
-     */
-    @Nullable CountryEccInfo getCountryEccInfo(@NonNull Context context, @Nullable String iso)
-            throws IOException;
-}