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