Ims provisioning storage in AOSP
Bug: 202199221
Test: ImsProvisioningLoaderTest
Change-Id: I02e0246f9f5c95b8a8d57c3e7b1d820102168311
diff --git a/src/com/android/phone/ImsProvisioningLoader.java b/src/com/android/phone/ImsProvisioningLoader.java
new file mode 100644
index 0000000..a9aac26
--- /dev/null
+++ b/src/com/android/phone/ImsProvisioningLoader.java
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.PersistableBundle;
+import android.preference.PreferenceManager;
+import android.telephony.ims.ProvisioningManager;
+import android.telephony.ims.feature.ImsFeature;
+import android.telephony.ims.feature.MmTelFeature;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ * Provides a function to set/get Ims feature provisioning status in storage.
+ */
+public class ImsProvisioningLoader {
+ private static final String LOG_TAG = ImsProvisioningLoader.class.getSimpleName();
+
+ public static final int STATUS_NOT_SET = -1;
+ public static final int STATUS_NOT_PROVISIONED =
+ ProvisioningManager.PROVISIONING_VALUE_DISABLED;
+ public static final int STATUS_PROVISIONED =
+ ProvisioningManager.PROVISIONING_VALUE_ENABLED;
+
+ public static final int IMS_FEATURE_MMTEL = ImsFeature.FEATURE_MMTEL;
+ public static final int IMS_FEATURE_RCS = ImsFeature.FEATURE_RCS;
+
+ private static final String PROVISIONING_FILE_NAME_PREF = "imsprovisioningstatus_";
+ private static final String PREF_PROVISION_IMS_MMTEL_PREFIX = "provision_ims_mmtel_";
+
+ private Context mContext;
+ private SharedPreferences mTelephonySharedPreferences;
+ // key : sub Id, value : read from sub Id's xml and it's in-memory cache
+ private SparseArray<PersistableBundle> mSubIdBundleArray = new SparseArray<>();
+ private final Object mLock = new Object();
+
+ public ImsProvisioningLoader(Context context) {
+ mContext = context;
+ mTelephonySharedPreferences =
+ PreferenceManager.getDefaultSharedPreferences(context);
+ }
+
+ /**
+ * Get Ims feature provisioned status in storage
+ */
+ public int getProvisioningStatus(int subId, @ImsFeature.FeatureType int imsFeature,
+ int capability, @ImsRegistrationImplBase.ImsRegistrationTech int tech) {
+ initCache(subId);
+ return getImsProvisioningStatus(subId, imsFeature, tech,
+ capability);
+ }
+
+ /**
+ * Set Ims feature provisioned status in storage
+ */
+ public boolean setProvisioningStatus(int subId, @ImsFeature.FeatureType int imsFeature,
+ int capability, @ImsRegistrationImplBase.ImsRegistrationTech int tech,
+ boolean isProvisioned) {
+ initCache(subId);
+ return setImsFeatureProvisioning(subId, imsFeature, tech, capability,
+ isProvisioned);
+ }
+
+ private boolean isFileExist(int subId) {
+ File file = new File(mContext.getFilesDir(), getFileName(subId));
+ return file.exists();
+ }
+
+ private void initCache(int subId) {
+ synchronized (mLock) {
+ PersistableBundle subIdBundle = mSubIdBundleArray.get(subId, null);
+ if (subIdBundle != null) {
+ // initCache() has already been called for the subId
+ return;
+ }
+ if (isFileExist(subId)) {
+ subIdBundle = readSubIdBundleFromXml(subId);
+ } else {
+ // It should read the MMTEL capability cache as part of shared prefs and migrate
+ // over any configs for UT.
+ final int[] regTech = {ImsRegistrationImplBase.REGISTRATION_TECH_LTE,
+ ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN,
+ ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM,
+ ImsRegistrationImplBase.REGISTRATION_TECH_NR};
+ subIdBundle = new PersistableBundle();
+ for (int tech : regTech) {
+ int UtProvisioningStatus = getUTProvisioningStatus(subId, tech);
+ if (STATUS_PROVISIONED == UtProvisioningStatus) {
+ setProvisioningStatusToSubIdBundle(ImsFeature.FEATURE_MMTEL, tech,
+ MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT, subIdBundle,
+ UtProvisioningStatus);
+ }
+ }
+ saveSubIdBundleToXml(subId, subIdBundle);
+ }
+ mSubIdBundleArray.put(subId, subIdBundle);
+ }
+ }
+
+ private int getImsProvisioningStatus(int subId, int imsFeature, int tech, int capability) {
+ PersistableBundle subIdBundle = null;
+ synchronized (mLock) {
+ subIdBundle = mSubIdBundleArray.get(subId, null);
+ }
+
+ return getProvisioningStatusFromSubIdBundle(imsFeature, tech,
+ capability, subIdBundle);
+ }
+
+ private boolean setImsFeatureProvisioning(int subId, int imsFeature, int tech, int capability,
+ boolean isProvisioned) {
+ synchronized (mLock) {
+ int preValue = getImsProvisioningStatus(subId, imsFeature, tech, capability);
+ int newValue = isProvisioned ? STATUS_PROVISIONED : STATUS_NOT_PROVISIONED;
+ if (preValue == newValue) {
+ logd("already stored provisioning status " + isProvisioned + " ImsFeature "
+ + imsFeature + " tech " + tech + " capa " + capability);
+ return false;
+ }
+
+ PersistableBundle subIdBundle = mSubIdBundleArray.get(subId, null);
+ setProvisioningStatusToSubIdBundle(imsFeature, tech, capability, subIdBundle,
+ newValue);
+ saveSubIdBundleToXml(subId, subIdBundle);
+ }
+ return true;
+ }
+
+ private int getProvisioningStatusFromSubIdBundle(int imsFeature, int tech,
+ int capability, PersistableBundle subIdBundle) {
+ // If it doesn't exist in xml, return STATUS_NOT_SET
+ if (subIdBundle == null || subIdBundle.isEmpty()) {
+ logd("xml is empty");
+ return STATUS_NOT_SET;
+ }
+
+ PersistableBundle regTechBundle = subIdBundle.getPersistableBundle(
+ String.valueOf(imsFeature));
+ if (regTechBundle == null) {
+ logd("ImsFeature " + imsFeature + " is not exist in xml");
+ return STATUS_NOT_SET;
+ }
+
+ PersistableBundle capabilityBundle = regTechBundle.getPersistableBundle(
+ String.valueOf(tech));
+ if (capabilityBundle == null) {
+ logd("RegistrationTech " + tech + " is not exist in xml");
+ return STATUS_NOT_SET;
+ }
+
+ return getIntValueFromBundle(String.valueOf(capability), capabilityBundle);
+ }
+
+ private void setProvisioningStatusToSubIdBundle(int imsFeature, int tech,
+ int capability, PersistableBundle subIdBundle, int newStatus) {
+ PersistableBundle regTechBundle = subIdBundle.getPersistableBundle(
+ String.valueOf(imsFeature));
+ if (regTechBundle == null) {
+ regTechBundle = new PersistableBundle();
+ subIdBundle.putPersistableBundle(String.valueOf(imsFeature), regTechBundle);
+ }
+
+ PersistableBundle capabilityBundle = regTechBundle.getPersistableBundle(
+ String.valueOf(tech));
+ if (capabilityBundle == null) {
+ capabilityBundle = new PersistableBundle();
+ regTechBundle.putPersistableBundle(String.valueOf(tech), capabilityBundle);
+ }
+
+ capabilityBundle.putInt(String.valueOf(capability), newStatus);
+ }
+
+ // Default value is STATUS_NOT_SET
+ private int getIntValueFromBundle(String key, PersistableBundle bundle) {
+ return bundle.getInt(key, STATUS_NOT_SET);
+ }
+
+ // Return subIdBundle from imsprovisioningstatus_{subId}.xml
+ private PersistableBundle readSubIdBundleFromXml(int subId) {
+ String fileName = getFileName(subId);
+
+ PersistableBundle subIdBundles = new PersistableBundle();
+ File file = null;
+ FileInputStream inFile = null;
+ synchronized (mLock) {
+ try {
+ file = new File(mContext.getFilesDir(), fileName);
+ inFile = new FileInputStream(file);
+ subIdBundles = PersistableBundle.readFromStream(inFile);
+ inFile.close();
+ } catch (FileNotFoundException e) {
+ logd(e.toString());
+ } catch (IOException e) {
+ loge(e.toString());
+ } catch (RuntimeException e) {
+ loge(e.toString());
+ }
+ }
+
+ return subIdBundles;
+ }
+
+ private void saveSubIdBundleToXml(int subId, PersistableBundle subIdBundle) {
+ String fileName = getFileName(subId);
+
+ if (subIdBundle == null || subIdBundle.isEmpty()) {
+ logd("subIdBundle is empty");
+ return;
+ }
+
+ FileOutputStream outFile = null;
+ synchronized (mLock) {
+ try {
+ outFile = new FileOutputStream(new File(mContext.getFilesDir(), fileName));
+ subIdBundle.writeToStream(outFile);
+ outFile.flush();
+ outFile.close();
+ } catch (IOException e) {
+ loge(e.toString());
+ } catch (RuntimeException e) {
+ loge(e.toString());
+ }
+ }
+ }
+
+ private int getUTProvisioningStatus(int subId, int tech) {
+ return getMmTelCapabilityProvisioningBitfield(subId, tech) > 0 ? STATUS_PROVISIONED
+ : STATUS_NOT_SET;
+ }
+
+ /**
+ * @return the bitfield containing the MmTel provisioning for the provided subscription and
+ * technology. The bitfield should mirror the bitfield defined by
+ * {@link MmTelFeature.MmTelCapabilities.MmTelCapability}.
+ */
+ private int getMmTelCapabilityProvisioningBitfield(int subId, int tech) {
+ String key = getMmTelProvisioningKey(subId, tech);
+ // Default is no capabilities are provisioned.
+ return mTelephonySharedPreferences.getInt(key, 0 /*default*/);
+ }
+
+ private String getMmTelProvisioningKey(int subId, int tech) {
+ // Resulting key is provision_ims_mmtel_{subId}_{tech}
+ return PREF_PROVISION_IMS_MMTEL_PREFIX + subId + "_" + tech;
+ }
+
+ private String getFileName(int subId) {
+ // Resulting name is imsprovisioningstatus_{subId}.xml
+ return PROVISIONING_FILE_NAME_PREF + subId + ".xml";
+ }
+
+ @VisibleForTesting
+ void clear() {
+ synchronized (mLock) {
+ mSubIdBundleArray.clear();
+ }
+ }
+
+ @VisibleForTesting
+ void setProvisioningToXml(int subId, PersistableBundle subIdBundle,
+ String[] infoArray) {
+ for (String info : infoArray) {
+ String[] paramArray = info.split(",");
+ setProvisioningStatusToSubIdBundle(Integer.valueOf(paramArray[0]),
+ Integer.valueOf(paramArray[1]), Integer.valueOf(paramArray[2]),
+ subIdBundle, Integer.valueOf(paramArray[3]));
+ }
+ saveSubIdBundleToXml(subId, subIdBundle);
+ }
+
+ private void loge(String contents) {
+ Log.e(LOG_TAG, contents);
+ }
+
+ private void logd(String contents) {
+ Log.d(LOG_TAG, contents);
+ }
+
+}
diff --git a/tests/src/com/android/phone/ImsProvisioningLoaderTest.java b/tests/src/com/android/phone/ImsProvisioningLoaderTest.java
new file mode 100644
index 0000000..61cab1d
--- /dev/null
+++ b/tests/src/com/android/phone/ImsProvisioningLoaderTest.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone;
+
+import static junit.framework.Assert.assertEquals;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doReturn;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.PersistableBundle;
+import android.telephony.ims.feature.MmTelFeature;
+import android.telephony.ims.feature.RcsFeature;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+/**
+ * Unit Test for ImsProvisioningLoader.
+ */
+public class ImsProvisioningLoaderTest {
+ private static final String LOG_TAG = ImsProvisioningLoaderTest.class.getSimpleName();
+
+ private static final int IMS_FEATURE_MMTEL = ImsProvisioningLoader.IMS_FEATURE_MMTEL;
+ private static final int IMS_FEATURE_RCS = ImsProvisioningLoader.IMS_FEATURE_RCS;
+
+ private static final int TECH_LTE = ImsRegistrationImplBase.REGISTRATION_TECH_LTE;
+ private static final int TECH_IWLAN = ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN;
+ private static final int TECH_NEW = Integer.MAX_VALUE;
+
+ private static final int CAPA_VOICE = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE;
+ private static final int CAPA_VIDEO = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO;
+ private static final int CAPA_UT = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT;
+ private static final int CAPA_PRESENCE =
+ RcsFeature.RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE;
+ private static final int CAPA_NEW = Integer.MAX_VALUE;
+
+ private static final int STATUS_NOT_PROVISIONED = ImsProvisioningLoader.STATUS_NOT_PROVISIONED;
+ private static final int STATUS_PROVISIONED = ImsProvisioningLoader.STATUS_PROVISIONED;
+
+ private static final int SUB_ID_1 = 111111;
+ private static final int SUB_ID_2 = 222222;
+
+ @Mock
+ Context mContext;
+ @Mock
+ SharedPreferences mSharedPreferences;
+ private ImsProvisioningLoader mImsProvisioningLoader;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ doReturn(mSharedPreferences).when(mContext).getSharedPreferences(anyString(), anyInt());
+ doReturn(InstrumentationRegistry.getTargetContext().getFilesDir()).when(
+ mContext).getFilesDir();
+
+ mImsProvisioningLoader = new ImsProvisioningLoader(mContext);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (mImsProvisioningLoader != null) {
+ mImsProvisioningLoader.clear();
+ }
+ deleteXml(SUB_ID_1, mContext);
+ deleteXml(SUB_ID_2, mContext);
+ }
+
+ @Test
+ @SmallTest
+ public void testSetProvisioningStatus_ExistFeature() {
+ // Set MMTEL IWLAN VOICE to STATUS_PROVISIONED
+ String[] info =
+ new String[]{IMS_FEATURE_MMTEL + "," + TECH_IWLAN + "," + CAPA_VOICE + "," + getInt(
+ true)};
+ mImsProvisioningLoader.setProvisioningToXml(SUB_ID_1, new PersistableBundle(), info);
+
+ int curValue = mImsProvisioningLoader.getProvisioningStatus(SUB_ID_1, IMS_FEATURE_MMTEL,
+ CAPA_VOICE, TECH_IWLAN);
+ assertEquals(getXmlContents(SUB_ID_1), getInt(true), curValue);
+
+ // Change MMTEL IWLAN VOICE provisioning status
+ boolean saveResult = mImsProvisioningLoader.setProvisioningStatus(SUB_ID_1,
+ IMS_FEATURE_MMTEL, CAPA_VOICE, TECH_IWLAN, false);
+ curValue = mImsProvisioningLoader.getProvisioningStatus(SUB_ID_1,
+ IMS_FEATURE_MMTEL, CAPA_VOICE, TECH_IWLAN);
+ assertEquals(getXmlContents(SUB_ID_1), true, saveResult);
+ assertEquals(getXmlContents(SUB_ID_1), getInt(false), curValue);
+
+ // If set to the same provisioning status, don't save it.
+ saveResult = mImsProvisioningLoader.setProvisioningStatus(SUB_ID_1,
+ IMS_FEATURE_MMTEL, CAPA_VOICE, TECH_IWLAN, false);
+ curValue = mImsProvisioningLoader.getProvisioningStatus(SUB_ID_1,
+ IMS_FEATURE_MMTEL, CAPA_VOICE, TECH_IWLAN);
+ assertEquals(getXmlContents(SUB_ID_1), false, saveResult);
+ assertEquals(getXmlContents(SUB_ID_1), getInt(false), curValue);
+ }
+
+ @Test
+ @SmallTest
+ public void testSetProvisioningStatus_NewFeature() {
+ // Set new capability
+ // Return true as a result to setProvisioningStatus()
+ boolean saveResult = mImsProvisioningLoader.setProvisioningStatus(SUB_ID_1,
+ IMS_FEATURE_MMTEL, CAPA_NEW, TECH_LTE, true);
+ int curValue = mImsProvisioningLoader.getProvisioningStatus(SUB_ID_1,
+ IMS_FEATURE_MMTEL, CAPA_NEW, TECH_LTE);
+ assertEquals(getXmlContents(SUB_ID_1), true, saveResult);
+ assertEquals(getXmlContents(SUB_ID_1), getInt(true), curValue);
+
+ // Set new tech
+ saveResult = mImsProvisioningLoader.setProvisioningStatus(SUB_ID_1,
+ IMS_FEATURE_MMTEL, CAPA_VOICE, TECH_NEW, false);
+ curValue = mImsProvisioningLoader.getProvisioningStatus(SUB_ID_1,
+ IMS_FEATURE_MMTEL, CAPA_VOICE, TECH_NEW);
+ assertEquals(getXmlContents(SUB_ID_1), true, saveResult);
+ assertEquals(getXmlContents(SUB_ID_1), getInt(false), curValue);
+ }
+
+ @Test
+ @SmallTest
+ public void testSetProvisioningStatus_DifferentSim() {
+ // Check whether the provisioning status does not change even if SIM is changed
+ // Sub id 2, set provisioning status
+ boolean prevValue = getBooleanFromProvisioningStatus(SUB_ID_2,
+ IMS_FEATURE_RCS, CAPA_PRESENCE, TECH_IWLAN);
+ boolean saveResult = mImsProvisioningLoader.setProvisioningStatus(
+ SUB_ID_2, IMS_FEATURE_RCS, CAPA_PRESENCE, TECH_IWLAN, !prevValue);
+ int curValue = mImsProvisioningLoader.getProvisioningStatus(SUB_ID_2,
+ IMS_FEATURE_RCS, CAPA_PRESENCE, TECH_IWLAN);
+ assertEquals(getXmlContents(SUB_ID_2), true, saveResult);
+ assertEquals(getXmlContents(SUB_ID_2), getInt(!prevValue), curValue);
+
+ // Sub id 1, set other provisioned status
+ mImsProvisioningLoader.setProvisioningStatus(
+ SUB_ID_1, IMS_FEATURE_RCS, CAPA_PRESENCE, TECH_IWLAN, prevValue);
+
+ // Sub id 2, check the previous provisioning status isn't changed
+ curValue = mImsProvisioningLoader.getProvisioningStatus(SUB_ID_2,
+ IMS_FEATURE_RCS, CAPA_PRESENCE, TECH_IWLAN);
+ assertEquals(getXmlContents(SUB_ID_2), getInt(!prevValue), curValue);
+ }
+
+ @Test
+ @SmallTest
+ public void testGetProvisioningStatus_UtProvisioningStatusIsExistInPref() {
+ // Ut provisioning status exists in preference
+ doReturn(1).when(mSharedPreferences).getInt(anyString(), anyInt());
+ int curValue = mImsProvisioningLoader.getProvisioningStatus(SUB_ID_1,
+ IMS_FEATURE_MMTEL, CAPA_UT, TECH_LTE);
+ assertEquals(getXmlContents(SUB_ID_1), getInt(true), curValue);
+ }
+
+ @Test
+ @SmallTest
+ public void testGetProvisioningStatus_ExistXml() {
+ // Set MMTEL LTE VOICE to STATUS_PROVISIONED, MMTEL LTE VIDEO to STATUS_NOT_PROVISIONED
+ String[] info =
+ new String[]{IMS_FEATURE_MMTEL + "," + TECH_LTE + "," + CAPA_VOICE + "," + getInt(
+ true),
+ IMS_FEATURE_MMTEL + "," + TECH_LTE + "," + CAPA_VIDEO + "," + getInt(
+ false)};
+ mImsProvisioningLoader.setProvisioningToXml(SUB_ID_1, new PersistableBundle(), info);
+
+ int curValue = mImsProvisioningLoader.getProvisioningStatus(SUB_ID_1,
+ IMS_FEATURE_MMTEL, CAPA_VOICE, TECH_LTE);
+ assertEquals(getXmlContents(SUB_ID_1), getInt(true), curValue);
+
+ curValue = mImsProvisioningLoader.getProvisioningStatus(SUB_ID_1,
+ IMS_FEATURE_MMTEL, CAPA_VIDEO, TECH_LTE);
+ assertEquals(getXmlContents(SUB_ID_1), getInt(false), curValue);
+ }
+
+ private boolean getBooleanFromProvisioningStatus(int subId, int imsFeature, int capa,
+ int tech) {
+ // Return provisioning status to bool
+ return mImsProvisioningLoader.getProvisioningStatus(
+ subId, imsFeature, capa, tech) == STATUS_PROVISIONED ? true
+ : false;
+ }
+
+ private int getInt(boolean isProvisioned) {
+ return isProvisioned ? STATUS_PROVISIONED : STATUS_NOT_PROVISIONED;
+ }
+
+ private void deleteXml(int subId, Context context) {
+ String fileName = getFileName(subId);
+ File file = null;
+ try {
+ file = new File(context.getFilesDir(), fileName);
+ } catch (Exception e) {
+ logd(e.toString());
+ }
+ file.delete();
+ }
+
+ private String getXmlContents(int subId) {
+ String fileName = getFileName(subId);
+
+ File file = null;
+ FileInputStream inFile = null;
+ StringBuilder readString = new StringBuilder();
+ readString.append("file name " + fileName + "\n");
+ byte[] buffer = new byte[1024];
+ int n = 0;
+ try {
+ file = new File(mContext.getFilesDir(), fileName);
+ inFile = new FileInputStream(file);
+ while ((n = inFile.read(buffer)) != -1) {
+ readString.append(new String(buffer, 0, n));
+ }
+ inFile.close();
+ } catch (FileNotFoundException e) {
+ logd(e.toString());
+
+ } catch (IOException e) {
+ logd(e.toString());
+ }
+ return readString.toString();
+ }
+
+ private String getFileName(int subId) {
+ // Resulting name is imsprovisioningstatus_{subId}.xml
+ return "imsprovisioningstatus_" + subId + ".xml";
+ }
+
+ private static void logd(String contents) {
+ Log.d(LOG_TAG, contents);
+ }
+
+}