Add nullability support for CarrierConfigLoader class

Follow the Android API guideline at
go/android-api-guidelines#nullability to annotate all non-primitive Java
arguments and return types with nullability.

Bug: 185129900
Test: atest CarrierConfigLoaderTest
Change-Id: Ia366727690ae451e4c8936b5907213f651aecd36
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index 4f4b2a7..2ec491b 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -88,42 +88,46 @@
     private static final String LOG_TAG = "CarrierConfigLoader";
 
     // Package name for platform carrier config app, bundled with system image.
-    private final String mPlatformCarrierConfigPackage;
+    @NonNull private final String mPlatformCarrierConfigPackage;
 
     /** The singleton instance. */
-    private static CarrierConfigLoader sInstance;
+    @Nullable private static CarrierConfigLoader sInstance;
     // The context for phone app, passed from PhoneGlobals.
-    private Context mContext;
+    @NonNull private Context mContext;
+
+    // All the states below (array indexed by phoneId) are non-null. But the member of the array
+    // is nullable, when e.g. the config for the phone is not loaded yet
     // Carrier configs from default app, indexed by phoneID.
-    private PersistableBundle[] mConfigFromDefaultApp;
+    @NonNull private PersistableBundle[] mConfigFromDefaultApp;
     // Carrier configs from privileged carrier config app, indexed by phoneID.
-    private PersistableBundle[] mConfigFromCarrierApp;
+    @NonNull private PersistableBundle[] mConfigFromCarrierApp;
     // Persistent Carrier configs that are provided via the override test API, indexed by phone ID.
-    private PersistableBundle[] mPersistentOverrideConfigs;
+    @NonNull private PersistableBundle[] mPersistentOverrideConfigs;
     // Carrier configs that are provided via the override test API, indexed by phone ID.
-    private PersistableBundle[] mOverrideConfigs;
+    @NonNull private PersistableBundle[] mOverrideConfigs;
     // Carrier configs to override code default when there is no SIM inserted
-    private PersistableBundle mNoSimConfig;
+    @NonNull private PersistableBundle mNoSimConfig;
     // Service connection for binding to config app.
-    private CarrierServiceConnection[] mServiceConnection;
+    @NonNull private CarrierServiceConnection[] mServiceConnection;
     // Service connection for binding to carrier config app for no SIM config.
-    private CarrierServiceConnection[] mServiceConnectionForNoSimConfig;
+    @NonNull private CarrierServiceConnection[] mServiceConnectionForNoSimConfig;
     // Whether we are bound to a service for each phone
-    private boolean[] mServiceBound;
+    @NonNull private boolean[] mServiceBound;
     // Whether we are bound to a service for no SIM config
-    private boolean[] mServiceBoundForNoSimConfig;
+    @NonNull private boolean[] mServiceBoundForNoSimConfig;
     // Whether we have sent config change broadcast for each phone id.
-    private boolean[] mHasSentConfigChange;
+    @NonNull private boolean[] mHasSentConfigChange;
     // Whether the broadcast was sent from EVENT_SYSTEM_UNLOCKED, to track rebroadcasts
-    private boolean[] mFromSystemUnlocked;
+    @NonNull private boolean[] mFromSystemUnlocked;
+
     // SubscriptionInfoUpdater
-    private final SubscriptionInfoUpdater mSubscriptionInfoUpdater;
+    @NonNull private final SubscriptionInfoUpdater mSubscriptionInfoUpdater;
 
     // Broadcast receiver for Boot intents, register intent filter in construtor.
-    private final BroadcastReceiver mBootReceiver = new ConfigLoaderBroadcastReceiver();
+    @NonNull private final BroadcastReceiver mBootReceiver = new ConfigLoaderBroadcastReceiver();
     // Broadcast receiver for SIM and pkg intents, register intent filter in constructor.
-    private final BroadcastReceiver mPackageReceiver = new ConfigLoaderBroadcastReceiver();
-    private final LocalLog mCarrierConfigLoadingLog = new LocalLog(100);
+    @NonNull private final BroadcastReceiver mPackageReceiver = new ConfigLoaderBroadcastReceiver();
+    @NonNull private final LocalLog mCarrierConfigLoadingLog = new LocalLog(100);
 
 
     // Message codes; see mHandler below.
