• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2015, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.phone;
18 
19 import static android.service.carrier.CarrierService.ICarrierServiceWrapper.KEY_CONFIG_BUNDLE;
20 import static android.service.carrier.CarrierService.ICarrierServiceWrapper.RESULT_ERROR;
21 
22 import android.annotation.NonNull;
23 import android.app.ActivityManager;
24 import android.content.BroadcastReceiver;
25 import android.content.ComponentName;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.IntentFilter;
29 import android.content.ServiceConnection;
30 import android.content.SharedPreferences;
31 import android.content.pm.PackageInfo;
32 import android.content.pm.PackageManager;
33 import android.os.Binder;
34 import android.os.Build;
35 import android.os.Bundle;
36 import android.os.Handler;
37 import android.os.IBinder;
38 import android.os.Message;
39 import android.os.PersistableBundle;
40 import android.os.RemoteException;
41 import android.os.ResultReceiver;
42 import android.os.ServiceManager;
43 import android.os.UserHandle;
44 import android.preference.PreferenceManager;
45 import android.service.carrier.CarrierIdentifier;
46 import android.service.carrier.CarrierService;
47 import android.service.carrier.ICarrierService;
48 import android.telephony.CarrierConfigManager;
49 import android.telephony.SubscriptionManager;
50 import android.telephony.TelephonyManager;
51 import android.util.LocalLog;
52 import android.util.Log;
53 
54 import com.android.internal.telephony.ICarrierConfigLoader;
55 import com.android.internal.telephony.IccCardConstants;
56 import com.android.internal.telephony.Phone;
57 import com.android.internal.telephony.PhoneFactory;
58 import com.android.internal.telephony.SubscriptionInfoUpdater;
59 import com.android.internal.telephony.TelephonyPermissions;
60 import com.android.internal.util.FastXmlSerializer;
61 import com.android.internal.util.IndentingPrintWriter;
62 
63 import org.xmlpull.v1.XmlPullParser;
64 import org.xmlpull.v1.XmlPullParserException;
65 import org.xmlpull.v1.XmlPullParserFactory;
66 
67 import java.io.File;
68 import java.io.FileDescriptor;
69 import java.io.FileInputStream;
70 import java.io.FileNotFoundException;
71 import java.io.FileOutputStream;
72 import java.io.FilenameFilter;
73 import java.io.IOException;
74 import java.io.PrintWriter;
75 import java.util.ArrayList;
76 import java.util.Arrays;
77 import java.util.Collections;
78 import java.util.List;
79 
80 /**
81  * CarrierConfigLoader binds to privileged carrier apps to fetch carrier config overlays.
82  */
83 
84 public class CarrierConfigLoader extends ICarrierConfigLoader.Stub {
85     private static final String LOG_TAG = "CarrierConfigLoader";
86 
87     // Package name for platform carrier config app, bundled with system image.
88     private final String mPlatformCarrierConfigPackage;
89 
90     /** The singleton instance. */
91     private static CarrierConfigLoader sInstance;
92     // The context for phone app, passed from PhoneGlobals.
93     private Context mContext;
94     // Carrier configs from default app, indexed by phoneID.
95     private PersistableBundle[] mConfigFromDefaultApp;
96     // Carrier configs from privileged carrier config app, indexed by phoneID.
97     private PersistableBundle[] mConfigFromCarrierApp;
98     // Carrier configs that are provided via the override test API, indexed by phone ID.
99     private PersistableBundle[] mOverrideConfigs;
100     // Service connection for binding to config app.
101     private CarrierServiceConnection[] mServiceConnection;
102     // Whether we have sent config change bcast for each phone id.
103     private boolean[] mHasSentConfigChange;
104     // SubscriptionInfoUpdater
105     private final SubscriptionInfoUpdater mSubscriptionInfoUpdater;
106 
107     // Broadcast receiver for Boot intents, register intent filter in construtor.
108     private final BroadcastReceiver mBootReceiver = new ConfigLoaderBroadcastReceiver();
109     // Broadcast receiver for SIM and pkg intents, register intent filter in constructor.
110     private final BroadcastReceiver mPackageReceiver = new ConfigLoaderBroadcastReceiver();
111     private final LocalLog mCarrierConfigLoadingLog = new LocalLog(50);
112 
113 
114     // Message codes; see mHandler below.
115     // Request from SubscriptionInfoUpdater when SIM becomes absent or error.
116     private static final int EVENT_CLEAR_CONFIG = 0;
117     // Has connected to default app.
118     private static final int EVENT_CONNECTED_TO_DEFAULT = 3;
119     // Has connected to carrier app.
120     private static final int EVENT_CONNECTED_TO_CARRIER = 4;
121     // Config has been loaded from default app (or cache).
122     private static final int EVENT_FETCH_DEFAULT_DONE = 5;
123     // Config has been loaded from carrier app (or cache).
124     private static final int EVENT_FETCH_CARRIER_DONE = 6;
125     // Attempt to fetch from default app or read from XML.
126     private static final int EVENT_DO_FETCH_DEFAULT = 7;
127     // Attempt to fetch from carrier app or read from XML.
128     private static final int EVENT_DO_FETCH_CARRIER = 8;
129     // A package has been installed, uninstalled, or updated.
130     private static final int EVENT_PACKAGE_CHANGED = 9;
131     // Bind timed out for the default app.
132     private static final int EVENT_BIND_DEFAULT_TIMEOUT = 10;
133     // Bind timed out for a carrier app.
134     private static final int EVENT_BIND_CARRIER_TIMEOUT = 11;
135     // Check if the system fingerprint has changed.
136     private static final int EVENT_CHECK_SYSTEM_UPDATE = 12;
137     // Rerun carrier config binding after system is unlocked.
138     private static final int EVENT_SYSTEM_UNLOCKED = 13;
139     // Fetching config timed out from the default app.
140     private static final int EVENT_FETCH_DEFAULT_TIMEOUT = 14;
141     // Fetching config timed out from a carrier app.
142     private static final int EVENT_FETCH_CARRIER_TIMEOUT = 15;
143     // SubscriptionInfoUpdater has finished updating the sub for the carrier config.
144     private static final int EVENT_SUBSCRIPTION_INFO_UPDATED = 16;
145 
146     private static final int BIND_TIMEOUT_MILLIS = 30000;
147 
148     // Tags used for saving and restoring XML documents.
149     private static final String TAG_DOCUMENT = "carrier_config";
150     private static final String TAG_VERSION = "package_version";
151     private static final String TAG_BUNDLE = "bundle_data";
152 
153     // SharedPreferences key for last known build fingerprint.
154     private static final String KEY_FINGERPRINT = "build_fingerprint";
155 
156     // Handler to process various events.
157     //
158     // For each phoneId, the event sequence should be:
159     //     fetch default, connected to default, fetch default (async), fetch default done,
160     //     fetch carrier, connected to carrier, fetch carrier (async), fetch carrier done.
161     //
162     // If there is a saved config file for either the default app or the carrier app, we skip
163     // binding to the app and go straight from fetch to loaded.
164     //
165     // At any time, at most one connection is active. If events are not in this order, previous
166     // connection will be unbound, so only latest event takes effect.
167     //
168     // We broadcast ACTION_CARRIER_CONFIG_CHANGED after:
169     // 1. loading from carrier app (even if read from a file)
170     // 2. loading from default app if there is no carrier app (even if read from a file)
171     // 3. clearing config (e.g. due to sim removal)
172     // 4. encountering bind or IPC error
173     private class ConfigHandler extends Handler {
174         @Override
handleMessage(Message msg)175         public void handleMessage(Message msg) {
176             final int phoneId = msg.arg1;
177             logWithLocalLog("mHandler: " + msg.what + " phoneId: " + phoneId);
178             switch (msg.what) {
179                 case EVENT_CLEAR_CONFIG:
180                 {
181                     /* Ignore clear configuration request if device is being shutdown. */
182                     Phone phone = PhoneFactory.getPhone(phoneId);
183                     if (phone != null) {
184                         if (phone.isShuttingDown()) {
185                             break;
186                         }
187                     }
188 
189                     mConfigFromDefaultApp[phoneId] = null;
190                     mConfigFromCarrierApp[phoneId] = null;
191                     mServiceConnection[phoneId] = null;
192                     broadcastConfigChangedIntent(phoneId, false);
193                     break;
194                 }
195 
196                 case EVENT_SYSTEM_UNLOCKED:
197                 {
198                     for (int i = 0; i < TelephonyManager.from(mContext).getPhoneCount(); ++i) {
199                         // When user unlock device, we should only try to send broadcast again if we
200                         // have sent it before unlock. This will avoid we try to load carrier config
201                         // when SIM is still loading when unlock happens.
202                         if (mHasSentConfigChange[i]) {
203                             updateConfigForPhoneId(i);
204                         }
205                     }
206                     break;
207                 }
208 
209                 case EVENT_PACKAGE_CHANGED:
210                 {
211                     final String carrierPackageName = (String) msg.obj;
212                     // Only update if there are cached config removed to avoid updating config for
213                     // unrelated packages.
214                     if (clearCachedConfigForPackage(carrierPackageName)) {
215                         int numPhones = TelephonyManager.from(mContext).getPhoneCount();
216                         for (int i = 0; i < numPhones; ++i) {
217                             updateConfigForPhoneId(i);
218                         }
219                     }
220                     break;
221                 }
222 
223                 case EVENT_DO_FETCH_DEFAULT:
224                 {
225                     final PersistableBundle config =
226                             restoreConfigFromXml(mPlatformCarrierConfigPackage, phoneId);
227                     if (config != null) {
228                         log(
229                                 "Loaded config from XML. package="
230                                         + mPlatformCarrierConfigPackage
231                                         + " phoneId="
232                                         + phoneId);
233                         mConfigFromDefaultApp[phoneId] = config;
234                         Message newMsg = obtainMessage(EVENT_FETCH_DEFAULT_DONE, phoneId, -1);
235                         newMsg.getData().putBoolean("loaded_from_xml", true);
236                         mHandler.sendMessage(newMsg);
237                     } else {
238                         // No cached config, so fetch it from the default app.
239                         if (bindToConfigPackage(
240                                 mPlatformCarrierConfigPackage,
241                                 phoneId,
242                                 EVENT_CONNECTED_TO_DEFAULT)) {
243                             sendMessageDelayed(
244                                     obtainMessage(EVENT_BIND_DEFAULT_TIMEOUT, phoneId, -1),
245                                     BIND_TIMEOUT_MILLIS);
246                         } else {
247                             // Send broadcast if bind fails.
248                             notifySubscriptionInfoUpdater(phoneId);
249                             // TODO: We *must* call unbindService even if bindService returns false.
250                             // (And possibly if SecurityException was thrown.)
251                             loge("binding to default app: "
252                                     + mPlatformCarrierConfigPackage + " fails");
253                         }
254                     }
255                     break;
256                 }
257 
258                 case EVENT_CONNECTED_TO_DEFAULT:
259                 {
260                     removeMessages(EVENT_BIND_DEFAULT_TIMEOUT);
261                     final CarrierServiceConnection conn = (CarrierServiceConnection) msg.obj;
262                     // If new service connection has been created, unbind.
263                     if (mServiceConnection[phoneId] != conn || conn.service == null) {
264                         mContext.unbindService(conn);
265                         break;
266                     }
267                     final CarrierIdentifier carrierId = getCarrierIdentifierForPhoneId(phoneId);
268                     // ResultReceiver callback will execute in this Handler's thread.
269                     final ResultReceiver resultReceiver =
270                             new ResultReceiver(this) {
271                                 @Override
272                                 public void onReceiveResult(int resultCode, Bundle resultData) {
273                                     mContext.unbindService(conn);
274                                     // If new service connection has been created, this is stale.
275                                     if (mServiceConnection[phoneId] != conn) {
276                                         loge("Received response for stale request.");
277                                         return;
278                                     }
279                                     removeMessages(EVENT_FETCH_DEFAULT_TIMEOUT);
280                                     if (resultCode == RESULT_ERROR || resultData == null) {
281                                         // On error, abort config fetching.
282                                         loge("Failed to get carrier config");
283                                         notifySubscriptionInfoUpdater(phoneId);
284                                         return;
285                                     }
286                                     PersistableBundle config =
287                                             resultData.getParcelable(KEY_CONFIG_BUNDLE);
288                                     saveConfigToXml(
289                                             mPlatformCarrierConfigPackage, phoneId, config);
290                                     mConfigFromDefaultApp[phoneId] = config;
291                                     sendMessage(
292                                             obtainMessage(
293                                                     EVENT_FETCH_DEFAULT_DONE, phoneId, -1));
294                                 }
295                             };
296                     // Now fetch the config asynchronously from the ICarrierService.
297                     try {
298                         ICarrierService carrierService =
299                                 ICarrierService.Stub.asInterface(conn.service);
300                         carrierService.getCarrierConfig(carrierId, resultReceiver);
301                         logWithLocalLog("fetch config for default app: "
302                                 + mPlatformCarrierConfigPackage
303                                 + " carrierid: " + carrierId.toString());
304                     } catch (RemoteException e) {
305                         loge("Failed to get carrier config from default app: " +
306                                 mPlatformCarrierConfigPackage + " err: " + e.toString());
307                         mContext.unbindService(conn);
308                         break; // So we don't set a timeout.
309                     }
310                     sendMessageDelayed(
311                             obtainMessage(EVENT_FETCH_DEFAULT_TIMEOUT, phoneId, -1),
312                             BIND_TIMEOUT_MILLIS);
313                     break;
314                 }
315 
316                 case EVENT_BIND_DEFAULT_TIMEOUT:
317                 case EVENT_FETCH_DEFAULT_TIMEOUT:
318                 {
319                     loge("bind/fetch time out from " + mPlatformCarrierConfigPackage);
320                     removeMessages(EVENT_FETCH_DEFAULT_TIMEOUT);
321                     // If we attempted to bind to the app, but the service connection is null due to
322                     // the race condition that clear config event happens before bind/fetch complete
323                     // then config was cleared while we were waiting and we should not continue.
324                     if (mServiceConnection[phoneId] != null) {
325                         // If a ResponseReceiver callback is in the queue when this happens, we will
326                         // unbind twice and throw an exception.
327                         mContext.unbindService(mServiceConnection[phoneId]);
328                         broadcastConfigChangedIntent(phoneId);
329                     }
330                     notifySubscriptionInfoUpdater(phoneId);
331                     break;
332                 }
333 
334                 case EVENT_FETCH_DEFAULT_DONE:
335                 {
336                     // If we attempted to bind to the app, but the service connection is null, then
337                     // config was cleared while we were waiting and we should not continue.
338                     if (!msg.getData().getBoolean("loaded_from_xml", false)
339                             && mServiceConnection[phoneId] == null) {
340                         break;
341                     }
342                     final String carrierPackageName = getCarrierPackageForPhoneId(phoneId);
343                     if (carrierPackageName != null) {
344                         log("Found carrier config app: " + carrierPackageName);
345                         sendMessage(obtainMessage(EVENT_DO_FETCH_CARRIER, phoneId, -1));
346                     } else {
347                         notifySubscriptionInfoUpdater(phoneId);
348                     }
349                     break;
350                 }
351 
352                 case EVENT_DO_FETCH_CARRIER:
353                 {
354                     final String carrierPackageName = getCarrierPackageForPhoneId(phoneId);
355                     final PersistableBundle config =
356                             restoreConfigFromXml(carrierPackageName, phoneId);
357                     if (config != null) {
358                         log(
359                                 "Loaded config from XML. package="
360                                         + carrierPackageName
361                                         + " phoneId="
362                                         + phoneId);
363                         mConfigFromCarrierApp[phoneId] = config;
364                         Message newMsg = obtainMessage(EVENT_FETCH_CARRIER_DONE, phoneId, -1);
365                         newMsg.getData().putBoolean("loaded_from_xml", true);
366                         sendMessage(newMsg);
367                     } else {
368                         // No cached config, so fetch it from a carrier app.
369                         if (carrierPackageName != null
370                                 && bindToConfigPackage(
371                                         carrierPackageName,
372                                         phoneId,
373                                         EVENT_CONNECTED_TO_CARRIER)) {
374                             sendMessageDelayed(
375                                     obtainMessage(EVENT_BIND_CARRIER_TIMEOUT, phoneId, -1),
376                                     BIND_TIMEOUT_MILLIS);
377                         } else {
378                             // Send broadcast if bind fails.
379                             broadcastConfigChangedIntent(phoneId);
380                             loge("bind to carrier app: " + carrierPackageName + " fails");
381                             notifySubscriptionInfoUpdater(phoneId);
382                         }
383                     }
384                     break;
385                 }
386 
387                 case EVENT_CONNECTED_TO_CARRIER:
388                 {
389                     removeMessages(EVENT_BIND_CARRIER_TIMEOUT);
390                     final CarrierServiceConnection conn = (CarrierServiceConnection) msg.obj;
391                     // If new service connection has been created, unbind.
392                     if (mServiceConnection[phoneId] != conn || conn.service == null) {
393                         mContext.unbindService(conn);
394                         break;
395                     }
396                     final CarrierIdentifier carrierId = getCarrierIdentifierForPhoneId(phoneId);
397                     // ResultReceiver callback will execute in this Handler's thread.
398                     final ResultReceiver resultReceiver =
399                             new ResultReceiver(this) {
400                                 @Override
401                                 public void onReceiveResult(int resultCode, Bundle resultData) {
402                                     mContext.unbindService(conn);
403                                     // If new service connection has been created, this is stale.
404                                     if (mServiceConnection[phoneId] != conn) {
405                                         loge("Received response for stale request.");
406                                         return;
407                                     }
408                                     removeMessages(EVENT_FETCH_CARRIER_TIMEOUT);
409                                     if (resultCode == RESULT_ERROR || resultData == null) {
410                                         // On error, abort config fetching.
411                                         loge("Failed to get carrier config from carrier app: "
412                                                 + getCarrierPackageForPhoneId(phoneId));
413                                         broadcastConfigChangedIntent(phoneId);
414                                         notifySubscriptionInfoUpdater(phoneId);
415                                         return;
416                                     }
417                                     PersistableBundle config =
418                                             resultData.getParcelable(KEY_CONFIG_BUNDLE);
419                                     saveConfigToXml(
420                                             getCarrierPackageForPhoneId(phoneId), phoneId, config);
421                                     mConfigFromCarrierApp[phoneId] = config;
422                                     sendMessage(
423                                             obtainMessage(
424                                                     EVENT_FETCH_CARRIER_DONE, phoneId, -1));
425                                 }
426                             };
427                     // Now fetch the config asynchronously from the ICarrierService.
428                     try {
429                         ICarrierService carrierService =
430                                 ICarrierService.Stub.asInterface(conn.service);
431                         carrierService.getCarrierConfig(carrierId, resultReceiver);
432                         logWithLocalLog("fetch config for carrier app: "
433                                 + getCarrierPackageForPhoneId(phoneId)
434                                 + " carrierid: " + carrierId.toString());
435                     } catch (RemoteException e) {
436                         loge("Failed to get carrier config: " + e.toString());
437                         mContext.unbindService(conn);
438                         break; // So we don't set a timeout.
439                     }
440                     sendMessageDelayed(
441                             obtainMessage(EVENT_FETCH_CARRIER_TIMEOUT, phoneId, -1),
442                             BIND_TIMEOUT_MILLIS);
443                     break;
444                 }
445 
446                 case EVENT_BIND_CARRIER_TIMEOUT:
447                 case EVENT_FETCH_CARRIER_TIMEOUT:
448                 {
449                     loge("bind/fetch from carrier app timeout");
450                     removeMessages(EVENT_FETCH_CARRIER_TIMEOUT);
451                     // If we attempted to bind to the app, but the service connection is null due to
452                     // the race condition that clear config event happens before bind/fetch complete
453                     // then config was cleared while we were waiting and we should not continue.
454                     if (mServiceConnection[phoneId] != null) {
455                         // If a ResponseReceiver callback is in the queue when this happens, we will
456                         // unbind twice and throw an exception.
457                         mContext.unbindService(mServiceConnection[phoneId]);
458                         broadcastConfigChangedIntent(phoneId);
459                     }
460                     notifySubscriptionInfoUpdater(phoneId);
461                     break;
462                 }
463                 case EVENT_FETCH_CARRIER_DONE:
464                 {
465                     // If we attempted to bind to the app, but the service connection is null, then
466                     // config was cleared while we were waiting and we should not continue.
467                     if (!msg.getData().getBoolean("loaded_from_xml", false)
468                             && mServiceConnection[phoneId] == null) {
469                         break;
470                     }
471                     notifySubscriptionInfoUpdater(phoneId);
472                     break;
473                 }
474 
475                 case EVENT_CHECK_SYSTEM_UPDATE:
476                 {
477                     SharedPreferences sharedPrefs =
478                             PreferenceManager.getDefaultSharedPreferences(mContext);
479                     final String lastFingerprint = sharedPrefs.getString(KEY_FINGERPRINT, null);
480                     if (!Build.FINGERPRINT.equals(lastFingerprint)) {
481                         log(
482                                 "Build fingerprint changed. old: "
483                                         + lastFingerprint
484                                         + " new: "
485                                         + Build.FINGERPRINT);
486                         clearCachedConfigForPackage(null);
487                         sharedPrefs
488                                 .edit()
489                                 .putString(KEY_FINGERPRINT, Build.FINGERPRINT)
490                                 .apply();
491                     }
492                     break;
493                 }
494 
495                 case EVENT_SUBSCRIPTION_INFO_UPDATED:
496                     broadcastConfigChangedIntent(phoneId);
497                     break;
498             }
499         }
500     }
501 
502     private final Handler mHandler;
503 
504     /**
505      * Constructs a CarrierConfigLoader, registers it as a service, and registers a broadcast
506      * receiver for relevant events.
507      */
CarrierConfigLoader(Context context)508     private CarrierConfigLoader(Context context) {
509         mContext = context;
510         mPlatformCarrierConfigPackage =
511                 mContext.getString(R.string.platform_carrier_config_package);
512         mHandler = new ConfigHandler();
513 
514         IntentFilter bootFilter = new IntentFilter();
515         bootFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
516         context.registerReceiver(mBootReceiver, bootFilter);
517 
518         // Register for package updates. Update app or uninstall app update will have all 3 intents,
519         // in the order or removed, added, replaced, all with extra_replace set to true.
520         IntentFilter pkgFilter = new IntentFilter();
521         pkgFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
522         pkgFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
523         pkgFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
524         pkgFilter.addDataScheme("package");
525         context.registerReceiverAsUser(mPackageReceiver, UserHandle.ALL, pkgFilter, null, null);
526 
527         int numPhones = TelephonyManager.from(context).getPhoneCount();
528         mConfigFromDefaultApp = new PersistableBundle[numPhones];
529         mConfigFromCarrierApp = new PersistableBundle[numPhones];
530         mOverrideConfigs = new PersistableBundle[numPhones];
531         mServiceConnection = new CarrierServiceConnection[numPhones];
532         mHasSentConfigChange = new boolean[numPhones];
533         // Make this service available through ServiceManager.
534         ServiceManager.addService(Context.CARRIER_CONFIG_SERVICE, this);
535         log("CarrierConfigLoader has started");
536         mSubscriptionInfoUpdater = PhoneFactory.getSubscriptionInfoUpdater();
537         mHandler.sendEmptyMessage(EVENT_CHECK_SYSTEM_UPDATE);
538     }
539 
540     /**
541      * Initialize the singleton CarrierConfigLoader instance.
542      *
543      * This is only done once, at startup, from {@link com.android.phone.PhoneApp#onCreate}.
544      */
545     /* package */
init(Context context)546     static CarrierConfigLoader init(Context context) {
547         synchronized (CarrierConfigLoader.class) {
548             if (sInstance == null) {
549                 sInstance = new CarrierConfigLoader(context);
550             } else {
551                 Log.wtf(LOG_TAG, "init() called multiple times!  sInstance = " + sInstance);
552             }
553             return sInstance;
554         }
555     }
556 
notifySubscriptionInfoUpdater(int phoneId)557     private void notifySubscriptionInfoUpdater(int phoneId) {
558         String configPackagename;
559         PersistableBundle configToSend;
560         int carrierId = getSpecificCarrierIdForPhoneId(phoneId);
561         // Prefer the carrier privileged carrier app, but if there is not one, use the platform
562         // default carrier app.
563         if (mConfigFromCarrierApp[phoneId] != null) {
564             configPackagename = getCarrierPackageForPhoneId(phoneId);
565             configToSend = mConfigFromCarrierApp[phoneId];
566         } else {
567             configPackagename = mPlatformCarrierConfigPackage;
568             configToSend = mConfigFromDefaultApp[phoneId];
569         }
570         mSubscriptionInfoUpdater.updateSubscriptionByCarrierConfigAndNotifyComplete(
571                 phoneId, configPackagename, configToSend,
572                 mHandler.obtainMessage(EVENT_SUBSCRIPTION_INFO_UPDATED, phoneId, -1));
573     }
574 
broadcastConfigChangedIntent(int phoneId)575     private void broadcastConfigChangedIntent(int phoneId) {
576         broadcastConfigChangedIntent(phoneId, true);
577     }
578 
broadcastConfigChangedIntent(int phoneId, boolean addSubIdExtra)579     private void broadcastConfigChangedIntent(int phoneId, boolean addSubIdExtra) {
580         Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
581         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
582                 Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND |
583                 Intent.FLAG_RECEIVER_FOREGROUND);
584         // Include subId/carrier id extra only if SIM records are loaded
585         TelephonyManager telephonyManager = TelephonyManager.from(mContext);
586         int simApplicationState = telephonyManager.getSimApplicationState();
587         if (addSubIdExtra && (simApplicationState != TelephonyManager.SIM_STATE_UNKNOWN
588                 && simApplicationState != TelephonyManager.SIM_STATE_NOT_READY)) {
589             SubscriptionManager.putPhoneIdAndSubIdExtra(intent, phoneId);
590             intent.putExtra(TelephonyManager.EXTRA_SPECIFIC_CARRIER_ID,
591                     getSpecificCarrierIdForPhoneId(phoneId));
592             intent.putExtra(TelephonyManager.EXTRA_CARRIER_ID, getCarrierIdForPhoneId(phoneId));
593         }
594         intent.putExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, phoneId);
595         log("Broadcast CARRIER_CONFIG_CHANGED for phone " + phoneId);
596         ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL);
597         mHasSentConfigChange[phoneId] = true;
598     }
599 
600     /** Binds to the default or carrier config app. */
bindToConfigPackage(String pkgName, int phoneId, int eventId)601     private boolean bindToConfigPackage(String pkgName, int phoneId, int eventId) {
602         logWithLocalLog("Binding to " + pkgName + " for phone " + phoneId);
603         Intent carrierService = new Intent(CarrierService.CARRIER_SERVICE_INTERFACE);
604         carrierService.setPackage(pkgName);
605         mServiceConnection[phoneId] = new CarrierServiceConnection(phoneId, eventId);
606         try {
607             return mContext.bindService(carrierService, mServiceConnection[phoneId],
608                     Context.BIND_AUTO_CREATE);
609         } catch (SecurityException ex) {
610             return false;
611         }
612     }
613 
getCarrierIdentifierForPhoneId(int phoneId)614     private CarrierIdentifier getCarrierIdentifierForPhoneId(int phoneId) {
615         String mcc = "";
616         String mnc = "";
617         String imsi = "";
618         String gid1 = "";
619         String gid2 = "";
620         String spn = TelephonyManager.from(mContext).getSimOperatorNameForPhone(phoneId);
621         String simOperator = TelephonyManager.from(mContext).getSimOperatorNumericForPhone(phoneId);
622         int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
623         int specificCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
624         // A valid simOperator should be 5 or 6 digits, depending on the length of the MNC.
625         if (simOperator != null && simOperator.length() >= 3) {
626             mcc = simOperator.substring(0, 3);
627             mnc = simOperator.substring(3);
628         }
629         Phone phone = PhoneFactory.getPhone(phoneId);
630         if (phone != null) {
631             imsi = phone.getSubscriberId();
632             gid1 = phone.getGroupIdLevel1();
633             gid2 = phone.getGroupIdLevel2();
634             carrierId = phone.getCarrierId();
635             specificCarrierId = phone.getSpecificCarrierId();
636         }
637         return new CarrierIdentifier(mcc, mnc, spn, imsi, gid1, gid2, carrierId, specificCarrierId);
638     }
639 
640     /** Returns the package name of a priveleged carrier app, or null if there is none. */
getCarrierPackageForPhoneId(int phoneId)641     private String getCarrierPackageForPhoneId(int phoneId) {
642         List<String> carrierPackageNames = TelephonyManager.from(mContext)
643                 .getCarrierPackageNamesForIntentAndPhone(
644                         new Intent(CarrierService.CARRIER_SERVICE_INTERFACE), phoneId);
645         if (carrierPackageNames != null && carrierPackageNames.size() > 0) {
646             return carrierPackageNames.get(0);
647         } else {
648             return null;
649         }
650     }
651 
getIccIdForPhoneId(int phoneId)652     private String getIccIdForPhoneId(int phoneId) {
653         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
654             return null;
655         }
656         Phone phone = PhoneFactory.getPhone(phoneId);
657         if (phone == null) {
658             return null;
659         }
660         return phone.getIccSerialNumber();
661     }
662 
663     /**
664      * Get the sim specific carrier id {@link TelephonyManager#getSimSpecificCarrierId()}
665      */
getSpecificCarrierIdForPhoneId(int phoneId)666     private int getSpecificCarrierIdForPhoneId(int phoneId) {
667         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
668             return TelephonyManager.UNKNOWN_CARRIER_ID;
669         }
670         Phone phone = PhoneFactory.getPhone(phoneId);
671         if (phone == null) {
672             return TelephonyManager.UNKNOWN_CARRIER_ID;
673         }
674         return phone.getSpecificCarrierId();
675     }
676 
677     /**
678      * Get the sim carrier id {@link TelephonyManager#getSimCarrierId() }
679      */
getCarrierIdForPhoneId(int phoneId)680     private int getCarrierIdForPhoneId(int phoneId) {
681         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
682             return TelephonyManager.UNKNOWN_CARRIER_ID;
683         }
684         Phone phone = PhoneFactory.getPhone(phoneId);
685         if (phone == null) {
686             return TelephonyManager.UNKNOWN_CARRIER_ID;
687         }
688         return phone.getCarrierId();
689     }
690 
691     /**
692      * Writes a bundle to an XML file.
693      *
694      * The bundle will be written to a file named after the package name, ICCID and
695      * specific carrier id {@link TelephonyManager#getSimSpecificCarrierId()}. the same carrier
696      * should have a single copy of XML file named after carrier id. However, it's still possible
697      * that platform doesn't recognize the current sim carrier, we will use iccid + carrierid as
698      * the canonical file name. carrierid can also handle the cases SIM OTA resolves to different
699      * carrier while iccid remains the same.
700      *
701      * The file can be restored later with {@link @restoreConfigFromXml}. The XML output will
702      * include the bundle and the current version of the specified package.
703      *
704      * In case of errors or invalid input, no file will be written.
705      *
706      * @param packageName the name of the package from which we fetched this bundle.
707      * @param phoneId the phone ID.
708      * @param config the bundle to be written. Null will be treated as an empty bundle.
709      */
saveConfigToXml(String packageName, int phoneId, PersistableBundle config)710     private void saveConfigToXml(String packageName, int phoneId, PersistableBundle config) {
711         if (SubscriptionManager.getSimStateForSlotIndex(phoneId)
712                 != TelephonyManager.SIM_STATE_LOADED) {
713             loge("Skip save config because SIM records are not loaded.");
714             return;
715         }
716 
717         final String iccid = getIccIdForPhoneId(phoneId);
718         final int cid = getSpecificCarrierIdForPhoneId(phoneId);
719         if (packageName == null || iccid == null) {
720             loge("Cannot save config with null packageName or iccid.");
721             return;
722         }
723         // b/32668103 Only save to file if config isn't empty.
724         // In case of failure, not caching an empty bundle will
725         // try loading config again on next power on or sim loaded.
726         // Downside is for genuinely empty bundle, will bind and load
727         // on every power on.
728         if (config == null || config.isEmpty()) {
729             return;
730         }
731 
732         final String version = getPackageVersion(packageName);
733         if (version == null) {
734             loge("Failed to get package version for: " + packageName);
735             return;
736         }
737 
738         logWithLocalLog("save config to xml, packagename: " + packageName + " phoneId: " + phoneId);
739 
740         FileOutputStream outFile = null;
741         try {
742             outFile = new FileOutputStream(
743                     new File(mContext.getFilesDir(),
744                             getFilenameForConfig(packageName, iccid, cid)));
745             FastXmlSerializer out = new FastXmlSerializer();
746             out.setOutput(outFile, "utf-8");
747             out.startDocument("utf-8", true);
748             out.startTag(null, TAG_DOCUMENT);
749             out.startTag(null, TAG_VERSION);
750             out.text(version);
751             out.endTag(null, TAG_VERSION);
752             out.startTag(null, TAG_BUNDLE);
753             config.saveToXml(out);
754             out.endTag(null, TAG_BUNDLE);
755             out.endTag(null, TAG_DOCUMENT);
756             out.endDocument();
757             out.flush();
758             outFile.close();
759         }
760         catch (IOException e) {
761             loge(e.toString());
762         }
763         catch (XmlPullParserException e) {
764             loge(e.toString());
765         }
766     }
767 
768     /**
769      * Reads a bundle from an XML file.
770      *
771      * This restores a bundle that was written with {@link #saveConfigToXml}. This returns the saved
772      * config bundle for the given package and phone ID.
773      *
774      * In case of errors, or if the saved config is from a different package version than the
775      * current version, then null will be returned.
776      *
777      * @param packageName the name of the package from which we fetched this bundle.
778      * @param phoneId the phone ID.
779      * @return the bundle from the XML file. Returns null if there is no saved config, the saved
780      *         version does not match, or reading config fails.
781      */
restoreConfigFromXml(String packageName, int phoneId)782     private PersistableBundle restoreConfigFromXml(String packageName, int phoneId) {
783         final String version = getPackageVersion(packageName);
784         if (version == null) {
785             loge("Failed to get package version for: " + packageName);
786             return null;
787         }
788         if (SubscriptionManager.getSimStateForSlotIndex(phoneId)
789                 != TelephonyManager.SIM_STATE_LOADED) {
790             loge("Skip restoring config because SIM records are not yet loaded.");
791             return null;
792         }
793 
794         final String iccid = getIccIdForPhoneId(phoneId);
795         final int cid = getSpecificCarrierIdForPhoneId(phoneId);
796         if (packageName == null || iccid == null) {
797             loge("Cannot restore config with null packageName or iccid.");
798             return null;
799         }
800 
801         PersistableBundle restoredBundle = null;
802         FileInputStream inFile = null;
803         try {
804             inFile = new FileInputStream(
805                     new File(mContext.getFilesDir(),
806                             getFilenameForConfig(packageName, iccid, cid)));
807             XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
808             parser.setInput(inFile, "utf-8");
809 
810             int event;
811             while (((event = parser.next()) != XmlPullParser.END_DOCUMENT)) {
812 
813                 if (event == XmlPullParser.START_TAG && TAG_VERSION.equals(parser.getName())) {
814                     String savedVersion = parser.nextText();
815                     if (!version.equals(savedVersion)) {
816                         loge("Saved version mismatch: " + version + " vs " + savedVersion);
817                         break;
818                     }
819                 }
820 
821                 if (event == XmlPullParser.START_TAG && TAG_BUNDLE.equals(parser.getName())) {
822                     restoredBundle = PersistableBundle.restoreFromXml(parser);
823                 }
824             }
825             inFile.close();
826         }
827         catch (FileNotFoundException e) {
828             loge(e.toString());
829         }
830         catch (XmlPullParserException e) {
831             loge(e.toString());
832         }
833         catch (IOException e) {
834             loge(e.toString());
835         }
836 
837         return restoredBundle;
838     }
839 
840     /**
841      * Clears cached carrier config.
842      * This deletes all saved XML files associated with the given package name. If packageName is
843      * null, then it deletes all saved XML files.
844      *
845      * @param packageName the name of a carrier package, or null if all cached config should be
846      *                    cleared.
847      * @return true iff one or more files were deleted.
848      */
clearCachedConfigForPackage(final String packageName)849     private boolean clearCachedConfigForPackage(final String packageName) {
850         File dir = mContext.getFilesDir();
851         File[] packageFiles = dir.listFiles(new FilenameFilter() {
852             public boolean accept(File dir, String filename) {
853                 if (packageName != null) {
854                     return filename.startsWith("carrierconfig-" + packageName + "-");
855                 } else {
856                     return filename.startsWith("carrierconfig-");
857                 }
858             }
859         });
860         if (packageFiles == null || packageFiles.length < 1) return false;
861         for (File f : packageFiles) {
862             log("deleting " + f.getName());
863             f.delete();
864         }
865         return true;
866     }
867 
868     /** Builds a canonical file name for a config file. */
getFilenameForConfig(@onNull String packageName, @NonNull String iccid, int cid)869     private String getFilenameForConfig(@NonNull String packageName, @NonNull String iccid,
870                                         int cid) {
871         // the same carrier should have a single copy of XML file named after carrier id.
872         // However, it's still possible that platform doesn't recognize the current sim carrier,
873         // we will use iccid + carrierid as the canonical file name. carrierid can also handle the
874         // cases SIM OTA resolves to different carrier while iccid remains the same.
875         return "carrierconfig-" + packageName + "-" + iccid + "-" + cid + ".xml";
876     }
877 
878     /** Return the current version code of a package, or null if the name is not found. */
getPackageVersion(String packageName)879     private String getPackageVersion(String packageName) {
880         try {
881             PackageInfo info = mContext.getPackageManager().getPackageInfo(packageName, 0);
882             return Long.toString(info.getLongVersionCode());
883         } catch (PackageManager.NameNotFoundException e) {
884             return null;
885         }
886     }
887 
888     /**
889      * Read up to date config.
890      *
891      * This reads config bundles for the given phoneId. That means getting the latest bundle from
892      * the default app and a privileged carrier app, if present. This will not bind to an app if we
893      * have a saved config file to use instead.
894      */
updateConfigForPhoneId(int phoneId)895     private void updateConfigForPhoneId(int phoneId) {
896         // Clear in-memory cache for carrier app config, so when carrier app gets uninstalled, no
897         // stale config is left.
898         if (mConfigFromCarrierApp[phoneId] != null &&
899                 getCarrierPackageForPhoneId(phoneId) == null) {
900             mConfigFromCarrierApp[phoneId] = null;
901         }
902         mHandler.sendMessage(mHandler.obtainMessage(EVENT_DO_FETCH_DEFAULT, phoneId, -1));
903     }
904 
905     @Override
getConfigForSubId(int subId, String callingPackage)906     public @NonNull PersistableBundle getConfigForSubId(int subId, String callingPackage) {
907         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
908                 mContext, subId, callingPackage, "getCarrierConfig")) {
909             return new PersistableBundle();
910         }
911 
912         int phoneId = SubscriptionManager.getPhoneId(subId);
913         PersistableBundle retConfig = CarrierConfigManager.getDefaultConfig();
914         if (SubscriptionManager.isValidPhoneId(phoneId)) {
915             PersistableBundle config = mConfigFromDefaultApp[phoneId];
916             if (config != null) {
917                 retConfig.putAll(config);
918                 retConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
919             }
920             config = mConfigFromCarrierApp[phoneId];
921             if (config != null) {
922                 retConfig.putAll(config);
923                 retConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
924             }
925             config = mOverrideConfigs[phoneId];
926             if (config != null) {
927                 retConfig.putAll(config);
928                 retConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
929             }
930         }
931         return retConfig;
932     }
933 
934     @Override
overrideConfig(int subscriptionId, PersistableBundle overrides)935     public void overrideConfig(int subscriptionId, PersistableBundle overrides) {
936         mContext.enforceCallingOrSelfPermission(
937                 android.Manifest.permission.MODIFY_PHONE_STATE, null);
938         //TODO: Also check for SHELL UID to restrict this method to testing only (b/131326259)
939         int phoneId = SubscriptionManager.getPhoneId(subscriptionId);
940         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
941             log("Ignore invalid phoneId: " + phoneId + " for subId: " + subscriptionId);
942             return;
943         }
944 
945         if (overrides == null) {
946             mOverrideConfigs[phoneId] = new PersistableBundle();
947         } else if (mOverrideConfigs[phoneId] == null) {
948             mOverrideConfigs[phoneId] = overrides;
949         } else {
950             mOverrideConfigs[phoneId].putAll(overrides);
951         }
952 
953         notifySubscriptionInfoUpdater(phoneId);
954     }
955 
956     @Override
notifyConfigChangedForSubId(int subId)957     public void notifyConfigChangedForSubId(int subId) {
958         int phoneId = SubscriptionManager.getPhoneId(subId);
959         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
960             log("Ignore invalid phoneId: " + phoneId + " for subId: " + subId);
961             return;
962         }
963 
964         // Requires the calling app to be either a carrier privileged app for this subId or
965         // system privileged app with MODIFY_PHONE_STATE permission.
966         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mContext, subId,
967                 "Require carrier privileges or MODIFY_PHONE_STATE permission.");
968 
969         // This method should block until deleting has completed, so that an error which prevents us
970         // from clearing the cache is passed back to the carrier app. With the files successfully
971         // deleted, this can return and we will eventually bind to the carrier app.
972         String callingPackageName = mContext.getPackageManager().getNameForUid(
973                 Binder.getCallingUid());
974         clearCachedConfigForPackage(callingPackageName);
975         updateConfigForPhoneId(phoneId);
976     }
977 
978     @Override
updateConfigForPhoneId(int phoneId, String simState)979     public void updateConfigForPhoneId(int phoneId, String simState) {
980         mContext.enforceCallingOrSelfPermission(
981                 android.Manifest.permission.MODIFY_PHONE_STATE, null);
982         logWithLocalLog("update config for phoneId: " + phoneId + " simState: " + simState);
983         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
984             return;
985         }
986         // requires Java 7 for switch on string.
987         switch (simState) {
988             case IccCardConstants.INTENT_VALUE_ICC_ABSENT:
989             case IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR:
990             case IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED:
991             case IccCardConstants.INTENT_VALUE_ICC_UNKNOWN:
992                 mHandler.sendMessage(mHandler.obtainMessage(EVENT_CLEAR_CONFIG, phoneId, -1));
993                 break;
994             case IccCardConstants.INTENT_VALUE_ICC_LOADED:
995             case IccCardConstants.INTENT_VALUE_ICC_LOCKED:
996                 updateConfigForPhoneId(phoneId);
997                 break;
998         }
999     }
1000 
1001     @Override
getDefaultCarrierServicePackageName()1002     public String getDefaultCarrierServicePackageName() {
1003         return mPlatformCarrierConfigPackage;
1004     }
1005 
1006     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)1007     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1008         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1009                 != PackageManager.PERMISSION_GRANTED) {
1010             pw.println("Permission Denial: can't dump carrierconfig from from pid="
1011                     + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
1012             return;
1013         }
1014         pw.println("CarrierConfigLoader: " + this);
1015         for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
1016             pw.println("Phone Id = " + i);
1017             // display default values in CarrierConfigManager
1018             printConfig(CarrierConfigManager.getDefaultConfig(), pw,
1019                     "Default Values from CarrierConfigManager");
1020             pw.println("");
1021             // display ConfigFromDefaultApp
1022             printConfig(mConfigFromDefaultApp[i], pw, "mConfigFromDefaultApp");
1023             pw.println("");
1024             // display ConfigFromCarrierApp
1025             printConfig(mConfigFromCarrierApp[i], pw, "mConfigFromCarrierApp");
1026             pw.println("");
1027             printConfig(mOverrideConfigs[i], pw, "mOverrideConfigs");
1028         }
1029 
1030         pw.println("CarrierConfigLoadingLog=");
1031         mCarrierConfigLoadingLog.dump(fd, pw, args);
1032     }
1033 
printConfig(PersistableBundle configApp, PrintWriter pw, String name)1034     private void printConfig(PersistableBundle configApp, PrintWriter pw, String name) {
1035         IndentingPrintWriter indentPW = new IndentingPrintWriter(pw, "    ");
1036         if (configApp == null) {
1037             indentPW.increaseIndent();
1038             indentPW.println(name + " : null ");
1039             return;
1040         }
1041         indentPW.increaseIndent();
1042         indentPW.println(name + " : ");
1043         List<String> sortedKeys = new ArrayList<String>(configApp.keySet());
1044         Collections.sort(sortedKeys);
1045         indentPW.increaseIndent();
1046         indentPW.increaseIndent();
1047         for (String key : sortedKeys) {
1048             if (configApp.get(key) != null && configApp.get(key) instanceof Object[]) {
1049                 indentPW.println(key + " = " +
1050                         Arrays.toString((Object[]) configApp.get(key)));
1051             } else if (configApp.get(key) != null && configApp.get(key) instanceof int[]) {
1052                 indentPW.println(key + " = " + Arrays.toString((int[]) configApp.get(key)));
1053             } else {
1054                 indentPW.println(key + " = " + configApp.get(key));
1055             }
1056         }
1057     }
1058 
1059     private class CarrierServiceConnection implements ServiceConnection {
1060         int phoneId;
1061         int eventId;
1062         IBinder service;
1063 
CarrierServiceConnection(int phoneId, int eventId)1064         public CarrierServiceConnection(int phoneId, int eventId) {
1065             this.phoneId = phoneId;
1066             this.eventId = eventId;
1067         }
1068 
1069         @Override
onServiceConnected(ComponentName name, IBinder service)1070         public void onServiceConnected(ComponentName name, IBinder service) {
1071             log("Connected to config app: " + name.flattenToString());
1072             this.service = service;
1073             mHandler.sendMessage(mHandler.obtainMessage(eventId, phoneId, -1, this));
1074         }
1075 
1076         @Override
onServiceDisconnected(ComponentName name)1077         public void onServiceDisconnected(ComponentName name) {
1078             this.service = null;
1079         }
1080     }
1081 
1082     private class ConfigLoaderBroadcastReceiver extends BroadcastReceiver {
1083         @Override
onReceive(Context context, Intent intent)1084         public void onReceive(Context context, Intent intent) {
1085             String action = intent.getAction();
1086             boolean replace = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
1087             // If replace is true, only care ACTION_PACKAGE_REPLACED.
1088             if (replace && !Intent.ACTION_PACKAGE_REPLACED.equals(action))
1089                 return;
1090 
1091             switch (action) {
1092                 case Intent.ACTION_BOOT_COMPLETED:
1093                     mHandler.sendMessage(mHandler.obtainMessage(EVENT_SYSTEM_UNLOCKED, null));
1094                     break;
1095 
1096                 case Intent.ACTION_PACKAGE_ADDED:
1097                 case Intent.ACTION_PACKAGE_REMOVED:
1098                 case Intent.ACTION_PACKAGE_REPLACED:
1099                     int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
1100                     String packageName = mContext.getPackageManager().getNameForUid(uid);
1101                     if (packageName != null) {
1102                         // We don't have a phoneId for arg1.
1103                         mHandler.sendMessage(
1104                                 mHandler.obtainMessage(EVENT_PACKAGE_CHANGED, packageName));
1105                     }
1106                     break;
1107             }
1108         }
1109     }
1110 
log(String msg)1111     private void log(String msg) {
1112         Log.d(LOG_TAG, msg);
1113     }
1114 
logWithLocalLog(String msg)1115     private void logWithLocalLog(String msg) {
1116         Log.d(LOG_TAG, msg);
1117         mCarrierConfigLoadingLog.log(msg);
1118     }
1119 
loge(String msg)1120     private void loge(String msg) {
1121         Log.e(LOG_TAG, msg);
1122         mCarrierConfigLoadingLog.log(msg);
1123     }
1124 }
1125