Merge "fix typo in DIGEST-MD5 charset" into nyc-mr1-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 2accdab..b5fd399 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -622,7 +622,7 @@
</intent-filter>
</provider>
<receiver android:name="com.android.phone.vvm.omtp.sms.OmtpMessageReceiver"
- android:exported="true"
+ android:exported="false"
androidprv:systemUserOnly="true">
<intent-filter>
<action android:name="android.intent.action.VOICEMAIL_SMS_RECEIVED"/>
diff --git a/res/xml/vvm_config.xml b/res/xml/vvm_config.xml
index fad246f..19c667e 100644
--- a/res/xml/vvm_config.xml
+++ b/res/xml/vvm_config.xml
@@ -36,6 +36,10 @@
</string-array>
<string name="vvm_type_string">vvm_type_omtp</string>
<boolean name="vvm_cellular_data_required_bool" value="true"/>
+ <string-array name="vvm_disabled_capabilities_string_array">
+ <!-- b/32365569 -->
+ <item value="STARTTLS"/>
+ </string-array>
</pbundle_as_map>
<pbundle_as_map>
diff --git a/sip/src/com/android/services/telephony/sip/SipEditor.java b/sip/src/com/android/services/telephony/sip/SipEditor.java
index f6e9c22..07e5b62 100644
--- a/sip/src/com/android/services/telephony/sip/SipEditor.java
+++ b/sip/src/com/android/services/telephony/sip/SipEditor.java
@@ -259,7 +259,7 @@
*
* @param p The {@link SipProfile} to delete.
*/
- private void deleteAndUnregisterProfile(SipProfile p) {
+ private void deleteAndUnregisterProfile(SipProfile p) throws IOException {
if (p == null) return;
mProfileDb.deleteProfile(p);
mSipAccountRegistry.stopSipService(this, p.getProfileName());
diff --git a/sip/src/com/android/services/telephony/sip/SipProfileDb.java b/sip/src/com/android/services/telephony/sip/SipProfileDb.java
index e7b201b..bb1c7ec 100644
--- a/sip/src/com/android/services/telephony/sip/SipProfileDb.java
+++ b/sip/src/com/android/services/telephony/sip/SipProfileDb.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.net.sip.SipProfile;
import android.text.TextUtils;
+import android.util.EventLog;
import android.util.Log;
import java.io.File;
@@ -66,9 +67,13 @@
mSipPreferences = new SipPreferences(mContext);
}
- public void deleteProfile(SipProfile p) {
+ public void deleteProfile(SipProfile p) throws IOException {
synchronized(SipProfileDb.class) {
- deleteProfile(new File(mProfilesDirectory + p.getProfileName()));
+ File profileFile = new File(mProfilesDirectory, p.getProfileName());
+ if (!isChild(new File(mProfilesDirectory), profileFile)) {
+ throw new IOException("Invalid Profile Credentials!");
+ }
+ deleteProfile(profileFile);
if (mProfilesCount < 0) retrieveSipProfileListInternal();
}
}
@@ -93,7 +98,10 @@
public void saveProfile(SipProfile p) throws IOException {
synchronized(SipProfileDb.class) {
if (mProfilesCount < 0) retrieveSipProfileListInternal();
- File f = new File(mProfilesDirectory + p.getProfileName());
+ File f = new File(mProfilesDirectory, p.getProfileName());
+ if (!isChild(new File(mProfilesDirectory), f)) {
+ throw new IOException("Invalid Profile Credentials!");
+ }
if (!f.exists()) f.mkdirs();
AtomicFile atomicFile = new AtomicFile(new File(f, PROFILE_OBJ_FILE));
FileOutputStream fos = null;
@@ -173,4 +181,19 @@
private static void log(String msg) {
Log.d(SipUtil.LOG_TAG, PREFIX + msg);
}
+
+ /**
+ * Verifies that the file is a direct child of the base directory.
+ */
+ private boolean isChild(File base, File file) {
+ if (base == null || file == null) {
+ return false;
+ }
+ if (!base.equals(file.getAbsoluteFile().getParentFile())) {
+ Log.w(SipUtil.LOG_TAG, "isChild, file is not a child of the base dir.");
+ EventLog.writeEvent(0x534e4554, "31530456", -1, "");
+ return false;
+ }
+ return true;
+ }
}
diff --git a/sip/src/com/android/services/telephony/sip/SipUtil.java b/sip/src/com/android/services/telephony/sip/SipUtil.java
index 3678c46..cf03dd3 100644
--- a/sip/src/com/android/services/telephony/sip/SipUtil.java
+++ b/sip/src/com/android/services/telephony/sip/SipUtil.java
@@ -164,7 +164,12 @@
}
Log.i(LOG_TAG, "(Migration) Deleting SIP profile: " +
profileToMove.getProfileName());
- dbDeStorage.deleteProfile(profileToMove);
+ try {
+ dbDeStorage.deleteProfile(profileToMove);
+ } catch (IOException e) {
+ Log.w(LOG_TAG, "Error Deleting file: " +
+ profileToMove.getProfileName(), e);
+ }
}
}
// Delete supporting structures if they exist
diff --git a/src/com/android/phone/settings/VoicemailChangePinActivity.java b/src/com/android/phone/settings/VoicemailChangePinActivity.java
index 52c97a7..33da27a 100644
--- a/src/com/android/phone/settings/VoicemailChangePinActivity.java
+++ b/src/com/android/phone/settings/VoicemailChangePinActivity.java
@@ -35,6 +35,7 @@
import android.text.InputFilter.LengthFilter;
import android.text.TextWatcher;
import android.view.KeyEvent;
+import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
@@ -436,6 +437,15 @@
}
}
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ onBackPressed();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (!mNextButton.isEnabled()) {
return true;
diff --git a/src/com/android/phone/vvm/omtp/ActivationTask.java b/src/com/android/phone/vvm/omtp/ActivationTask.java
index 3a9893a..72f1f54 100644
--- a/src/com/android/phone/vvm/omtp/ActivationTask.java
+++ b/src/com/android/phone/vvm/omtp/ActivationTask.java
@@ -24,7 +24,6 @@
import android.os.Bundle;
import android.provider.Settings;
import android.provider.Settings.Global;
-import android.provider.VoicemailContract.Status;
import android.telecom.PhoneAccountHandle;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
@@ -101,13 +100,6 @@
return;
}
- // Check for signal before activating. The event often happen while boot and the
- // network is not connected yet. Launching activation will likely to cause the SMS
- // sending to fail and waste unnecessary time waiting for time out.
- if (!hasSignal(context, subId)) {
- VvmLog.i(TAG, "Activation requested while not in service, rejecting");
- }
-
Intent intent = BaseTask.createIntent(context, ActivationTask.class, subId);
if (messageData != null) {
intent.putExtra(EXTRA_MESSAGE_DATA_BUNDLE, messageData);
@@ -140,12 +132,6 @@
return;
}
- if (!hasSignal(getContext(), subId)) {
- VvmLog.i(TAG, "Service lost during activation, aborting");
- // Don't retry, a new activation will be started after the signal returned.
- return;
- }
-
OmtpVvmCarrierConfigHelper helper = new OmtpVvmCarrierConfigHelper(getContext(), subId);
if (!helper.isValid()) {
VvmLog.i(TAG, "VVM not supported on subId " + subId);
@@ -167,6 +153,7 @@
if (!OmtpVvmSourceManager.getInstance(getContext())
.isVvmSourceRegistered(phoneAccountHandle)) {
+ // This account has not been activated before during the lifetime of this boot.
VisualVoicemailPreferences preferences = new VisualVoicemailPreferences(getContext(),
phoneAccountHandle);
if (preferences.getString(OmtpConstants.SERVER_ADDRESS, null) == null) {
@@ -178,12 +165,20 @@
} else {
// The account has been activated on this device before. Pretend it is already
// activated. If there are any activation error it will overwrite this status.
- VoicemailStatus.edit(getContext(), phoneAccountHandle)
- .setConfigurationState(Status.CONFIGURATION_STATE_OK)
- .apply();
+ helper.handleEvent(VoicemailStatus.edit(getContext(), phoneAccountHandle),
+ OmtpEvents.CONFIG_ACTIVATING_SUBSEQUENT);
}
}
+ if (!hasSignal(getContext(), subId)) {
+ VvmLog.i(TAG, "Service lost during activation, aborting");
+ // Restore the "NO SIGNAL" state since it will be overwritten by the CONFIG_ACTIVATING
+ // event.
+ helper.handleEvent(VoicemailStatus.edit(getContext(), phoneAccountHandle),
+ OmtpEvents.NOTIFICATION_SERVICE_LOST);
+ // Don't retry, a new activation will be started after the signal returned.
+ return;
+ }
helper.activateSmsFilter();
VoicemailStatus.Editor status = mRetryPolicy.getVoicemailStatusEditor();
diff --git a/src/com/android/phone/vvm/omtp/DefaultOmtpEventHandler.java b/src/com/android/phone/vvm/omtp/DefaultOmtpEventHandler.java
index 88943c9..0c19a6a 100644
--- a/src/com/android/phone/vvm/omtp/DefaultOmtpEventHandler.java
+++ b/src/com/android/phone/vvm/omtp/DefaultOmtpEventHandler.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.provider.VoicemailContract;
import android.provider.VoicemailContract.Status;
+
import com.android.phone.VoicemailStatus;
import com.android.phone.vvm.omtp.OmtpEvents.Type;
@@ -49,6 +50,7 @@
private static void handleConfigurationEvent(Context context, VoicemailStatus.Editor status,
OmtpEvents event) {
switch (event) {
+ case CONFIG_DEFAULT_PIN_REPLACED:
case CONFIG_REQUEST_STATUS_SUCCESS:
case CONFIG_PIN_SET:
status
@@ -61,8 +63,14 @@
// for this activation.
status
.setConfigurationState(Status.CONFIGURATION_STATE_CONFIGURING)
- .setDataChannelState(Status.DATA_CHANNEL_STATE_OK)
- .setNotificationChannelState(Status.NOTIFICATION_CHANNEL_STATE_OK).apply();
+ .setNotificationChannelState(Status.NOTIFICATION_CHANNEL_STATE_OK)
+ .setDataChannelState(Status.DATA_CHANNEL_STATE_OK).apply();
+ break;
+ case CONFIG_ACTIVATING_SUBSEQUENT:
+ status
+ .setConfigurationState(Status.CONFIGURATION_STATE_OK)
+ .setNotificationChannelState(Status.NOTIFICATION_CHANNEL_STATE_OK)
+ .setDataChannelState(Status.DATA_CHANNEL_STATE_OK).apply();
break;
case CONFIG_SERVICE_NOT_AVAILABLE:
status
@@ -116,6 +124,7 @@
case DATA_SSL_INVALID_HOST_NAME:
case DATA_CANNOT_ESTABLISH_SSL_SESSION:
case DATA_IOE_ON_OPEN:
+ case DATA_GENERIC_IMAP_IOE:
status
.setDataChannelState(
VoicemailContract.Status.DATA_CHANNEL_STATE_COMMUNICATION_ERROR)
@@ -137,6 +146,7 @@
case DATA_REJECTED_SERVER_RESPONSE:
case DATA_INVALID_INITIAL_SERVER_RESPONSE:
+ case DATA_MAILBOX_OPEN_FAILED:
case DATA_SSL_EXCEPTION:
case DATA_ALL_SOCKET_CONNECTION_FAILED:
status
diff --git a/src/com/android/phone/vvm/omtp/OmtpEvents.java b/src/com/android/phone/vvm/omtp/OmtpEvents.java
index 648e0d0..7a89418 100644
--- a/src/com/android/phone/vvm/omtp/OmtpEvents.java
+++ b/src/com/android/phone/vvm/omtp/OmtpEvents.java
@@ -17,6 +17,7 @@
package com.android.phone.vvm.omtp;
import android.annotation.IntDef;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -34,6 +35,8 @@
// The voicemail PIN is replaced with a generated PIN, user should change it.
CONFIG_DEFAULT_PIN_REPLACED(Type.CONFIGURATION, true),
CONFIG_ACTIVATING(Type.CONFIGURATION, true),
+ // There are already activation records, this is only a book-keeping activation.
+ CONFIG_ACTIVATING_SUBSEQUENT(Type.CONFIGURATION, true),
CONFIG_STATUS_SMS_TIME_OUT(Type.CONFIGURATION),
CONFIG_SERVICE_NOT_AVAILABLE(Type.CONFIGURATION),
diff --git a/src/com/android/services/telephony/CdmaConnection.java b/src/com/android/services/telephony/CdmaConnection.java
index 8020996..29ccc6c 100644
--- a/src/com/android/services/telephony/CdmaConnection.java
+++ b/src/com/android/services/telephony/CdmaConnection.java
@@ -184,7 +184,7 @@
}
@Override
- public void performConference(TelephonyConnection otherConnection) {
+ public void performConference(android.telecom.Connection otherConnection) {
if (isImsConnection()) {
super.performConference(otherConnection);
} else {
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index e33c351..4acb6f8 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -439,7 +439,7 @@
@Override
public void onMerge(android.telecom.Connection connection) {
try {
- Phone phone = ((TelephonyConnection) connection).getPhone();
+ Phone phone = mConferenceHost.getPhone();
if (phone != null) {
phone.conference();
}
diff --git a/src/com/android/services/telephony/ImsConferenceController.java b/src/com/android/services/telephony/ImsConferenceController.java
index 6669482..f7d587d 100644
--- a/src/com/android/services/telephony/ImsConferenceController.java
+++ b/src/com/android/services/telephony/ImsConferenceController.java
@@ -187,6 +187,7 @@
Log.v(this, "recalculateConferenceable : %d", mTelephonyConnections.size());
HashSet<Conferenceable> conferenceableSet = new HashSet<>(mTelephonyConnections.size() +
mImsConferences.size());
+ HashSet<Conferenceable> conferenceParticipantsSet = new HashSet<>();
// Loop through and collect all calls which are active or holding
for (TelephonyConnection connection : mTelephonyConnections) {
@@ -240,6 +241,7 @@
case Connection.STATE_ACTIVE:
//fall through
case Connection.STATE_HOLDING:
+ conferenceParticipantsSet.addAll(conference.getConnections());
conferenceableSet.add(conference);
continue;
default:
@@ -256,6 +258,16 @@
.stream()
.filter(conferenceable -> c != conferenceable)
.collect(Collectors.toList());
+ // TODO: Remove this once RemoteConnection#setConferenceableConnections is fixed.
+ // Add all conference participant connections as conferenceable with a standalone
+ // Connection. We need to do this to ensure that RemoteConnections work properly.
+ // At the current time, a RemoteConnection will not be conferenceable with a
+ // Conference, so we need to add its children to ensure the user can merge the call
+ // into the conference.
+ // We should add support for RemoteConnection#setConferenceables, which accepts a
+ // list of remote conferences and connections in the future.
+ conferenceables.addAll(conferenceParticipantsSet);
+
((Connection) c).setConferenceables(conferenceables);
} else if (c instanceof Conference) {
// Remove all conferences from the set, since we can not conference a conference
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 365f99e..c4f9c9a 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -683,7 +683,7 @@
}
}
- public void performConference(TelephonyConnection otherConnection) {
+ public void performConference(Connection otherConnection) {
Log.d(this, "performConference - %s", this);
if (getPhone() != null) {
try {
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index becb570..5afdd72 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -616,14 +616,35 @@
}
}
+ /**
+ * Conferences two connections.
+ *
+ * Note: The {@link android.telecom.RemoteConnection#setConferenceableConnections(List)} API has
+ * a limitation in that it can only specify conferenceables which are instances of
+ * {@link android.telecom.RemoteConnection}. In the case of an {@link ImsConference}, the
+ * regular {@link Connection#setConferenceables(List)} API properly handles being able to merge
+ * a {@link Conference} and a {@link Connection}. As a result when, merging a
+ * {@link android.telecom.RemoteConnection} into a {@link android.telecom.RemoteConference}
+ * require merging a {@link ConferenceParticipantConnection} which is a child of the
+ * {@link Conference} with a {@link TelephonyConnection}. The
+ * {@link ConferenceParticipantConnection} class does not have the capability to initiate a
+ * conference merge, so we need to call
+ * {@link TelephonyConnection#performConference(Connection)} on either {@code connection1} or
+ * {@code connection2}, one of which is an instance of {@link TelephonyConnection}.
+ *
+ * @param connection1 A connection to merge into a conference call.
+ * @param connection2 A connection to merge into a conference call.
+ */
@Override
public void onConference(Connection connection1, Connection connection2) {
- if (connection1 instanceof TelephonyConnection &&
- connection2 instanceof TelephonyConnection) {
- ((TelephonyConnection) connection1).performConference(
- (TelephonyConnection) connection2);
+ if (connection1 instanceof TelephonyConnection) {
+ ((TelephonyConnection) connection1).performConference(connection2);
+ } else if (connection2 instanceof TelephonyConnection) {
+ ((TelephonyConnection) connection2).performConference(connection1);
+ } else {
+ Log.w(this, "onConference - cannot merge connections " +
+ "Connection1: %s, Connection2: %2", connection1, connection2);
}
-
}
private boolean isRadioOn() {