16465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri/**
26465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri * Copyright (c) 2015, The Android Open Source Project
36465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri *
46465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri * Licensed under the Apache License, Version 2.0 (the "License");
56465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri * you may not use this file except in compliance with the License.
66465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri * You may obtain a copy of the License at
76465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri *
86465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri *     http://www.apache.org/licenses/LICENSE-2.0
96465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri *
106465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri * Unless required by applicable law or agreed to in writing, software
116465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri * distributed under the License is distributed on an "AS IS" BASIS,
126465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri * See the License for the specific language governing permissions and
146465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri * limitations under the License.
156465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri */
166465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
176465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseripackage com.android.phone;
186465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
196465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseriimport static android.Manifest.permission.READ_PHONE_STATE;
2040b3fa5a53992ebf84484c37ba5afde99081f11aAmit Mahajanimport static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
216465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
2211f8957f3a603e5109ae15c5386ddbb7d76972adJonathan Basseriimport android.annotation.NonNull;
23bb03c632465951b058d16645bf54638a7c771a64Sudheer Shankaimport android.app.ActivityManager;
246465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseriimport android.content.BroadcastReceiver;
256465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseriimport android.content.ComponentName;
266465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseriimport android.content.Context;
276465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseriimport android.content.Intent;
286465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseriimport android.content.IntentFilter;
296465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseriimport android.content.ServiceConnection;
307697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseriimport android.content.SharedPreferences;
316b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseriimport android.content.pm.PackageInfo;
32c31f1f32963534763aaf82ae2544f3a94f13edcaJonathan Basseriimport android.content.pm.PackageManager;
3343d723a19bed8492da059b394869065cc713c484Junda Liuimport android.os.Binder;
347697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseriimport android.os.Build;
356465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseriimport android.os.Handler;
366465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseriimport android.os.IBinder;
376465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseriimport android.os.Message;
38c31f1f32963534763aaf82ae2544f3a94f13edcaJonathan Basseriimport android.os.PersistableBundle;
396465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseriimport android.os.ServiceManager;
406465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseriimport android.os.UserHandle;
417697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseriimport android.preference.PreferenceManager;
426465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseriimport android.service.carrier.CarrierIdentifier;
4336d7aab00cd08f9efded5148c8f8a42ed7402641Zach Johnsonimport android.service.carrier.CarrierService;
4436d7aab00cd08f9efded5148c8f8a42ed7402641Zach Johnsonimport android.service.carrier.ICarrierService;
456465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseriimport android.telephony.CarrierConfigManager;
466465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseriimport android.telephony.SubscriptionManager;
476465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseriimport android.telephony.TelephonyManager;
486465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseriimport android.util.Log;
496465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
506465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseriimport com.android.internal.telephony.ICarrierConfigLoader;
516465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseriimport com.android.internal.telephony.IccCardConstants;
526465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseriimport com.android.internal.telephony.Phone;
536465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseriimport com.android.internal.telephony.PhoneFactory;
546b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseriimport com.android.internal.util.FastXmlSerializer;
5526a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoqimport com.android.internal.util.IndentingPrintWriter;
566b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri
576b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseriimport org.xmlpull.v1.XmlPullParser;
586b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseriimport org.xmlpull.v1.XmlPullParserException;
596b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseriimport org.xmlpull.v1.XmlPullParserFactory;
606465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
616b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseriimport java.io.File;
6243d723a19bed8492da059b394869065cc713c484Junda Liuimport java.io.FileDescriptor;
636b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseriimport java.io.FileInputStream;
646b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseriimport java.io.FileNotFoundException;
656b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseriimport java.io.FileOutputStream;
661f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseriimport java.io.FilenameFilter;
676b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseriimport java.io.IOException;
6843d723a19bed8492da059b394869065cc713c484Junda Liuimport java.io.PrintWriter;
6926a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoqimport java.util.ArrayList;
7026a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoqimport java.util.Arrays;
7126a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoqimport java.util.Collections;
726465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseriimport java.util.List;
736465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
746465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri/**
756465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri * CarrierConfigLoader binds to privileged carrier apps to fetch carrier config overlays.
766465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri */
776465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
786465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseripublic class CarrierConfigLoader extends ICarrierConfigLoader.Stub {
796b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri    private static final String LOG_TAG = "CarrierConfigLoader";
8033ad2bca5efc6750e25f793afeaddedcbc577c40Meng Wang
8133ad2bca5efc6750e25f793afeaddedcbc577c40Meng Wang    // Package name for platform carrier config app, bundled with system image.
8233ad2bca5efc6750e25f793afeaddedcbc577c40Meng Wang    private final String mPlatformCarrierConfigPackage;
836465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
846465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    /** The singleton instance. */
856465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    private static CarrierConfigLoader sInstance;
866465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    // The context for phone app, passed from PhoneGlobals.
876465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    private Context mContext;
886465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    // Carrier configs from default app, indexed by phoneID.
89c31f1f32963534763aaf82ae2544f3a94f13edcaJonathan Basseri    private PersistableBundle[] mConfigFromDefaultApp;
906465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    // Carrier configs from privileged carrier config app, indexed by phoneID.
91c31f1f32963534763aaf82ae2544f3a94f13edcaJonathan Basseri    private PersistableBundle[] mConfigFromCarrierApp;
926465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    // Service connection for binding to config app.
9336d7aab00cd08f9efded5148c8f8a42ed7402641Zach Johnson    private CarrierServiceConnection[] mServiceConnection;
9403aad762e94928b14c7e91e04147856448d77d8dJunda Liu    // Whether we have sent config change bcast for each phone id.
9503aad762e94928b14c7e91e04147856448d77d8dJunda Liu    private boolean[] mHasSentConfigChange;
966465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
973d670504427b08d6efd96d05401b6a5d5e44742dNanxi Chen    // Broadcast receiver for Boot intents, register intent filter in construtor.
983d670504427b08d6efd96d05401b6a5d5e44742dNanxi Chen    private final BroadcastReceiver mBootReceiver = new ConfigLoaderBroadcastReceiver();
996465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    // Broadcast receiver for SIM and pkg intents, register intent filter in constructor.
1003d670504427b08d6efd96d05401b6a5d5e44742dNanxi Chen    private final BroadcastReceiver mPackageReceiver = new ConfigLoaderBroadcastReceiver();
1016465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
1026465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    // Message codes; see mHandler below.
1036465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    // Request from SubscriptionInfoUpdater when SIM becomes absent or error.
1046465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    private static final int EVENT_CLEAR_CONFIG = 0;
1056465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    // Has connected to default app.
1066465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    private static final int EVENT_CONNECTED_TO_DEFAULT = 3;
1076465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    // Has connected to carrier app.
1086465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    private static final int EVENT_CONNECTED_TO_CARRIER = 4;
109154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri    // Config has been loaded from default app.
110154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri    private static final int EVENT_LOADED_FROM_DEFAULT = 5;
111154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri    // Config has been loaded from carrier app.
112154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri    private static final int EVENT_LOADED_FROM_CARRIER = 6;
1131f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    // Attempt to fetch from default app or read from XML.
114154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri    private static final int EVENT_FETCH_DEFAULT = 7;
1151f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    // Attempt to fetch from carrier app or read from XML.
116154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri    private static final int EVENT_FETCH_CARRIER = 8;
1171f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    // A package has been installed, uninstalled, or updated.
1181f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    private static final int EVENT_PACKAGE_CHANGED = 9;
119930701e59f6b2e29961916982fdd7bc96f36f13eJonathan Basseri    // Bind timed out for the default app.
120930701e59f6b2e29961916982fdd7bc96f36f13eJonathan Basseri    private static final int EVENT_BIND_DEFAULT_TIMEOUT = 10;
121930701e59f6b2e29961916982fdd7bc96f36f13eJonathan Basseri    // Bind timed out for a carrier app.
122930701e59f6b2e29961916982fdd7bc96f36f13eJonathan Basseri    private static final int EVENT_BIND_CARRIER_TIMEOUT = 11;
1237697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri    // Check if the system fingerprint has changed.
1247697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri    private static final int EVENT_CHECK_SYSTEM_UPDATE = 12;
1253d670504427b08d6efd96d05401b6a5d5e44742dNanxi Chen    // Rerun carrier config binding after system is unlocked.
1263d670504427b08d6efd96d05401b6a5d5e44742dNanxi Chen    private static final int EVENT_SYSTEM_UNLOCKED = 13;
127930701e59f6b2e29961916982fdd7bc96f36f13eJonathan Basseri
1286cb4500759f1fc56eb5b7248dbdfb2decc2129b3Junda Liu    private static final int BIND_TIMEOUT_MILLIS = 30000;
1296465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
1306b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri    // Tags used for saving and restoring XML documents.
1316b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri    private static final String TAG_DOCUMENT = "carrier_config";
1326b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri    private static final String TAG_VERSION = "package_version";
1336b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri    private static final String TAG_BUNDLE = "bundle_data";
1346465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
1357697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri    // SharedPreferences key for last known build fingerprint.
1367697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri    private static final String KEY_FINGERPRINT = "build_fingerprint";
1377697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri
1386465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    // Handler to process various events.
1396b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri    //
1401f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    // For each phoneId, the event sequence should be:
141154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri    //     fetch default, connected to default, loaded from default,
142154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri    //     fetch carrier, connected to carrier, loaded from carrier.
1436b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri    //
1441f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    // If there is a saved config file for either the default app or the carrier app, we skip
1451f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    // binding to the app and go straight from fetch to loaded.
1461f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    //
1471f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    // At any time, at most one connection is active. If events are not in this order, previous
1481f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    // connection will be unbound, so only latest event takes effect.
1491f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    //
1501f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    // We broadcast ACTION_CARRIER_CONFIG_CHANGED after:
1511f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    // 1. loading from carrier app (even if read from a file)
1521f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    // 2. loading from default app if there is no carrier app (even if read from a file)
1531f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    // 3. clearing config (e.g. due to sim removal)
1541f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    // 4. encountering bind or IPC error
155154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri    private Handler mHandler = new Handler() {
156154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri            @Override
1576465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        public void handleMessage(Message msg) {
158154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri            int phoneId = msg.arg1;
1596465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            log("mHandler: " + msg.what + " phoneId: " + phoneId);
160154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri            String iccid;
161154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri            CarrierIdentifier carrierId;
162154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri            String carrierPackageName;
163154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri            CarrierServiceConnection conn;
164154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri            PersistableBundle config;
1656465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            switch (msg.what) {
1666465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                case EVENT_CLEAR_CONFIG:
1677dd5d0c9d57e0b6253c5f081a92c1b16efcc109aSooraj Sasindran
1687dd5d0c9d57e0b6253c5f081a92c1b16efcc109aSooraj Sasindran                    /* Ignore clear configuration request if device is being shutdown. */
1697dd5d0c9d57e0b6253c5f081a92c1b16efcc109aSooraj Sasindran                    Phone phone = PhoneFactory.getPhone(phoneId);
1707dd5d0c9d57e0b6253c5f081a92c1b16efcc109aSooraj Sasindran                    if (phone != null) {
1717dd5d0c9d57e0b6253c5f081a92c1b16efcc109aSooraj Sasindran                        if (phone.isShuttingDown()) {
1727dd5d0c9d57e0b6253c5f081a92c1b16efcc109aSooraj Sasindran                            break;
1737dd5d0c9d57e0b6253c5f081a92c1b16efcc109aSooraj Sasindran                        }
1747dd5d0c9d57e0b6253c5f081a92c1b16efcc109aSooraj Sasindran                    }
1757dd5d0c9d57e0b6253c5f081a92c1b16efcc109aSooraj Sasindran
176154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                    if (mConfigFromDefaultApp[phoneId] == null &&
177154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        mConfigFromCarrierApp[phoneId] == null)
178154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        break;
1797dd5d0c9d57e0b6253c5f081a92c1b16efcc109aSooraj Sasindran
1806465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                    mConfigFromDefaultApp[phoneId] = null;
1816465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                    mConfigFromCarrierApp[phoneId] = null;
1826465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                    mServiceConnection[phoneId] = null;
1836465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                    broadcastConfigChangedIntent(phoneId);
1846465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                    break;
1851f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri
1863d670504427b08d6efd96d05401b6a5d5e44742dNanxi Chen                case EVENT_SYSTEM_UNLOCKED:
1873d670504427b08d6efd96d05401b6a5d5e44742dNanxi Chen                    for (int i = 0; i < TelephonyManager.from(mContext).getPhoneCount(); ++i) {
188154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        // When user unlock device, we should only try to send broadcast again if
189154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        // we have sent it before unlock. This will avoid we try to load carrier
190154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        // config when SIM is still loading when unlock happens.
19103aad762e94928b14c7e91e04147856448d77d8dJunda Liu                        if (mHasSentConfigChange[i]) {
19203aad762e94928b14c7e91e04147856448d77d8dJunda Liu                            updateConfigForPhoneId(i);
19303aad762e94928b14c7e91e04147856448d77d8dJunda Liu                        }
1943d670504427b08d6efd96d05401b6a5d5e44742dNanxi Chen                    }
1953d670504427b08d6efd96d05401b6a5d5e44742dNanxi Chen                    break;
1963d670504427b08d6efd96d05401b6a5d5e44742dNanxi Chen
1971f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                case EVENT_PACKAGE_CHANGED:
198154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                    carrierPackageName = (String) msg.obj;
199154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                    // Only update if there are cached config removed to avoid updating config
200154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                    // for unrelated packages.
2017697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri                    if (clearCachedConfigForPackage(carrierPackageName)) {
2028a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu                        int numPhones = TelephonyManager.from(mContext).getPhoneCount();
2038a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu                        for (int i = 0; i < numPhones; ++i) {
2048a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu                            updateConfigForPhoneId(i);
2058a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu                        }
2061f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                    }
2071f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                    break;
2081f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri
209154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                case EVENT_FETCH_DEFAULT:
210154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                    iccid = getIccIdForPhoneId(phoneId);
211154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                    config = restoreConfigFromXml(mPlatformCarrierConfigPackage, iccid);
2121f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                    if (config != null) {
213154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        log("Loaded config from XML. package=" + mPlatformCarrierConfigPackage
214154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                                + " phoneId=" + phoneId);
2151f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                        mConfigFromDefaultApp[phoneId] = config;
216154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        Message newMsg = obtainMessage(EVENT_LOADED_FROM_DEFAULT, phoneId, -1);
2171f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                        newMsg.getData().putBoolean("loaded_from_xml", true);
2181f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                        mHandler.sendMessage(newMsg);
2191f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                    } else {
220154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        if (bindToConfigPackage(mPlatformCarrierConfigPackage,
221154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                                phoneId, EVENT_CONNECTED_TO_DEFAULT)) {
222154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                            sendMessageDelayed(obtainMessage(EVENT_BIND_DEFAULT_TIMEOUT, phoneId, -1),
223930701e59f6b2e29961916982fdd7bc96f36f13eJonathan Basseri                                    BIND_TIMEOUT_MILLIS);
224930701e59f6b2e29961916982fdd7bc96f36f13eJonathan Basseri                        } else {
225154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                            // Send bcast if bind fails
2261f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                            broadcastConfigChangedIntent(phoneId);
2271f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                        }
2286465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                    }
2296465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                    break;
2306465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
2316465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                case EVENT_CONNECTED_TO_DEFAULT:
232930701e59f6b2e29961916982fdd7bc96f36f13eJonathan Basseri                    removeMessages(EVENT_BIND_DEFAULT_TIMEOUT);
233154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                    carrierId = getCarrierIdForPhoneId(phoneId);
234154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                    conn = (CarrierServiceConnection) msg.obj;
2356465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                    // If new service connection has been created, unbind.
2366465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                    if (mServiceConnection[phoneId] != conn || conn.service == null) {
2376465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                        mContext.unbindService(conn);
2386465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                        break;
2396465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                    }
2406465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                    try {
241154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        ICarrierService carrierService = ICarrierService.Stub
242154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                                .asInterface(conn.service);
243154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        config = carrierService.getCarrierConfig(carrierId);
244154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        iccid = getIccIdForPhoneId(phoneId);
245154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        saveConfigToXml(mPlatformCarrierConfigPackage, iccid, config);
246154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        mConfigFromDefaultApp[phoneId] = config;
247154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        sendMessage(obtainMessage(EVENT_LOADED_FROM_DEFAULT, phoneId, -1));
248154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                    } catch (Exception ex) {
249154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        // The bound app could throw exceptions that binder will pass to us.
250154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        loge("Failed to get carrier config: " + ex.toString());
251154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                    } finally {
252154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        mContext.unbindService(mServiceConnection[phoneId]);
2536465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                    }
2546465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                    break;
2556465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
256930701e59f6b2e29961916982fdd7bc96f36f13eJonathan Basseri                case EVENT_BIND_DEFAULT_TIMEOUT:
257930701e59f6b2e29961916982fdd7bc96f36f13eJonathan Basseri                    mContext.unbindService(mServiceConnection[phoneId]);
258930701e59f6b2e29961916982fdd7bc96f36f13eJonathan Basseri                    broadcastConfigChangedIntent(phoneId);
259930701e59f6b2e29961916982fdd7bc96f36f13eJonathan Basseri                    break;
260930701e59f6b2e29961916982fdd7bc96f36f13eJonathan Basseri
261154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                case EVENT_LOADED_FROM_DEFAULT:
2621f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                    // If we attempted to bind to the app, but the service connection is null, then
2631f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                    // config was cleared while we were waiting and we should not continue.
2641f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                    if (!msg.getData().getBoolean("loaded_from_xml", false)
2651f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                            && mServiceConnection[phoneId] == null) {
2666465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                        break;
2676465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                    }
268154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                    carrierPackageName = getCarrierPackageForPhoneId(phoneId);
2691f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                    if (carrierPackageName != null) {
2701f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                        log("Found carrier config app: " + carrierPackageName);
271154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        sendMessage(obtainMessage(EVENT_FETCH_CARRIER, phoneId));
272b919e93c9afe91914ed0d82dc63b57ecfa28eab2Jonathan Basseri                    } else {
273b919e93c9afe91914ed0d82dc63b57ecfa28eab2Jonathan Basseri                        broadcastConfigChangedIntent(phoneId);
2744ae2e7c7e0b6480ec428b9efedc77d8f0fb07430Jonathan Basseri                    }
2754ae2e7c7e0b6480ec428b9efedc77d8f0fb07430Jonathan Basseri                    break;
2764ae2e7c7e0b6480ec428b9efedc77d8f0fb07430Jonathan Basseri
277154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                case EVENT_FETCH_CARRIER:
278154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                    carrierPackageName = getCarrierPackageForPhoneId(phoneId);
279154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                    iccid = getIccIdForPhoneId(phoneId);
280154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                    config = restoreConfigFromXml(carrierPackageName, iccid);
2811f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                    if (config != null) {
282154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        log("Loaded config from XML. package=" + carrierPackageName + " phoneId="
283154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                                + phoneId);
2841f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                        mConfigFromCarrierApp[phoneId] = config;
285154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        Message newMsg = obtainMessage(EVENT_LOADED_FROM_CARRIER, phoneId, -1);
2861f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                        newMsg.getData().putBoolean("loaded_from_xml", true);
2871f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                        sendMessage(newMsg);
2881f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                    } else {
28940473a538d0b51b5d4e83421e06c99cbe05c2468Jonathan Basseri                        if (carrierPackageName != null
290154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                            && bindToConfigPackage(carrierPackageName, phoneId,
291154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                                    EVENT_CONNECTED_TO_CARRIER)) {
292154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                            sendMessageDelayed(obtainMessage(EVENT_BIND_CARRIER_TIMEOUT, phoneId, -1),
293930701e59f6b2e29961916982fdd7bc96f36f13eJonathan Basseri                                    BIND_TIMEOUT_MILLIS);
294930701e59f6b2e29961916982fdd7bc96f36f13eJonathan Basseri                        } else {
295154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                            // Send bcast if bind fails
2961f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                            broadcastConfigChangedIntent(phoneId);
2971f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                        }
2981f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                    }
2991f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                    break;
3001f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri
3016465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                case EVENT_CONNECTED_TO_CARRIER:
302930701e59f6b2e29961916982fdd7bc96f36f13eJonathan Basseri                    removeMessages(EVENT_BIND_CARRIER_TIMEOUT);
303154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                    carrierId = getCarrierIdForPhoneId(phoneId);
304154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                    conn = (CarrierServiceConnection) msg.obj;
3056465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                    // If new service connection has been created, unbind.
306154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                    if (mServiceConnection[phoneId] != conn ||
307154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                            conn.service == null) {
3086465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                        mContext.unbindService(conn);
3096465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                        break;
3106465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                    }
3116465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                    try {
312154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        ICarrierService carrierService = ICarrierService.Stub
313154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                                .asInterface(conn.service);
314154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        config = carrierService.getCarrierConfig(carrierId);
315154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        carrierPackageName = getCarrierPackageForPhoneId(phoneId);
316154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        iccid = getIccIdForPhoneId(phoneId);
317154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        saveConfigToXml(carrierPackageName, iccid, config);
318154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        mConfigFromCarrierApp[phoneId] = config;
319154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        sendMessage(obtainMessage(EVENT_LOADED_FROM_CARRIER, phoneId, -1));
320154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                    } catch (Exception ex) {
321154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        // The bound app could throw exceptions that binder will pass to us.
322154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        loge("Failed to get carrier config: " + ex.toString());
323154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                    } finally {
324154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        mContext.unbindService(mServiceConnection[phoneId]);
3256465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                    }
3266465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                    break;
3276465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
328930701e59f6b2e29961916982fdd7bc96f36f13eJonathan Basseri                case EVENT_BIND_CARRIER_TIMEOUT:
329930701e59f6b2e29961916982fdd7bc96f36f13eJonathan Basseri                    mContext.unbindService(mServiceConnection[phoneId]);
330930701e59f6b2e29961916982fdd7bc96f36f13eJonathan Basseri                    broadcastConfigChangedIntent(phoneId);
331930701e59f6b2e29961916982fdd7bc96f36f13eJonathan Basseri                    break;
332930701e59f6b2e29961916982fdd7bc96f36f13eJonathan Basseri
333154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                case EVENT_LOADED_FROM_CARRIER:
3341f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                    // If we attempted to bind to the app, but the service connection is null, then
3351f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                    // config was cleared while we were waiting and we should not continue.
3361f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                    if (!msg.getData().getBoolean("loaded_from_xml", false)
3371f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                            && mServiceConnection[phoneId] == null) {
3386465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                        break;
3396465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                    }
3406465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                    broadcastConfigChangedIntent(phoneId);
3416465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                    break;
3427697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri
3437697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri                case EVENT_CHECK_SYSTEM_UPDATE:
3447697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri                    SharedPreferences sharedPrefs =
3457697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri                            PreferenceManager.getDefaultSharedPreferences(mContext);
3467697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri                    final String lastFingerprint = sharedPrefs.getString(KEY_FINGERPRINT, null);
3477697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri                    if (!Build.FINGERPRINT.equals(lastFingerprint)) {
348154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        log("Build fingerprint changed. old: "
349154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                                + lastFingerprint + " new: " + Build.FINGERPRINT);
3507697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri                        clearCachedConfigForPackage(null);
351154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri                        sharedPrefs.edit().putString(KEY_FINGERPRINT, Build.FINGERPRINT).apply();
3527697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri                    }
3537697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri                    break;
3546465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            }
3556465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        }
356154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri    };
3576465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
3586465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    /**
3596465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri     * Constructs a CarrierConfigLoader, registers it as a service, and registers a broadcast
3606465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri     * receiver for relevant events.
3616465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri     */
3626465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    private CarrierConfigLoader(Context context) {
3636465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        mContext = context;
36433ad2bca5efc6750e25f793afeaddedcbc577c40Meng Wang        mPlatformCarrierConfigPackage =
36533ad2bca5efc6750e25f793afeaddedcbc577c40Meng Wang                mContext.getString(R.string.platform_carrier_config_package);
3666465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
3673d670504427b08d6efd96d05401b6a5d5e44742dNanxi Chen        IntentFilter bootFilter = new IntentFilter();
3683d670504427b08d6efd96d05401b6a5d5e44742dNanxi Chen        bootFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
3693d670504427b08d6efd96d05401b6a5d5e44742dNanxi Chen        context.registerReceiver(mBootReceiver, bootFilter);
3703d670504427b08d6efd96d05401b6a5d5e44742dNanxi Chen
3718a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu        // Register for package updates. Update app or uninstall app update will have all 3 intents,
3728a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu        // in the order or removed, added, replaced, all with extra_replace set to true.
3738a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu        IntentFilter pkgFilter = new IntentFilter();
3748a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu        pkgFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
3758a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu        pkgFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
3768a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu        pkgFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
3778a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu        pkgFilter.addDataScheme("package");
3783d670504427b08d6efd96d05401b6a5d5e44742dNanxi Chen        context.registerReceiverAsUser(mPackageReceiver, UserHandle.ALL, pkgFilter, null, null);
3796465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
3806465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        int numPhones = TelephonyManager.from(context).getPhoneCount();
381c31f1f32963534763aaf82ae2544f3a94f13edcaJonathan Basseri        mConfigFromDefaultApp = new PersistableBundle[numPhones];
382c31f1f32963534763aaf82ae2544f3a94f13edcaJonathan Basseri        mConfigFromCarrierApp = new PersistableBundle[numPhones];
38336d7aab00cd08f9efded5148c8f8a42ed7402641Zach Johnson        mServiceConnection = new CarrierServiceConnection[numPhones];
38403aad762e94928b14c7e91e04147856448d77d8dJunda Liu        mHasSentConfigChange = new boolean[numPhones];
3856465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        // Make this service available through ServiceManager.
3866465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        ServiceManager.addService(Context.CARRIER_CONFIG_SERVICE, this);
3876465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        log("CarrierConfigLoader has started");
3887697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri        mHandler.sendEmptyMessage(EVENT_CHECK_SYSTEM_UPDATE);
3896465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    }
3906465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
3916465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    /**
3926465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri     * Initialize the singleton CarrierConfigLoader instance.
3936465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri     *
3946465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri     * This is only done once, at startup, from {@link com.android.phone.PhoneApp#onCreate}.
3956465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri     */
3966465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    /* package */
3976465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    static CarrierConfigLoader init(Context context) {
3986465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        synchronized (CarrierConfigLoader.class) {
3996465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            if (sInstance == null) {
4006465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                sInstance = new CarrierConfigLoader(context);
4016465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            } else {
4026b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri                Log.wtf(LOG_TAG, "init() called multiple times!  sInstance = " + sInstance);
4036465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            }
4046465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            return sInstance;
4056465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        }
4066465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    }
4076465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
4086465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    private void broadcastConfigChangedIntent(int phoneId) {
4096465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
41038f55eb5bf3404a773089fd117a8f4b5255096acChristopher Tate        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
41138f55eb5bf3404a773089fd117a8f4b5255096acChristopher Tate                Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
4126465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        SubscriptionManager.putPhoneIdAndSubIdExtra(intent, phoneId);
413bb03c632465951b058d16645bf54638a7c771a64Sudheer Shanka        ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL);
41403aad762e94928b14c7e91e04147856448d77d8dJunda Liu        mHasSentConfigChange[phoneId] = true;
4156465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    }
4166465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
4176465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    /** Binds to the default or carrier config app. */
4186465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    private boolean bindToConfigPackage(String pkgName, int phoneId, int eventId) {
4196465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        log("Binding to " + pkgName + " for phone " + phoneId);
420fca8a8daba0c2333fbe4ab0c4acca463a0f754a0Zach Johnson        Intent carrierService = new Intent(CarrierService.CARRIER_SERVICE_INTERFACE);
42136d7aab00cd08f9efded5148c8f8a42ed7402641Zach Johnson        carrierService.setPackage(pkgName);
42236d7aab00cd08f9efded5148c8f8a42ed7402641Zach Johnson        mServiceConnection[phoneId] = new CarrierServiceConnection(phoneId, eventId);
4236465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        try {
42436d7aab00cd08f9efded5148c8f8a42ed7402641Zach Johnson            return mContext.bindService(carrierService, mServiceConnection[phoneId],
4256465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                    Context.BIND_AUTO_CREATE);
4266465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        } catch (SecurityException ex) {
4276465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            return false;
4286465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        }
4296465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    }
4306465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
4316465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    private CarrierIdentifier getCarrierIdForPhoneId(int phoneId) {
4326465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        String mcc = "";
4336465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        String mnc = "";
4346465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        String imsi = "";
4356465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        String gid1 = "";
4366465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        String gid2 = "";
4376465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        String spn = TelephonyManager.from(mContext).getSimOperatorNameForPhone(phoneId);
4386465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        String simOperator = TelephonyManager.from(mContext).getSimOperatorNumericForPhone(phoneId);
4391fa437cd0b34550ab4befc4f5198761e61b3b0bdJonathan Basseri        // A valid simOperator should be 5 or 6 digits, depending on the length of the MNC.
4401fa437cd0b34550ab4befc4f5198761e61b3b0bdJonathan Basseri        if (simOperator != null && simOperator.length() >= 3) {
4416465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            mcc = simOperator.substring(0, 3);
4426465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            mnc = simOperator.substring(3);
4436465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        }
4446465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        Phone phone = PhoneFactory.getPhone(phoneId);
4456465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        if (phone != null) {
4466465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            imsi = phone.getSubscriberId();
4476465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            gid1 = phone.getGroupIdLevel1();
44873183530f04aa474758bfacbce0ed9d637d49e71Junda Liu            gid2 = phone.getGroupIdLevel2();
4496465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        }
4506465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
4516465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        return new CarrierIdentifier(mcc, mnc, spn, imsi, gid1, gid2);
4526465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    }
4536465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
4541f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    /** Returns the package name of a priveleged carrier app, or null if there is none. */
4551f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    private String getCarrierPackageForPhoneId(int phoneId) {
4561f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        List<String> carrierPackageNames = TelephonyManager.from(mContext)
4571f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                .getCarrierPackageNamesForIntentAndPhone(
458fca8a8daba0c2333fbe4ab0c4acca463a0f754a0Zach Johnson                        new Intent(CarrierService.CARRIER_SERVICE_INTERFACE), phoneId);
4591f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        if (carrierPackageNames != null && carrierPackageNames.size() > 0) {
4601f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri            return carrierPackageNames.get(0);
4611f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        } else {
4621f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri            return null;
4631f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        }
4641f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    }
4651f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri
4661f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    private String getIccIdForPhoneId(int phoneId) {
4671f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        if (!SubscriptionManager.isValidPhoneId(phoneId)) {
4681f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri            return null;
4691f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        }
4701f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        Phone phone = PhoneFactory.getPhone(phoneId);
4711f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        if (phone == null) {
4721f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri            return null;
4731f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        }
4741f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        return phone.getIccSerialNumber();
4751f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    }
4761f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri
4776b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri    /**
4786b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri     * Writes a bundle to an XML file.
4796b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri     *
4806b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri     * The bundle will be written to a file named after the package name and ICCID, so that it can
4816b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri     * be restored later with {@link @restoreConfigFromXml}. The XML output will include the bundle
4821f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri     * and the current version of the specified package.
4831f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri     *
4841f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri     * In case of errors or invalid input, no file will be written.
4856b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri     *
4866b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri     * @param packageName the name of the package from which we fetched this bundle.
4876b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri     * @param iccid the ICCID of the subscription for which this bundle was fetched.
4881f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri     * @param config the bundle to be written. Null will be treated as an empty bundle.
4896b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri     */
4906b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri    private void saveConfigToXml(String packageName, String iccid, PersistableBundle config) {
4911f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        if (packageName == null || iccid == null) {
4921f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri            loge("Cannot save config with null packageName or iccid.");
4931f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri            return;
4941f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        }
4950259650d985a6279de7a0a8ce4ec823011dd7a4bJunda Liu        // b/32668103 Only save to file if config isn't empty.
4960259650d985a6279de7a0a8ce4ec823011dd7a4bJunda Liu        // In case of failure, not caching an empty bundle will
4970259650d985a6279de7a0a8ce4ec823011dd7a4bJunda Liu        // try loading config again on next power on or sim loaded.
4980259650d985a6279de7a0a8ce4ec823011dd7a4bJunda Liu        // Downside is for genuinely empty bundle, will bind and load
4990259650d985a6279de7a0a8ce4ec823011dd7a4bJunda Liu        // on every power on.
5000259650d985a6279de7a0a8ce4ec823011dd7a4bJunda Liu        if (config == null || config.isEmpty()) {
5010259650d985a6279de7a0a8ce4ec823011dd7a4bJunda Liu            return;
5021f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        }
5031f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri
5046b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        final String version = getPackageVersion(packageName);
5056b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        if (version == null) {
5066b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            loge("Failed to get package version for: " + packageName);
5076b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            return;
5086b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        }
5096b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri
5106b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        FileOutputStream outFile = null;
5116b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        try {
5126b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            outFile = new FileOutputStream(
5136b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri                    new File(mContext.getFilesDir(), getFilenameForConfig(packageName, iccid)));
5146b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            FastXmlSerializer out = new FastXmlSerializer();
5156b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            out.setOutput(outFile, "utf-8");
5166b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            out.startDocument("utf-8", true);
5176b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            out.startTag(null, TAG_DOCUMENT);
5186b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            out.startTag(null, TAG_VERSION);
5196b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            out.text(version);
5206b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            out.endTag(null, TAG_VERSION);
5216b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            out.startTag(null, TAG_BUNDLE);
5226b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            config.saveToXml(out);
5236b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            out.endTag(null, TAG_BUNDLE);
5246b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            out.endTag(null, TAG_DOCUMENT);
5256b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            out.endDocument();
5266b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            out.flush();
5276b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            outFile.close();
5286b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        }
5296b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        catch (IOException e) {
5306b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            loge(e.toString());
5316b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        }
5326b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        catch (XmlPullParserException e) {
5336b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            loge(e.toString());
5346b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        }
5356b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri    }
5366b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri
5376b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri    /**
5386b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri     * Reads a bundle from an XML file.
5396b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri     *
5406b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri     * This restores a bundle that was written with {@link #saveConfigToXml}. This returns the saved
5411f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri     * config bundle for the given package and ICCID.
5421f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri     *
5431f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri     * In case of errors, or if the saved config is from a different package version than the
5441f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri     * current version, then null will be returned.
5456b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri     *
5466b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri     * @param packageName the name of the package from which we fetched this bundle.
5476b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri     * @param iccid the ICCID of the subscription for which this bundle was fetched.
5486b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri     * @return the bundle from the XML file. Returns null if there is no saved config, the saved
5496b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri     *         version does not match, or reading config fails.
5506b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri     */
5516b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri    private PersistableBundle restoreConfigFromXml(String packageName, String iccid) {
5526b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        final String version = getPackageVersion(packageName);
5536b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        if (version == null) {
5546b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            loge("Failed to get package version for: " + packageName);
5556b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            return null;
5566b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        }
5571f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        if (packageName == null || iccid == null) {
5581f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri            loge("Cannot restore config with null packageName or iccid.");
5591f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri            return null;
5601f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        }
5616b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri
5626b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        PersistableBundle restoredBundle = null;
5636b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        FileInputStream inFile = null;
5646b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        try {
5656b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            inFile = new FileInputStream(
5666b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri                    new File(mContext.getFilesDir(), getFilenameForConfig(packageName, iccid)));
5676b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
5686b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            parser.setInput(inFile, "utf-8");
5696b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri
5706b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            int event;
5716b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            while (((event = parser.next()) != XmlPullParser.END_DOCUMENT)) {
5726b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri
5736b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri                if (event == XmlPullParser.START_TAG && TAG_VERSION.equals(parser.getName())) {
5746b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri                    String savedVersion = parser.nextText();
5756b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri                    if (!version.equals(savedVersion)) {
5766b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri                        log("Saved version mismatch: " + version + " vs " + savedVersion);
5776b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri                        break;
5786b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri                    }
5796b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri                }
5806b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri
5816b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri                if (event == XmlPullParser.START_TAG && TAG_BUNDLE.equals(parser.getName())) {
5826b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri                    restoredBundle = PersistableBundle.restoreFromXml(parser);
5836b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri                }
5846b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            }
5856b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            inFile.close();
5866b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        }
5876b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        catch (FileNotFoundException e) {
5886b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            loge(e.toString());
5896b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        }
5906b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        catch (XmlPullParserException e) {
5916b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            loge(e.toString());
5926b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        }
5936b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        catch (IOException e) {
5946b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            loge(e.toString());
5956b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        }
5966b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri
5976b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        return restoredBundle;
5986b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri    }
5996b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri
6008a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu    /**
6017697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri     * Clears cached carrier config.
6027697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri     * This deletes all saved XML files associated with the given package name. If packageName is
6037697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri     * null, then it deletes all saved XML files.
6047697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri     *
6057697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri     * @param packageName the name of a carrier package, or null if all cached config should be
6067697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri     *                    cleared.
6077697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri     * @return true iff one or more files were deleted.
6088a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu     */
6097697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri    private boolean clearCachedConfigForPackage(final String packageName) {
6101f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        File dir = mContext.getFilesDir();
6111f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        File[] packageFiles = dir.listFiles(new FilenameFilter() {
6121f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri            public boolean accept(File dir, String filename) {
6137697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri                if (packageName != null) {
6147697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri                    return filename.startsWith("carrierconfig-" + packageName + "-");
6157697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri                } else {
6167697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri                    return filename.startsWith("carrierconfig-");
6177697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri                }
6181f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri            }
6191f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        });
6208a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu        if (packageFiles == null || packageFiles.length < 1) return false;
6211f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        for (File f : packageFiles) {
6221f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri            log("deleting " + f.getName());
6231f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri            f.delete();
6241f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        }
6258a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu        return true;
6261f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    }
6271f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri
6286b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri    /** Builds a canonical file name for a config file. */
6291f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    private String getFilenameForConfig(@NonNull String packageName, @NonNull String iccid) {
6306b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        return "carrierconfig-" + packageName + "-" + iccid + ".xml";
6316b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri    }
6326b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri
6331f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    /** Return the current version code of a package, or null if the name is not found. */
6346b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri    private String getPackageVersion(String packageName) {
6356b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        try {
6366b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            PackageInfo info = mContext.getPackageManager().getPackageInfo(packageName, 0);
6371f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri            return Integer.toString(info.versionCode);
6386b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        } catch (PackageManager.NameNotFoundException e) {
6396b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            return null;
6406b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        }
6416b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri    }
6426b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri
643154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri    /** Read up to date config.
6441f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri     *
6451f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri     * This reads config bundles for the given phoneId. That means getting the latest bundle from
6461f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri     * the default app and a privileged carrier app, if present. This will not bind to an app if we
6471f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri     * have a saved config file to use instead.
6481f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri     */
6491f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    private void updateConfigForPhoneId(int phoneId) {
6508a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu        // Clear in-memory cache for carrier app config, so when carrier app gets uninstalled, no
6518a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu        // stale config is left.
6528a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu        if (mConfigFromCarrierApp[phoneId] != null &&
6538a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu                getCarrierPackageForPhoneId(phoneId) == null) {
6548a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu            mConfigFromCarrierApp[phoneId] = null;
6558a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu        }
656154e05d16fcd498667afd6fb451e7ae75b9a7166Jonathan Basseri        mHandler.sendMessage(mHandler.obtainMessage(EVENT_FETCH_DEFAULT, phoneId, -1));
6571f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    }
6581f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri
6591f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    @Override public
6601f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    @NonNull
6611f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri    PersistableBundle getConfigForSubId(int subId) {
66240b3fa5a53992ebf84484c37ba5afde99081f11aAmit Mahajan        try {
66340b3fa5a53992ebf84484c37ba5afde99081f11aAmit Mahajan            mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, null);
66440b3fa5a53992ebf84484c37ba5afde99081f11aAmit Mahajan            // SKIP checking run-time READ_PHONE_STATE since using PRIVILEGED
66540b3fa5a53992ebf84484c37ba5afde99081f11aAmit Mahajan        } catch (SecurityException e) {
66640b3fa5a53992ebf84484c37ba5afde99081f11aAmit Mahajan            mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, null);
66740b3fa5a53992ebf84484c37ba5afde99081f11aAmit Mahajan        }
6686465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        int phoneId = SubscriptionManager.getPhoneId(subId);
669c31f1f32963534763aaf82ae2544f3a94f13edcaJonathan Basseri        PersistableBundle retConfig = CarrierConfigManager.getDefaultConfig();
6706465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        if (SubscriptionManager.isValidPhoneId(phoneId)) {
671c31f1f32963534763aaf82ae2544f3a94f13edcaJonathan Basseri            PersistableBundle config = mConfigFromDefaultApp[phoneId];
6726b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            if (config != null)
6736b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri                retConfig.putAll(config);
6746465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            config = mConfigFromCarrierApp[phoneId];
6756b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri            if (config != null)
6766b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri                retConfig.putAll(config);
6776465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        }
6786465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        return retConfig;
6796465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    }
6806465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
6816465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    @Override
6828603035b5620cc61b8987ba576466f9aed083931Jonathan Basseri    public void notifyConfigChangedForSubId(int subId) {
6836465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        int phoneId = SubscriptionManager.getPhoneId(subId);
6841f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        if (!SubscriptionManager.isValidPhoneId(phoneId)) {
6856465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            log("Ignore invalid phoneId: " + phoneId + " for subId: " + subId);
6861f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri            return;
6876465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        }
6881f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        String callingPackageName = mContext.getPackageManager().getNameForUid(
6891f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                Binder.getCallingUid());
6901f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        // TODO: Check that the calling packages is privileged for subId specifically.
6911f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        int privilegeStatus = TelephonyManager.from(mContext).checkCarrierPrivilegesForPackage(
6921f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                callingPackageName);
693fbd2bcbfec0e6d70306e19a9a7788dc99ef54a42Junda Liu        // Requires the calling app to be either a carrier privileged app or
694fbd2bcbfec0e6d70306e19a9a7788dc99ef54a42Junda Liu        // system privileged app with MODIFY_PHONE_STATE permission.
6951f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        if (privilegeStatus != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
696fbd2bcbfec0e6d70306e19a9a7788dc99ef54a42Junda Liu            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE,
697fbd2bcbfec0e6d70306e19a9a7788dc99ef54a42Junda Liu                    "Require carrier privileges or MODIFY_PHONE_STATE permission.");
6981f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        }
6991f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri
7001f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        // This method should block until deleting has completed, so that an error which prevents us
7011f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        // from clearing the cache is passed back to the carrier app. With the files successfully
7021f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        // deleted, this can return and we will eventually bind to the carrier app.
7037697cae0185c7a3b4c62895245320f3f24abcadaJonathan Basseri        clearCachedConfigForPackage(callingPackageName);
7041f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri        updateConfigForPhoneId(phoneId);
7056465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    }
7066465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
7076465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    @Override
7086465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    public void updateConfigForPhoneId(int phoneId, String simState) {
7091f2b34d415e020ab88bc152a8d93116482da8d6aJunda Liu        mContext.enforceCallingOrSelfPermission(
7101f2b34d415e020ab88bc152a8d93116482da8d6aJunda Liu                android.Manifest.permission.MODIFY_PHONE_STATE, null);
7116465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        log("update config for phoneId: " + phoneId + " simState: " + simState);
7126465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        if (!SubscriptionManager.isValidPhoneId(phoneId)) {
7136465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            return;
7146465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        }
7156465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        // requires Java 7 for switch on string.
7166465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        switch (simState) {
7176465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            case IccCardConstants.INTENT_VALUE_ICC_ABSENT:
7186465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            case IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR:
7196f5fddf570cd729eddcdb8479802631babbfb5b9Junda Liu            case IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED:
7206465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            case IccCardConstants.INTENT_VALUE_ICC_UNKNOWN:
7219f2d271f693b445e513235ebc48ccd0f67926860Junda Liu                mHandler.sendMessage(mHandler.obtainMessage(EVENT_CLEAR_CONFIG, phoneId, -1));
7226465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                break;
7236465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            case IccCardConstants.INTENT_VALUE_ICC_LOADED:
7246465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            case IccCardConstants.INTENT_VALUE_ICC_LOCKED:
7251f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                updateConfigForPhoneId(phoneId);
7266465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri                break;
7276465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        }
7286465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    }
7296465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
73043d723a19bed8492da059b394869065cc713c484Junda Liu    @Override
731a6fcfed336cbdfe85a84e695bde5b63d71c39a55Jeff Sharkey    public String getDefaultCarrierServicePackageName() {
732a6fcfed336cbdfe85a84e695bde5b63d71c39a55Jeff Sharkey        return mPlatformCarrierConfigPackage;
733a6fcfed336cbdfe85a84e695bde5b63d71c39a55Jeff Sharkey    }
734a6fcfed336cbdfe85a84e695bde5b63d71c39a55Jeff Sharkey
735a6fcfed336cbdfe85a84e695bde5b63d71c39a55Jeff Sharkey    @Override
73643d723a19bed8492da059b394869065cc713c484Junda Liu    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
73743d723a19bed8492da059b394869065cc713c484Junda Liu        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
73843d723a19bed8492da059b394869065cc713c484Junda Liu                != PackageManager.PERMISSION_GRANTED) {
73943d723a19bed8492da059b394869065cc713c484Junda Liu            pw.println("Permission Denial: can't dump carrierconfig from from pid="
74043d723a19bed8492da059b394869065cc713c484Junda Liu                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
74143d723a19bed8492da059b394869065cc713c484Junda Liu            return;
74243d723a19bed8492da059b394869065cc713c484Junda Liu        }
74343d723a19bed8492da059b394869065cc713c484Junda Liu        pw.println("CarrierConfigLoader: " + this);
74443d723a19bed8492da059b394869065cc713c484Junda Liu        for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
74526a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq            pw.println("Phone Id = " + i);
74626a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq            // display default values in CarrierConfigManager
74726a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq            printConfig(CarrierConfigManager.getDefaultConfig(), pw,
74826a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq                    "Default Values from CarrierConfigManager");
74926a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq            pw.println("");
75026a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq            // display ConfigFromDefaultApp
75126a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq            printConfig(mConfigFromDefaultApp[i], pw, "mConfigFromDefaultApp");
75226a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq            pw.println("");
75326a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq            // display ConfigFromCarrierApp
75426a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq            printConfig(mConfigFromCarrierApp[i], pw, "mConfigFromCarrierApp");
75526a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq        }
75626a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq    }
75726a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq
75826a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq    private void printConfig(PersistableBundle configApp, PrintWriter pw, String name) {
75926a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq        IndentingPrintWriter indentPW = new IndentingPrintWriter(pw, "    ");
76026a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq        if (configApp == null) {
76126a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq            indentPW.increaseIndent();
76226a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq            indentPW.println(name + " : null ");
76326a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq            return;
76426a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq        }
76526a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq        indentPW.increaseIndent();
76626a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq        indentPW.println(name + " : ");
76726a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq        List<String> sortedKeys = new ArrayList<String>(configApp.keySet());
76826a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq        Collections.sort(sortedKeys);
76926a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq        indentPW.increaseIndent();
77026a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq        indentPW.increaseIndent();
77126a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq        for (String key : sortedKeys) {
77226a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq            if (configApp.get(key) != null && configApp.get(key) instanceof Object[]) {
77326a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq                indentPW.println(key + " = " +
77426a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq                        Arrays.toString((Object[]) configApp.get(key)));
77526a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq            } else if (configApp.get(key) != null && configApp.get(key) instanceof int[]) {
77626a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq                indentPW.println(key + " = " + Arrays.toString((int[]) configApp.get(key)));
77726a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq            } else {
77826a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq                indentPW.println(key + " = " + configApp.get(key));
77926a3a4cae7dd67710361ef83baee2e6cb9ed01b4shuoq            }
78043d723a19bed8492da059b394869065cc713c484Junda Liu        }
78143d723a19bed8492da059b394869065cc713c484Junda Liu    }
78243d723a19bed8492da059b394869065cc713c484Junda Liu
78336d7aab00cd08f9efded5148c8f8a42ed7402641Zach Johnson    private class CarrierServiceConnection implements ServiceConnection {
7846465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        int phoneId;
7856465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        int eventId;
7866465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        IBinder service;
7876465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
78836d7aab00cd08f9efded5148c8f8a42ed7402641Zach Johnson        public CarrierServiceConnection(int phoneId, int eventId) {
7896465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            this.phoneId = phoneId;
7906465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            this.eventId = eventId;
7916465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        }
7926465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
7936465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        @Override
7946465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        public void onServiceConnected(ComponentName name, IBinder service) {
7956465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            log("Connected to config app: " + name.flattenToString());
7966465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            this.service = service;
7976465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            mHandler.sendMessage(mHandler.obtainMessage(eventId, phoneId, -1, this));
7986465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        }
7996465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
8006465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        @Override
8016465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        public void onServiceDisconnected(ComponentName name) {
8026465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            this.service = null;
8036465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        }
8046465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    }
8056465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
8066465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    private class ConfigLoaderBroadcastReceiver extends BroadcastReceiver {
8076465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        @Override
8086465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        public void onReceive(Context context, Intent intent) {
8096465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri            String action = intent.getAction();
8108a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu            boolean replace = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
8118a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu            // If replace is true, only care ACTION_PACKAGE_REPLACED.
8128a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu            if (replace && !Intent.ACTION_PACKAGE_REPLACED.equals(action))
8138a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu                return;
8148a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu
8151f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri            switch (action) {
8163d670504427b08d6efd96d05401b6a5d5e44742dNanxi Chen                case Intent.ACTION_BOOT_COMPLETED:
8173d670504427b08d6efd96d05401b6a5d5e44742dNanxi Chen                    mHandler.sendMessage(mHandler.obtainMessage(EVENT_SYSTEM_UNLOCKED, null));
8183d670504427b08d6efd96d05401b6a5d5e44742dNanxi Chen                    break;
8193d670504427b08d6efd96d05401b6a5d5e44742dNanxi Chen
8201f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                case Intent.ACTION_PACKAGE_ADDED:
8211f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                case Intent.ACTION_PACKAGE_REMOVED:
8228a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu                case Intent.ACTION_PACKAGE_REPLACED:
8231f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                    int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
8241f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                    String packageName = mContext.getPackageManager().getNameForUid(uid);
8258a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu                    if (packageName != null) {
8268a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu                        // We don't have a phoneId for arg1.
8278a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu                        mHandler.sendMessage(
8288a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu                                mHandler.obtainMessage(EVENT_PACKAGE_CHANGED, packageName));
8298a8a53ad137a6f40a00613f2c1f273bf798c8a61Junda Liu                    }
8301f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri                    break;
8311f743c9007ee5bdfca3d2d5eb875dd8c99e654d6Jonathan Basseri            }
8326465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri        }
8336465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    }
8346465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
8356465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    private static void log(String msg) {
8366b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        Log.d(LOG_TAG, msg);
8376465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri    }
8386465afd1636d57fce4291b02beaa88facd4e02aeJonathan Basseri
8396b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri    private static void loge(String msg) {
8406b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri        Log.e(LOG_TAG, msg);
8416b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri    }
8426b50e9f0ec71ffbd630da9c280a9d64ec267f33eJonathan Basseri}
843