Merge "Trigger silent redial under alerting state"
diff --git a/src/java/com/android/internal/telephony/NetworkTypeController.java b/src/java/com/android/internal/telephony/NetworkTypeController.java
index 5007c93..14b38da 100644
--- a/src/java/com/android/internal/telephony/NetworkTypeController.java
+++ b/src/java/com/android/internal/telephony/NetworkTypeController.java
@@ -23,7 +23,6 @@
import android.os.AsyncResult;
import android.os.Message;
import android.os.PersistableBundle;
-import android.provider.Settings;
import android.telephony.AccessNetworkConstants;
import android.telephony.Annotation;
import android.telephony.CarrierConfigManager;
@@ -89,14 +88,14 @@
private static final int EVENT_SECONDARY_TIMER_EXPIRED = 9;
private static final int EVENT_RADIO_OFF_OR_UNAVAILABLE = 10;
private static final int EVENT_PREFERRED_NETWORK_MODE_CHANGED = 11;
- private static final int EVENT_INIITIALIZE = 12;
+ private static final int EVENT_INITIALIZE = 12;
// events that don't reset the timer
private static final int[] ALL_EVENTS = { EVENT_DATA_RAT_CHANGED, EVENT_NR_STATE_CHANGED,
EVENT_NR_FREQUENCY_CHANGED, EVENT_PHYSICAL_LINK_STATE_CHANGED,
EVENT_PHYSICAL_CHANNEL_CONFIG_NOTIF_CHANGED, EVENT_PRIMARY_TIMER_EXPIRED,
EVENT_SECONDARY_TIMER_EXPIRED};
- private static final String[] sEvents = new String[EVENT_PREFERRED_NETWORK_MODE_CHANGED + 1];
+ private static final String[] sEvents = new String[EVENT_INITIALIZE + 1];
static {
sEvents[EVENT_UPDATE] = "EVENT_UPDATE";
sEvents[EVENT_QUIT] = "EVENT_QUIT";
@@ -111,11 +110,11 @@
sEvents[EVENT_SECONDARY_TIMER_EXPIRED] = "EVENT_SECONDARY_TIMER_EXPIRED";
sEvents[EVENT_RADIO_OFF_OR_UNAVAILABLE] = "EVENT_RADIO_OFF_OR_UNAVAILABLE";
sEvents[EVENT_PREFERRED_NETWORK_MODE_CHANGED] = "EVENT_PREFERRED_NETWORK_MODE_CHANGED";
+ sEvents[EVENT_INITIALIZE] = "EVENT_INITIALIZE";
}
private final Phone mPhone;
private final DisplayInfoController mDisplayInfoController;
- private final SettingsObserver mSettingsObserver;
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -151,7 +150,6 @@
super(TAG, displayInfoController);
mPhone = phone;
mDisplayInfoController = displayInfoController;
- mSettingsObserver = new SettingsObserver(mPhone.getContext(), getHandler());
mOverrideNetworkType = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
mIsPhysicalChannelConfigOn = true;
addState(mDefaultState);
@@ -161,7 +159,7 @@
addState(mNrConnectedState, mDefaultState);
setInitialState(mDefaultState);
start();
- sendMessage(EVENT_INIITIALIZE);
+ sendMessage(EVENT_INITIALIZE);
}
/**
@@ -175,6 +173,8 @@
private void registerForAllEvents() {
mPhone.registerForRadioOffOrNotAvailable(getHandler(),
EVENT_RADIO_OFF_OR_UNAVAILABLE, null);
+ mPhone.registerForPreferredNetworkTypeChanged(getHandler(),
+ EVENT_PREFERRED_NETWORK_MODE_CHANGED, null);
mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged(
AccessNetworkConstants.TRANSPORT_TYPE_WWAN, getHandler(),
EVENT_DATA_RAT_CHANGED, null);
@@ -190,19 +190,17 @@
IntentFilter filter = new IntentFilter();
filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
- mSettingsObserver.observe(Settings.Global.getUriFor(Settings.Global.PREFERRED_NETWORK_MODE),
- EVENT_PREFERRED_NETWORK_MODE_CHANGED);
}
private void unRegisterForAllEvents() {
mPhone.unregisterForRadioOffOrNotAvailable(getHandler());
+ mPhone.unregisterForPreferredNetworkTypeChanged(getHandler());
mPhone.getServiceStateTracker().unregisterForDataRegStateOrRatChanged(
AccessNetworkConstants.TRANSPORT_TYPE_WWAN, getHandler());
mPhone.getServiceStateTracker().unregisterForNrStateChanged(getHandler());
mPhone.getServiceStateTracker().unregisterForNrFrequencyChanged(getHandler());
mPhone.getDeviceStateMonitor().unregisterForPhysicalChannelConfigNotifChanged(getHandler());
mPhone.getContext().unregisterReceiver(mIntentReceiver);
- mSettingsObserver.unobserve();
}
private void parseCarrierConfigs() {
@@ -446,7 +444,7 @@
unRegisterForAllEvents();
quit();
break;
- case EVENT_INIITIALIZE:
+ case EVENT_INITIALIZE:
// The reason that we do it here is because some of the works below requires
// other modules (e.g. DcTracker, ServiceStateTracker), which is not created
// yet when NetworkTypeController is created.
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index 9ae3abb..2d66e37 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -405,6 +405,8 @@
private final RegistrantList mOtaspRegistrants = new RegistrantList();
+ private final RegistrantList mPreferredNetworkTypeRegistrants = new RegistrantList();
+
protected Registrant mPostDialHandler;
protected final LocalLog mLocalLog;
@@ -2249,6 +2251,7 @@
+ " filteredType = " + filteredType);
mCi.setPreferredNetworkType(filteredType, response);
+ mPreferredNetworkTypeRegistrants.notifyRegistrants();
}
/**
@@ -2261,6 +2264,27 @@
}
/**
+ * Register for preferred network type changes
+ *
+ * @param h Handler that receives the notification message.
+ * @param what User-defined message code.
+ * @param obj User object.
+ */
+ public void registerForPreferredNetworkTypeChanged(Handler h, int what, Object obj) {
+ checkCorrectThread(h);
+ mPreferredNetworkTypeRegistrants.addUnique(h, what, obj);
+ }
+
+ /**
+ * Unregister for preferred network type changes.
+ *
+ * @param h Handler that should be unregistered.
+ */
+ public void unregisterForPreferredNetworkTypeChanged(Handler h) {
+ mPreferredNetworkTypeRegistrants.remove(h);
+ }
+
+ /**
* Get the cached value of the preferred network type setting
*/
public int getCachedPreferredNetworkType() {
diff --git a/src/java/com/android/internal/telephony/SubscriptionController.java b/src/java/com/android/internal/telephony/SubscriptionController.java
index d30f95f..64d828b 100644
--- a/src/java/com/android/internal/telephony/SubscriptionController.java
+++ b/src/java/com/android/internal/telephony/SubscriptionController.java
@@ -577,16 +577,18 @@
* @hide
*/
public SubscriptionInfo getSubscriptionInfo(int subId) {
- // check cache for active subscriptions first, before querying db
- for (SubscriptionInfo subInfo : mCacheActiveSubInfoList) {
- if (subInfo.getSubscriptionId() == subId) {
- return subInfo;
+ synchronized (mSubInfoListLock) {
+ // check cache for active subscriptions first, before querying db
+ for (SubscriptionInfo subInfo : mCacheActiveSubInfoList) {
+ if (subInfo.getSubscriptionId() == subId) {
+ return subInfo;
+ }
}
- }
- // check cache for opportunistic subscriptions too, before querying db
- for (SubscriptionInfo subInfo : mCacheOpportunisticSubInfoList) {
- if (subInfo.getSubscriptionId() == subId) {
- return subInfo;
+ // check cache for opportunistic subscriptions too, before querying db
+ for (SubscriptionInfo subInfo : mCacheOpportunisticSubInfoList) {
+ if (subInfo.getSubscriptionId() == subId) {
+ return subInfo;
+ }
}
}
@@ -1364,12 +1366,14 @@
// validate the given info - does it exist in the active subscription list
int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
int slotIndex = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
- for (SubscriptionInfo info : mCacheActiveSubInfoList) {
- if ((info.getSubscriptionType() == subscriptionType)
- && info.getIccId().equalsIgnoreCase(uniqueId)) {
- subId = info.getSubscriptionId();
- slotIndex = info.getSimSlotIndex();
- break;
+ synchronized (mSubInfoListLock) {
+ for (SubscriptionInfo info : mCacheActiveSubInfoList) {
+ if ((info.getSubscriptionType() == subscriptionType)
+ && info.getIccId().equalsIgnoreCase(uniqueId)) {
+ subId = info.getSubscriptionId();
+ slotIndex = info.getSimSlotIndex();
+ break;
+ }
}
}
if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
@@ -2608,11 +2612,13 @@
}
private boolean isSubscriptionVisible(int subId) {
- for (SubscriptionInfo info : mCacheOpportunisticSubInfoList) {
- if (info.getSubscriptionId() == subId) {
- // If group UUID is null, it's stand alone opportunistic profile. So it's visible.
- // otherwise, it's bundled opportunistic profile, and is not visible.
- return info.getGroupUuid() == null;
+ synchronized (mSubInfoListLock) {
+ for (SubscriptionInfo info : mCacheOpportunisticSubInfoList) {
+ if (info.getSubscriptionId() == subId) {
+ // If group UUID is null, it's stand alone opportunistic profile. So it's
+ // visible. Otherwise, it's bundled opportunistic profile, and is not visible.
+ return info.getGroupUuid() == null;
+ }
}
}
@@ -3898,9 +3904,11 @@
private boolean shouldDisableSubGroup(ParcelUuid groupUuid) {
if (groupUuid == null) return false;
- for (SubscriptionInfo activeInfo : mCacheActiveSubInfoList) {
- if (!activeInfo.isOpportunistic() && groupUuid.equals(activeInfo.getGroupUuid())) {
- return false;
+ synchronized (mSubInfoListLock) {
+ for (SubscriptionInfo activeInfo : mCacheActiveSubInfoList) {
+ if (!activeInfo.isOpportunistic() && groupUuid.equals(activeInfo.getGroupUuid())) {
+ return false;
+ }
}
}
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
index bea9a00..8663961 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
@@ -1575,7 +1575,7 @@
}
for (InetAddress gateway : response.getGatewayAddresses()) {
- int mtu = gateway instanceof java.net.Inet6Address ? response.getMtuV6()
+ int mtu = gateway instanceof java.net.Inet6Address ? response.getMtuV6()
: response.getMtuV4();
// Allow 0.0.0.0 or :: as a gateway;
// this indicates a point-to-point interface.
@@ -1877,10 +1877,8 @@
DataConnection.this, mTransportType);
NetworkInfo networkInfo = mHandoverSourceNetworkAgent.getNetworkInfo();
if (networkInfo != null) {
- networkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED,
- "dangling clean up", networkInfo.getExtraInfo());
- mHandoverSourceNetworkAgent.sendNetworkInfo(networkInfo,
- DataConnection.this);
+ log("Cleared dangling network agent. " + mHandoverSourceNetworkAgent);
+ mHandoverSourceNetworkAgent.unregister(DataConnection.this);
} else {
String str = "Failed to get network info.";
loge(str);
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java b/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java
index c911dfd..5a15fab 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java
@@ -17,6 +17,7 @@
package com.android.internal.telephony.dataconnection;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.net.KeepalivePacketData;
import android.net.LinkProperties;
import android.net.NattKeepalivePacketData;
@@ -32,6 +33,7 @@
import android.telephony.AccessNetworkConstants.TransportType;
import android.telephony.AnomalyReporter;
import android.telephony.TelephonyManager;
+import android.util.ArrayMap;
import android.util.LocalLog;
import android.util.SparseArray;
@@ -45,8 +47,8 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.time.Duration;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Map;
+import java.util.Objects;
import java.util.UUID;
/**
@@ -62,6 +64,8 @@
public class DcNetworkAgent extends NetworkAgent {
private final String mTag;
+ private final int mId;
+
private Phone mPhone;
private int mTransportType;
@@ -76,10 +80,8 @@
private NetworkInfo mNetworkInfo;
- // For debugging IMS redundant network agent issue.
- private static List<DcNetworkAgent> sNetworkAgents = new ArrayList<>();
-
- private static int sRedundantTimes = 0;
+ // For interface duplicate detection. Key is the net id, value is the interface name in string.
+ private static Map<Integer, String> sInterfaceNames = new ArrayMap<>();
DcNetworkAgent(DataConnection dc, Phone phone, NetworkInfo ni, int score,
NetworkAgentConfig config, NetworkProvider networkProvider, int transportType) {
@@ -87,36 +89,38 @@
dc.getNetworkCapabilities(), dc.getLinkProperties(), score, config,
networkProvider);
register();
- mTag = "DcNetworkAgent" + "-" + getNetwork().netId;
+ mId = getNetwork().netId;
+ mTag = "DcNetworkAgent" + "-" + mId;
mPhone = phone;
mNetworkCapabilities = dc.getNetworkCapabilities();
mTransportType = transportType;
mDataConnection = dc;
mNetworkInfo = new NetworkInfo(ni);
setLegacyExtraInfo(ni.getExtraInfo());
- // TODO: Remove after b/151487565 is fixed.
- sNetworkAgents.add(this);
- checkRedundantIms();
- logd(mTag + " created for data connection " + dc.getName());
+ if (dc.getLinkProperties() != null) {
+ checkDuplicateInterface(mId, dc.getLinkProperties().getInterfaceName());
+ logd("created for data connection " + dc.getName() + ", "
+ + dc.getLinkProperties().getInterfaceName());
+ } else {
+ loge("The connection does not have a valid link properties.");
+ }
}
- // This is a temp code to catch the multiple IMS network agents issue.
- // TODO: Remove after b/151487565 is fixed.
- private void checkRedundantIms() {
- if (sNetworkAgents.stream()
- .filter(n -> n.mNetworkCapabilities.hasCapability(
- NetworkCapabilities.NET_CAPABILITY_IMS))
- .count() > 1) {
- sRedundantTimes++;
- if (sRedundantTimes == 5) { // When it occurs 5 times.
- String message = "Multiple IMS network agents detected.";
- log(message);
+ private void checkDuplicateInterface(int netId, @Nullable String interfaceName) {
+ for (Map.Entry<Integer, String> entry: sInterfaceNames.entrySet()) {
+ if (Objects.equals(interfaceName, entry.getValue())) {
+ String message = "Duplicate interface " + interfaceName
+ + " is detected. DcNetworkAgent-" + entry.getKey()
+ + " already used this interface name.";
+ loge(message);
// Using fixed UUID to avoid duplicate bugreport notification
AnomalyReporter.reportAnomaly(
- UUID.fromString("a5cf4881-75ae-4129-a25d-71bc4293f493"),
+ UUID.fromString("02f3d3f6-4613-4415-b6cb-8d92c8a938a6"),
message);
+ return;
}
}
+ sInterfaceNames.put(netId, interfaceName);
}
/**
@@ -147,7 +151,7 @@
loge("releaseOwnership called on no-owner DcNetworkAgent!");
return;
} else if (mDataConnection != dc) {
- log("releaseOwnership: This agent belongs to "
+ loge("releaseOwnership: This agent belongs to "
+ mDataConnection.getName() + ", ignored the request from " + dc.getName());
return;
}
@@ -256,9 +260,11 @@
* @param linkProperties The link properties
* @param dc The data connection that invokes this method.
*/
- public synchronized void sendLinkProperties(LinkProperties linkProperties,
+ public synchronized void sendLinkProperties(@NonNull LinkProperties linkProperties,
DataConnection dc) {
if (!isOwned(dc, "sendLinkProperties")) return;
+
+ sInterfaceNames.put(mId, dc.getLinkProperties().getInterfaceName());
sendLinkProperties(linkProperties);
}
@@ -274,6 +280,19 @@
}
/**
+ * Unregister the network agent from connectivity service.
+ *
+ * @param dc The data connection that invokes this method.
+ */
+ public synchronized void unregister(DataConnection dc) {
+ if (!isOwned(dc, "unregister")) return;
+
+ logd("Unregister from connectivity service. " + sInterfaceNames.get(mId) + " removed.");
+ sInterfaceNames.remove(mId);
+ super.unregister();
+ }
+
+ /**
* Set the network info.
*
* @param networkInfo The network info.
@@ -292,9 +311,7 @@
}
if ((oldState == NetworkInfo.State.SUSPENDED || oldState == NetworkInfo.State.CONNECTED)
&& state == NetworkInfo.State.DISCONNECTED) {
- logd("Unregister from connectivity service");
- sNetworkAgents.remove(this);
- unregister();
+ unregister(dc);
}
mNetworkInfo = new NetworkInfo(networkInfo);
}
@@ -337,11 +354,13 @@
@Override
public String toString() {
- return "DcNetworkAgent:"
+ return "DcNetworkAgent-"
+ + mId
+ " mDataConnection="
+ ((mDataConnection != null) ? mDataConnection.getName() : null)
+ " mTransportType="
+ AccessNetworkConstants.transportTypeToString(mTransportType)
+ + " " + ((mDataConnection != null) ? mDataConnection.getLinkProperties() : null)
+ " mNetworkCapabilities=" + mNetworkCapabilities;
}
diff --git a/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
index 8cfde1f..3b55008 100644
--- a/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
+++ b/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
@@ -59,7 +59,6 @@
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
-import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
@@ -80,7 +79,9 @@
private static final String EMERGENCY_NUMBER_DB_OTA_FILE_NAME = "emergency_number_db";
private static final String EMERGENCY_NUMBER_DB_OTA_FILE_PATH =
"misc/emergencynumberdb/" + EMERGENCY_NUMBER_DB_OTA_FILE_NAME;
- private FileInputStream mEmergencyNumberDbOtaFileInputStream = null;
+
+ /** Used for storing overrided (non-default) OTA database file path */
+ private ParcelFileDescriptor mOverridedOtaDbParcelFileDescriptor = null;
/** @hide */
public static boolean DBG = false;
@@ -170,13 +171,6 @@
mPhone = phone;
mCi = ci;
- try {
- mEmergencyNumberDbOtaFileInputStream = new FileInputStream(
- new File(Environment.getDataDirectory(), EMERGENCY_NUMBER_DB_OTA_FILE_PATH));
- } catch (FileNotFoundException ex) {
- loge("Initialize ota emergency database file input failure: " + ex);
- }
-
if (mPhone != null) {
CarrierConfigManager configMgr = (CarrierConfigManager)
mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
@@ -488,6 +482,7 @@
}
private int cacheOtaEmergencyNumberDatabase() {
+ FileInputStream fileInputStream = null;
BufferedInputStream inputStream = null;
ProtobufEccData.AllInfo allEccMessages = null;
int otaDatabaseVersion = INVALID_DATABASE_VERSION;
@@ -496,11 +491,16 @@
List<EmergencyNumber> updatedOtaEmergencyNumberList = new ArrayList<>();
try {
// If OTA File partition is not available, try to reload the default one.
- if (mEmergencyNumberDbOtaFileInputStream == null) {
- mEmergencyNumberDbOtaFileInputStream = new FileInputStream(
- new File(Environment.getDataDirectory(), EMERGENCY_NUMBER_DB_OTA_FILE_PATH));
+ if (mOverridedOtaDbParcelFileDescriptor == null) {
+ fileInputStream = new FileInputStream(
+ new File(Environment.getDataDirectory(),
+ EMERGENCY_NUMBER_DB_OTA_FILE_PATH));
+ } else {
+ File file = ParcelFileDescriptor
+ .getFile(mOverridedOtaDbParcelFileDescriptor.getFileDescriptor());
+ fileInputStream = new FileInputStream(new File(file.getAbsolutePath()));
}
- inputStream = new BufferedInputStream(mEmergencyNumberDbOtaFileInputStream);
+ inputStream = new BufferedInputStream(fileInputStream);
allEccMessages = ProtobufEccData.AllInfo.parseFrom(readInputStreamToByteArray(
new GZIPInputStream(inputStream)));
logd(mCountryIso + " ota emergency database is loaded. Ver: " + otaDatabaseVersion);
@@ -517,7 +517,7 @@
} catch (IOException ex) {
loge("Cache ota emergency database IOException: " + ex);
} finally {
- // close quietly by catching non-runtime exceptions.
+ // Close quietly by catching non-runtime exceptions.
if (inputStream != null) {
try {
inputStream.close();
@@ -526,6 +526,14 @@
} catch (Exception ignored) {
}
}
+ if (fileInputStream != null) {
+ try {
+ fileInputStream.close();
+ } catch (RuntimeException rethrown) {
+ throw rethrown;
+ } catch (Exception ignored) {
+ }
+ }
}
// Use a valid database that has higher version.
@@ -606,17 +614,7 @@
private void overrideOtaEmergencyNumberDbFilePath(
ParcelFileDescriptor otaParcelableFileDescriptor) {
logd("overrideOtaEmergencyNumberDbFilePath:" + otaParcelableFileDescriptor);
- try {
- if (otaParcelableFileDescriptor == null) {
- mEmergencyNumberDbOtaFileInputStream = new FileInputStream(
- new File(Environment.getDataDirectory(), EMERGENCY_NUMBER_DB_OTA_FILE_PATH));
- } else {
- mEmergencyNumberDbOtaFileInputStream = new FileInputStream(
- otaParcelableFileDescriptor.getFileDescriptor());
- }
- } catch (FileNotFoundException ex) {
- loge("Override ota emergency database failure: " + ex);
- }
+ mOverridedOtaDbParcelFileDescriptor = otaParcelableFileDescriptor;
}
private void updateOtaEmergencyNumberListDatabaseAndNotify() {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
index 589be81..001ba39 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
@@ -57,6 +57,7 @@
private static final int EVENT_SECONDARY_TIMER_EXPIRED = 9;
private static final int EVENT_RADIO_OFF_OR_UNAVAILABLE = 10;
private static final int EVENT_PREFERRED_NETWORK_MODE_CHANGED = 11;
+ private static final int EVENT_INITIALIZE = 12;
private NetworkTypeController mNetworkTypeController;
private PersistableBundle mBundle;