Merge "Do not update state of Disconnected Connection" into nyc-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 47987fa..2335d77 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -662,13 +662,22 @@
<data android:scheme="sms" />
</intent-filter>
</receiver>
- <receiver android:name="com.android.phone.vvm.omtp.SimChangeReceiver"
+ <receiver
+ android:name="com.android.phone.vvm.omtp.SimChangeReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.telephony.action.CARRIER_CONFIG_CHANGED" />
<action android:name="android.intent.action.SIM_STATE_CHANGED" />
</intent-filter>
- </receiver>
+ </receiver>
+ <receiver
+ android:name="com.android.phone.vvm.omtp.OmtpBootCompletedReceiver"
+ android:exported="true"
+ android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
+ <intent-filter>
+ <action android:name="android.intent.action.BOOT_COMPLETED"/>
+ </intent-filter>
+ </receiver>
<receiver
android:name="com.android.phone.vvm.omtp.fetch.FetchVoicemailReceiver"
android:exported="true">
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4f7cd53..49bc518 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -966,7 +966,7 @@
<!-- In-call screen: call failure message displayed in an error dialog -->
<string name="incall_error_no_phone_number_supplied">To place a call, enter a valid number.</string>
<!-- In-call screen: call failure message displayed in an error dialog -->
- <string name="incall_error_call_failed">Can\'t call.</string>
+ <string name="incall_error_call_failed">Call failed.</string>
<!-- In-call screen: status message displayed in a dialog when starting an MMI -->
<string name="incall_status_dialed_mmi">Starting MMI sequence\u2026</string>
<!-- In-call screen: message displayed in an error dialog -->
diff --git a/src/com/android/phone/vvm/omtp/OmtpBootCompletedReceiver.java b/src/com/android/phone/vvm/omtp/OmtpBootCompletedReceiver.java
new file mode 100644
index 0000000..a751e19
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/OmtpBootCompletedReceiver.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.util.ArraySet;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.Set;
+
+/**
+ * Stores subscription ID of SIMs while the device is locked to process them after the device is
+ * unlocked. This class is only intended to be used within {@link SimChangeReceiver}. subId is used
+ * for Visual voicemail activation/deactivation, which need to be done when the device is unlocked.
+ * But the enumeration of subIds happen on boot, when the device could be locked. This class is used
+ * to defer all activation/deactivation until the device is unlocked.
+ *
+ * The subIds are stored in device encrypted {@link SharedPreferences} (readable/writable even
+ * locked). after the device is unlocked the list is read and deleted.
+ */
+public class OmtpBootCompletedReceiver extends BroadcastReceiver {
+
+ private static final String TAG = "OmtpBootCompletedRcvr";
+
+ private static final String DEFERRED_SUBID_LIST_KEY = "deferred_sub_id_key";
+
+ @VisibleForTesting
+ interface SubIdProcessor{
+ void process(Context context,int subId);
+ }
+
+ private SubIdProcessor mSubIdProcessor = new SubIdProcessor() {
+ @Override
+ public void process(Context context, int subId) {
+ SimChangeReceiver.processSubId(context,subId);
+ }
+ };
+
+ /**
+ * Write the subId to the the list.
+ */
+ public static void addDeferredSubId(Context context, int subId) {
+ SharedPreferences sharedPreferences = getSubIdSharedPreference(context);
+ Set<String> subIds =
+ new ArraySet<>(sharedPreferences.getStringSet(DEFERRED_SUBID_LIST_KEY, null));
+ subIds.add(String.valueOf(subId));
+ sharedPreferences.edit().putStringSet(DEFERRED_SUBID_LIST_KEY, subIds).apply();
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // Listens to android.intent.action.BOOT_COMPLETED
+ if(!intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
+ return;
+ }
+
+ Log.v(TAG, "processing deferred subId list");
+ Set<Integer> subIds = readAndDeleteSubIds(context);
+ for (Integer subId : subIds) {
+ Log.v(TAG, "processing subId " + subId);
+ mSubIdProcessor.process(context, subId);
+ }
+ }
+
+ /**
+ * Read all subId from the list to a unique integer set, and delete the preference.
+ */
+ private static Set<Integer> readAndDeleteSubIds(Context context) {
+ SharedPreferences sharedPreferences = getSubIdSharedPreference(context);
+ Set<String> subIdStrings = sharedPreferences.getStringSet(DEFERRED_SUBID_LIST_KEY, null);
+ Set<Integer> subIds = new ArraySet<>();
+ if(subIdStrings == null) {
+ return subIds;
+ }
+ for(String string : subIdStrings){
+ subIds.add(Integer.valueOf(string));
+ }
+ getSubIdSharedPreference(context).edit().remove(DEFERRED_SUBID_LIST_KEY).apply();
+ return subIds;
+ }
+
+ @VisibleForTesting
+ void setSubIdProcessorForTest(SubIdProcessor processor){
+ mSubIdProcessor = processor;
+ }
+
+ private static SharedPreferences getSubIdSharedPreference(Context context) {
+ return PreferenceManager
+ .getDefaultSharedPreferences(context.createDeviceEncryptedStorageContext());
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/OmtpVvmCarrierConfigHelper.java b/src/com/android/phone/vvm/omtp/OmtpVvmCarrierConfigHelper.java
index 57e23a9..61cf6d3 100644
--- a/src/com/android/phone/vvm/omtp/OmtpVvmCarrierConfigHelper.java
+++ b/src/com/android/phone/vvm/omtp/OmtpVvmCarrierConfigHelper.java
@@ -34,7 +34,8 @@
* retrieve carrier vvm configuration details before sending the appropriate texts.
*/
public class OmtpVvmCarrierConfigHelper {
- private static final String TAG = "OmtpVvmCarrierConfigHelper";
+
+ private static final String TAG = "OmtpVvmCarrierCfgHlpr";
private Context mContext;
private int mSubId;
private PersistableBundle mCarrierConfig;
diff --git a/src/com/android/phone/vvm/omtp/SimChangeReceiver.java b/src/com/android/phone/vvm/omtp/SimChangeReceiver.java
index c42797a..0a37493 100644
--- a/src/com/android/phone/vvm/omtp/SimChangeReceiver.java
+++ b/src/com/android/phone/vvm/omtp/SimChangeReceiver.java
@@ -34,15 +34,16 @@
import com.android.phone.vvm.omtp.sync.OmtpVvmSourceManager;
/**
- * This class listens to the {@link CarrierConfigManager#ACTION_CARRIER_CONFIG_CHANGED} and
- * {@link TelephonyIntents#ACTION_SIM_STATE_CHANGED} to determine when a SIM is added, replaced,
- * or removed.
+ * This class listens to the {@link CarrierConfigManager#ACTION_CARRIER_CONFIG_CHANGED} and {@link
+ * TelephonyIntents#ACTION_SIM_STATE_CHANGED} to determine when a SIM is added, replaced, or
+ * removed.
*
* When a SIM is added, send an activate SMS. When a SIM is removed, remove the sync accounts and
* change the status in the voicemail_status table.
*/
public class SimChangeReceiver extends BroadcastReceiver {
- private final String TAG = "SimChangeReceiver";
+
+ private static final String TAG = "SimChangeReceiver";
@Override
public void onReceive(Context context, Intent intent) {
@@ -74,46 +75,54 @@
return;
}
- OmtpVvmCarrierConfigHelper carrierConfigHelper =
- new OmtpVvmCarrierConfigHelper(context, subId);
- if (carrierConfigHelper.isOmtpVvmType()) {
- PhoneAccountHandle phoneAccount = PhoneUtils.makePstnPhoneAccountHandle(
- SubscriptionManager.getPhoneId(subId));
-
- boolean isUserSet = VisualVoicemailSettingsUtil.isVisualVoicemailUserSet(
- context, phoneAccount);
- boolean isEnabledInSettings =
- VisualVoicemailSettingsUtil.isVisualVoicemailEnabled(context,
- phoneAccount);
- boolean isSupported =
- context.getResources().getBoolean(R.bool.allow_visual_voicemail);
- boolean isEnabled = isSupported && (isUserSet ? isEnabledInSettings :
- carrierConfigHelper.isEnabledByDefault());
-
- if (!isUserSet) {
- // Preserve the previous setting for "isVisualVoicemailEnabled" if it is
- // set by the user, otherwise, set this value for the first time.
- VisualVoicemailSettingsUtil.setVisualVoicemailEnabled(context, phoneAccount,
- isEnabled, /** isUserSet */ false);
- }
-
- if (isEnabled) {
- LocalLogHelper.log(TAG, "Sim state or carrier config changed: requesting"
- + " activation for " + phoneAccount.getId());
-
- // Add a phone state listener so that changes to the communication channels
- // can be recorded.
- OmtpVvmSourceManager.getInstance(context).addPhoneStateListener(
- phoneAccount);
- carrierConfigHelper.startActivation();
- } else {
- // It may be that the source was not registered to begin with but we want
- // to run through the steps to remove the source just in case.
- OmtpVvmSourceManager.getInstance(context).removeSource(phoneAccount);
- Log.v(TAG, "Sim change for disabled account.");
- }
+ if (!UserManager.get(context).isUserUnlocked()) {
+ OmtpBootCompletedReceiver.addDeferredSubId(context, subId);
+ } else {
+ processSubId(context, subId);
}
break;
}
}
+
+ public static void processSubId(Context context, int subId) {
+ OmtpVvmCarrierConfigHelper carrierConfigHelper =
+ new OmtpVvmCarrierConfigHelper(context, subId);
+ if (carrierConfigHelper.isOmtpVvmType()) {
+ PhoneAccountHandle phoneAccount = PhoneUtils.makePstnPhoneAccountHandle(
+ SubscriptionManager.getPhoneId(subId));
+
+ boolean isUserSet = VisualVoicemailSettingsUtil.isVisualVoicemailUserSet(
+ context, phoneAccount);
+ boolean isEnabledInSettings =
+ VisualVoicemailSettingsUtil.isVisualVoicemailEnabled(context,
+ phoneAccount);
+ boolean isSupported =
+ context.getResources().getBoolean(R.bool.allow_visual_voicemail);
+ boolean isEnabled = isSupported && (isUserSet ? isEnabledInSettings :
+ carrierConfigHelper.isEnabledByDefault());
+
+ if (!isUserSet) {
+ // Preserve the previous setting for "isVisualVoicemailEnabled" if it is
+ // set by the user, otherwise, set this value for the first time.
+ VisualVoicemailSettingsUtil.setVisualVoicemailEnabled(context, phoneAccount,
+ isEnabled, /** isUserSet */false);
+ }
+
+ if (isEnabled) {
+ LocalLogHelper.log(TAG, "Sim state or carrier config changed: requesting"
+ + " activation for " + phoneAccount.getId());
+
+ // Add a phone state listener so that changes to the communication channels
+ // can be recorded.
+ OmtpVvmSourceManager.getInstance(context).addPhoneStateListener(
+ phoneAccount);
+ carrierConfigHelper.startActivation();
+ } else {
+ // It may be that the source was not registered to begin with but we want
+ // to run through the steps to remove the source just in case.
+ OmtpVvmSourceManager.getInstance(context).removeSource(phoneAccount);
+ Log.v(TAG, "Sim change for disabled account.");
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java b/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
index 0950862..9ac37a4 100644
--- a/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
+++ b/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
@@ -19,16 +19,13 @@
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
-import android.net.ConnectivityManager;
-import android.net.ConnectivityManager.NetworkCallback;
-import android.net.NetworkRequest;
import android.net.Uri;
+import android.os.UserManager;
import android.provider.Telephony;
import android.provider.VoicemailContract;
import android.telecom.PhoneAccountHandle;
import android.telecom.Voicemail;
import android.telephony.SmsMessage;
-import android.telephony.SubscriptionManager;
import android.util.Log;
import com.android.internal.telephony.PhoneConstants;
@@ -52,6 +49,12 @@
@Override
public void onReceive(Context context, Intent intent) {
+ if (!UserManager.get(context).isUserUnlocked()) {
+ Log.i(TAG, "Received message on locked device");
+ // A full sync will happen after the device is unlocked, so nothing need to be done.
+ return;
+ }
+
mContext = context;
mPhoneAccount = PhoneUtils.makePstnPhoneAccountHandle(
intent.getExtras().getInt(PhoneConstants.PHONE_KEY));
diff --git a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
index 853ad65..fb8b45b 100644
--- a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
+++ b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
@@ -319,7 +319,12 @@
public void onAvailable(Network network) {
super.onAvailable(network);
NetworkInfo info = getConnectivityManager().getNetworkInfo(network);
- Log.d(TAG, "Network Type: " + info == null ? "Unknown" : info.getTypeName());
+ if (info == null) {
+ Log.d(TAG, "Network Type: Unknown");
+ } else {
+ Log.d(TAG, "Network Type: " + info.getTypeName());
+ }
+
doSync(network, this, mPhoneAccount, mVoicemail, mAction);
}
diff --git a/tests/src/com/android/phone/vvm/omtp/OmtpBootCompletedReceiverTests.java b/tests/src/com/android/phone/vvm/omtp/OmtpBootCompletedReceiverTests.java
new file mode 100644
index 0000000..a2d247a
--- /dev/null
+++ b/tests/src/com/android/phone/vvm/omtp/OmtpBootCompletedReceiverTests.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp;
+
+import android.content.Context;
+import android.content.Intent;
+import android.preference.PreferenceManager;
+import android.test.AndroidTestCase;
+import android.util.ArraySet;
+
+import com.android.phone.vvm.omtp.OmtpBootCompletedReceiver.SubIdProcessor;
+
+import java.util.Set;
+
+public class OmtpBootCompletedReceiverTests extends AndroidTestCase {
+ OmtpBootCompletedReceiver mReceiver = new OmtpBootCompletedReceiver();
+ @Override
+ public void setUp() {
+ }
+
+ @Override
+ public void tearDown() {
+ PreferenceManager
+ .getDefaultSharedPreferences(getContext().createDeviceEncryptedStorageContext())
+ .edit().clear().apply();
+ }
+
+ public void testReadWriteList() {
+ readWriteList(new int[] {1});
+ }
+
+ public void testReadWriteList_Multiple() {
+ readWriteList(new int[] {1, 2});
+ }
+
+ public void testReadWriteList_Duplicate() {
+ readWriteList(new int[] {1, 1});
+ }
+
+ private void readWriteList(int[] values) {
+ for (int value : values) {
+ OmtpBootCompletedReceiver.addDeferredSubId(getContext(), value);
+ }
+ TestSubIdProcessor processor = new TestSubIdProcessor(values);
+ mReceiver.setSubIdProcessorForTest(processor);
+ Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED);
+ mReceiver.onReceive(getContext(), intent);
+ processor.assertMatch();
+ // after onReceive() is called the list should be empty
+ TestSubIdProcessor emptyProcessor = new TestSubIdProcessor(new int[] {});
+ mReceiver.setSubIdProcessorForTest(processor);
+ mReceiver.onReceive(getContext(), intent);
+ processor.assertMatch();
+ }
+
+ private static class TestSubIdProcessor implements SubIdProcessor {
+ private final Set<Integer> mExpectedSubIds;
+
+ public TestSubIdProcessor(int[] expectedSubIds) {
+ mExpectedSubIds = new ArraySet<>();
+ for(int subId : expectedSubIds){
+ mExpectedSubIds.add(subId);
+ }
+ }
+
+ @Override
+ public void process(Context context, int subId){
+ assertTrue(mExpectedSubIds.contains(subId));
+ mExpectedSubIds.remove(subId);
+ }
+
+ public void assertMatch(){
+ assertTrue(mExpectedSubIds.isEmpty());
+ }
+ }
+}