@@ -210,7 +214,7 @@
         }
 
         @Override
-        public void handleMessage(Message msg) {
+        public void handleMessage(@NonNull Message msg) {
             final int phoneId = msg.arg1;
             logdWithLocalLog("mHandler: " + eventToString(msg.what) + " phoneId: " + phoneId);
             if (!SubscriptionManager.isValidPhoneId(phoneId)
@@ -676,15 +680,15 @@
         }
     }
 
-    private final Handler mHandler;
+    @NonNull private final Handler mHandler;
 
     /**
      * Constructs a CarrierConfigLoader, registers it as a service, and registers a broadcast
      * receiver for relevant events.
      */
     @VisibleForTesting
-    /* package */ CarrierConfigLoader(Context context,
-            SubscriptionInfoUpdater subscriptionInfoUpdater, @NonNull Looper looper) {
+    /* package */ CarrierConfigLoader(@NonNull Context context,
+            @NonNull SubscriptionInfoUpdater subscriptionInfoUpdater, @NonNull Looper looper) {
         mContext = context;
         mPlatformCarrierConfigPackage =
                 mContext.getString(R.string.platform_carrier_config_package);
@@ -725,7 +729,8 @@
      *
      * This is only done once, at startup, from {@link com.android.phone.PhoneApp#onCreate}.
      */
-    /* package */ static CarrierConfigLoader init(Context context) {
+    @NonNull
+    /* package */ static CarrierConfigLoader init(@NonNull Context context) {
         synchronized (CarrierConfigLoader.class) {
             if (sInstance == null) {
                 sInstance = new CarrierConfigLoader(context,
@@ -835,7 +840,7 @@
     }
 
     /** Binds to the default or carrier config app. */
-    private boolean bindToConfigPackage(String pkgName, int phoneId, int eventId) {
+    private boolean bindToConfigPackage(@NonNull String pkgName, int phoneId, int eventId) {
         logdWithLocalLog("Binding to " + pkgName + " for phone " + phoneId);
         Intent carrierService = new Intent(CarrierService.CARRIER_SERVICE_INTERFACE);
         carrierService.setPackage(pkgName);
@@ -864,6 +869,7 @@
     }
 
     @VisibleForTesting
+    @NonNull
     /* package */ CarrierIdentifier getCarrierIdentifierForPhoneId(int phoneId) {
         String mcc = "";
         String mnc = "";
@@ -902,6 +908,7 @@
         }
     }
 
+    @Nullable
     private String getIccIdForPhoneId(int phoneId) {
         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
             return null;
@@ -963,8 +970,9 @@
      * @param config        the bundle to be written. Null will be treated as an empty bundle.
      * @param isNoSimConfig whether this is invoked for noSimConfig or not.
      */
-    private void saveConfigToXml(String packageName, @NonNull String extraString, int phoneId,
-            CarrierIdentifier carrierId, PersistableBundle config, boolean isNoSimConfig) {
+    private void saveConfigToXml(@Nullable String packageName, @NonNull String extraString,
+            int phoneId, @Nullable CarrierIdentifier carrierId, @NonNull PersistableBundle config,
+            boolean isNoSimConfig) {
         if (packageName == null) {
             loge("Cannot save config with null packageName");
             return;
@@ -981,7 +989,8 @@
             }
 
             final String iccid = getIccIdForPhoneId(phoneId);
-            final int cid = carrierId.getSpecificCarrierId();
+            final int cid = carrierId != null ? carrierId.getSpecificCarrierId()
+                    : TelephonyManager.UNKNOWN_CARRIER_ID;
             if (iccid == null) {
                 loge("Cannot save config with null iccid.");
                 return;
@@ -1020,13 +1029,14 @@
     }
 
     @VisibleForTesting
-    /* package */ void saveConfigToXml(String packageName, @NonNull String extraString, int phoneId,
-            CarrierIdentifier carrierId, PersistableBundle config) {
+    /* package */ void saveConfigToXml(@Nullable String packageName, @NonNull String extraString,
+            int phoneId, @NonNull CarrierIdentifier carrierId, @NonNull PersistableBundle config) {
         saveConfigToXml(packageName, extraString, phoneId, carrierId, config, false);
     }
 
     @VisibleForTesting
-    /* package */ void saveNoSimConfigToXml(String packageName, PersistableBundle config) {
+    /* package */ void saveNoSimConfigToXml(@Nullable String packageName,
+            @NonNull PersistableBundle config) {
         saveConfigToXml(packageName, "", -1, null, config, true);
     }
 
@@ -1046,8 +1056,9 @@
      * @return the bundle from the XML file. Returns null if there is no saved config, the saved
      * version does not match, or reading config fails.
      */
-    private PersistableBundle restoreConfigFromXml(String packageName, @NonNull String extraString,
-            int phoneId, boolean isNoSimConfig) {
+    @Nullable
+    private PersistableBundle restoreConfigFromXml(@Nullable String packageName,
+            @NonNull String extraString, int phoneId, boolean isNoSimConfig) {
         if (packageName == null) {
             loge("Cannot restore config with null packageName");
         }
@@ -1116,7 +1127,8 @@
     /**
      * This method will mask most part of iccid in the filepath for logging on userbuild
      */
-    private String getFilePathForLogging(String filePath, String iccid) {
+    @NonNull
+    private String getFilePathForLogging(@Nullable String filePath, @Nullable String iccid) {
         // If loggable then return with actual file path
         if (Rlog.isLoggable(LOG_TAG, Log.VERBOSE)) {
             return filePath;
@@ -1129,12 +1141,14 @@
         return path;
     }
 
-    private PersistableBundle restoreConfigFromXml(String packageName, @NonNull String extraString,
-            int phoneId) {
+    @Nullable
+    private PersistableBundle restoreConfigFromXml(@Nullable String packageName,
+            @NonNull String extraString, int phoneId) {
         return restoreConfigFromXml(packageName, extraString, phoneId, false);
     }
 
-    private PersistableBundle restoreNoSimConfigFromXml(String packageName) {
+    @Nullable
+    private PersistableBundle restoreNoSimConfigFromXml(@Nullable String packageName) {
         return restoreConfigFromXml(packageName, "", -1, true);
     }
 
@@ -1147,7 +1161,7 @@
      *                    cleared.
      * @return true iff one or more files were deleted.
      */
-    private boolean clearCachedConfigForPackage(final String packageName) {
+    private boolean clearCachedConfigForPackage(@Nullable final String packageName) {
         File dir = mContext.getFilesDir();
         File[] packageFiles = dir.listFiles(new FilenameFilter() {
             public boolean accept(File dir, String filename) {
@@ -1167,6 +1181,7 @@
     }
 
     /** Builds a canonical file name for a config file. */
+    @NonNull
     private static String getFilenameForConfig(
             @NonNull String packageName, @NonNull String extraString,
             @NonNull String iccid, int cid) {
@@ -1178,12 +1193,14 @@
     }
 
     /** Builds a canonical file name for no SIM config file. */
+    @NonNull
     private String getFilenameForNoSimConfig(@NonNull String packageName) {
         return "carrierconfig-" + packageName + "-" + "nosim" + ".xml";
     }
 
     /** Return the current version code of a package, or null if the name is not found. */
-    private String getPackageVersion(String packageName) {
+    @Nullable
+    private String getPackageVersion(@NonNull String packageName) {
         try {
             PackageInfo info = mContext.getPackageManager().getPackageInfo(packageName, 0);
             return Long.toString(info.getLongVersionCode());
@@ -1212,14 +1229,14 @@
 
     @Override
     @NonNull
-    public PersistableBundle getConfigForSubId(int subscriptionId, String callingPackage) {
+    public PersistableBundle getConfigForSubId(int subscriptionId, @NonNull String callingPackage) {
         return getConfigForSubIdWithFeature(subscriptionId, callingPackage, null);
     }
 
     @Override
     @NonNull
-    public PersistableBundle getConfigForSubIdWithFeature(int subscriptionId, String callingPackage,
-            String callingFeatureId) {
+    public PersistableBundle getConfigForSubIdWithFeature(int subscriptionId,
+            @NonNull String callingPackage, @Nullable String callingFeatureId) {
         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, subscriptionId,
                 callingPackage, callingFeatureId, "getCarrierConfig")) {
             return new PersistableBundle();
@@ -1332,7 +1349,7 @@
     }
 
     @Override
-    public void updateConfigForPhoneId(int phoneId, String simState) {
+    public void updateConfigForPhoneId(int phoneId, @NonNull String simState) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.MODIFY_PHONE_STATE, null);
         logdWithLocalLog("Update config for phoneId: " + phoneId + " simState: " + simState);
@@ -1356,6 +1373,7 @@
     }
 
     @Override
+    @NonNull
     public String getDefaultCarrierServicePackageName() {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
@@ -1364,31 +1382,36 @@
     }
 
     @VisibleForTesting
+    @NonNull
     /* package */ Handler getHandler() {
         return mHandler;
     }
 
     @VisibleForTesting
+    @Nullable
     /* package */ PersistableBundle getConfigFromDefaultApp(int phoneId) {
         return mConfigFromDefaultApp[phoneId];
     }
 
     @VisibleForTesting
+    @Nullable
     /* package */ PersistableBundle getConfigFromCarrierApp(int phoneId) {
         return mConfigFromCarrierApp[phoneId];
     }
 
     @VisibleForTesting
+    @NonNull
      /* package */ PersistableBundle getNoSimConfig() {
         return mNoSimConfig;
     }
 
     @VisibleForTesting
+    @Nullable
     /* package */ PersistableBundle getOverrideConfig(int phoneId) {
         return mOverrideConfigs[phoneId];
     }
 
-    private void unbindIfBound(Context context, CarrierServiceConnection conn,
+    private void unbindIfBound(@NonNull Context context, @NonNull CarrierServiceConnection conn,
             int phoneId) {
         if (mServiceBound[phoneId]) {
             mServiceBound[phoneId] = false;
@@ -1396,8 +1419,8 @@
         }
     }
 
-    private void unbindIfBoundForNoSimConfig(Context context, CarrierServiceConnection conn,
-            int phoneId) {
+    private void unbindIfBoundForNoSimConfig(@NonNull Context context,
+            @NonNull CarrierServiceConnection conn, int phoneId) {
         if (mServiceBoundForNoSimConfig[phoneId]) {
             mServiceBoundForNoSimConfig[phoneId] = false;
             context.unbindService(conn);
@@ -1408,6 +1431,7 @@
      * Returns a boxed Integer object for phoneId, services as message token to distinguish messages
      * with same code when calling {@link Handler#removeMessages(int, Object)}.
      */
+    @NonNull
     private Integer getMessageToken(int phoneId) {
         if (phoneId < -128 || phoneId > 127) {
             throw new IllegalArgumentException("phoneId should be in range [-128, 127], inclusive");
@@ -1425,7 +1449,7 @@
      * too much info, but we still want to let carrier apps include their diagnostics.
      */
     @Override
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+    public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
         IndentingPrintWriter indentPW = new IndentingPrintWriter(pw, "    ");
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
                 != PackageManager.PERMISSION_GRANTED) {
@@ -1473,8 +1497,8 @@
         }
     }
 
-    private void printConfig(PersistableBundle configApp, IndentingPrintWriter indentPW,
-            String name) {
+    private void printConfig(@NonNull PersistableBundle configApp,
+            @NonNull IndentingPrintWriter indentPW, @NonNull String name) {
         indentPW.increaseIndent();
         if (configApp == null) {
             indentPW.println(name + " : null ");
@@ -1511,7 +1535,7 @@
      *
      * @throws SecurityException if none of the above conditions are met.
      */
-    private void enforceCallerIsSystemOrRequestingPackage(String requestingPackage)
+    private void enforceCallerIsSystemOrRequestingPackage(@NonNull String requestingPackage)
             throws SecurityException {
         final int callingUid = Binder.getCallingUid();
         if (callingUid == Process.ROOT_UID || callingUid == Process.SYSTEM_UID
@@ -1539,8 +1563,9 @@
      *                                  otherwise, only dump a carrier service if it is {@code
      *                                  targetPkgName}
      */
-    private void dumpCarrierServiceIfBound(FileDescriptor fd, IndentingPrintWriter indentPW,
-            String prefix, String targetPkgName, boolean considerCarrierPrivileges) {
+    private void dumpCarrierServiceIfBound(@NonNull FileDescriptor fd,
+            @NonNull IndentingPrintWriter indentPW, @NonNull String prefix,
+            @NonNull String targetPkgName, boolean considerCarrierPrivileges) {
         // Null package is possible if it's early in the boot process, there was a recent crash, we
         // loaded the config from XML most recently, or a SIM slot is empty. Carrier apps with
         // long-lived bindings should typically get dumped here regardless. Even if an app is being
@@ -1609,7 +1634,7 @@
         indentPW.decreaseIndent();
     }
 
-    private boolean hasCarrierPrivileges(String pkgName, int phoneId) {
+    private boolean hasCarrierPrivileges(@NonNull String pkgName, int phoneId) {
         int[] subIds = SubscriptionManager.getSubId(phoneId);
         if (ArrayUtils.isEmpty(subIds)) {
             return false;
@@ -1621,37 +1646,37 @@
 
     private class CarrierServiceConnection implements ServiceConnection {
         final int phoneId;
-        final String pkgName;
+        @NonNull final String pkgName;
         final int eventId;
         IBinder service;
 
-        CarrierServiceConnection(int phoneId, String pkgName, int eventId) {
+        CarrierServiceConnection(int phoneId, @NonNull String pkgName, int eventId) {
             this.phoneId = phoneId;
             this.pkgName = pkgName;
             this.eventId = eventId;
         }
 
         @Override
-        public void onServiceConnected(ComponentName name, IBinder service) {
+        public void onServiceConnected(@NonNull ComponentName name, @NonNull IBinder service) {
             logd("Connected to config app: " + name.flattenToShortString());
             this.service = service;
             mHandler.sendMessage(mHandler.obtainMessage(eventId, phoneId, -1, this));
         }
 
         @Override
-        public void onServiceDisconnected(ComponentName name) {
+        public void onServiceDisconnected(@NonNull ComponentName name) {
             logd("Disconnected from config app: " + name.flattenToShortString());
             this.service = null;
         }
 
         @Override
-        public void onBindingDied(ComponentName name) {
+        public void onBindingDied(@NonNull ComponentName name) {
             logd("Binding died from config app: " + name.flattenToShortString());
             this.service = null;
         }
 
         @Override
-        public void onNullBinding(ComponentName name) {
+        public void onNullBinding(@NonNull ComponentName name) {
             logd("Null binding from config app: " + name.flattenToShortString());
             this.service = null;
         }
@@ -1659,7 +1684,7 @@
 
     private class ConfigLoaderBroadcastReceiver extends BroadcastReceiver {
         @Override
-        public void onReceive(Context context, Intent intent) {
+        public void onReceive(@NonNull Context context, @NonNull Intent intent) {
             String action = intent.getAction();
             boolean replace = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
             // If replace is true, only care ACTION_PACKAGE_REPLACED.
@@ -1688,6 +1713,7 @@
     }
 
     // Get readable string for the message code supported in this class.
+    @NonNull
     private static String eventToString(int code) {
         switch (code) {
             case EVENT_CLEAR_CONFIG:
@@ -1737,20 +1763,20 @@
         }
     }
 
-    private void logd(String msg) {
+    private void logd(@NonNull String msg) {
         Log.d(LOG_TAG, msg);
     }
 
-    private void logd(String msg, Throwable tr) {
+    private void logd(@NonNull String msg, Throwable tr) {
         Log.d(LOG_TAG, msg, tr);
     }
 
-    private void logdWithLocalLog(String msg) {
+    private void logdWithLocalLog(@NonNull String msg) {
         Log.d(LOG_TAG, msg);
         mCarrierConfigLoadingLog.log(msg);
     }
 
-    private void loge(String msg) {
+    private void loge(@NonNull String msg) {
         Log.e(LOG_TAG, msg);
         mCarrierConfigLoadingLog.log(msg);
     }