168 lines
5.7 KiB
Java
168 lines
5.7 KiB
Java
/*
|
|
* Copyright (C) 2015 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.voicemail.impl.sms;
|
|
|
|
import android.annotation.TargetApi;
|
|
import android.app.Activity;
|
|
import android.app.PendingIntent;
|
|
import android.content.BroadcastReceiver;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.content.IntentFilter;
|
|
import android.os.Build.VERSION_CODES;
|
|
import android.os.Bundle;
|
|
import android.support.annotation.MainThread;
|
|
import android.support.annotation.Nullable;
|
|
import android.support.annotation.WorkerThread;
|
|
import android.telecom.PhoneAccountHandle;
|
|
import android.telephony.SmsManager;
|
|
import android.telephony.VisualVoicemailSms;
|
|
import com.android.voicemail.impl.Assert;
|
|
import com.android.voicemail.impl.OmtpConstants;
|
|
import com.android.voicemail.impl.OmtpService;
|
|
import com.android.voicemail.impl.OmtpVvmCarrierConfigHelper;
|
|
import com.android.voicemail.impl.VvmLog;
|
|
import com.android.voicemail.impl.protocol.VisualVoicemailProtocol;
|
|
import java.io.Closeable;
|
|
import java.io.IOException;
|
|
import java.util.concurrent.CancellationException;
|
|
import java.util.concurrent.CompletableFuture;
|
|
import java.util.concurrent.ExecutionException;
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.concurrent.TimeoutException;
|
|
|
|
/** Intercepts a incoming STATUS SMS with a blocking call. */
|
|
@TargetApi(VERSION_CODES.O)
|
|
public class StatusSmsFetcher extends BroadcastReceiver implements Closeable {
|
|
|
|
private static final String TAG = "VvmStatusSmsFetcher";
|
|
|
|
private static final long STATUS_SMS_TIMEOUT_MILLIS = 60_000;
|
|
|
|
private static final String PERMISSION_DIALER_ORIGIN =
|
|
"com.android.dialer.permission.DIALER_ORIGIN";
|
|
|
|
private static final String ACTION_REQUEST_SENT_INTENT =
|
|
"com.android.voicemailomtp.sms.REQUEST_SENT";
|
|
|
|
private static final int ACTION_REQUEST_SENT_REQUEST_CODE = 0;
|
|
|
|
private CompletableFuture<Bundle> future = new CompletableFuture<>();
|
|
|
|
private final Context context;
|
|
private final PhoneAccountHandle phoneAccountHandle;
|
|
|
|
public StatusSmsFetcher(Context context, PhoneAccountHandle phoneAccountHandle) {
|
|
this.context = context;
|
|
this.phoneAccountHandle = phoneAccountHandle;
|
|
IntentFilter filter = new IntentFilter(ACTION_REQUEST_SENT_INTENT);
|
|
filter.addAction(OmtpService.ACTION_SMS_RECEIVED);
|
|
context.registerReceiver(this, filter, PERMISSION_DIALER_ORIGIN, /* scheduler= */ null);
|
|
}
|
|
|
|
@Override
|
|
public void close() throws IOException {
|
|
context.unregisterReceiver(this);
|
|
}
|
|
|
|
@WorkerThread
|
|
@Nullable
|
|
public Bundle get()
|
|
throws InterruptedException, ExecutionException, TimeoutException, CancellationException {
|
|
Assert.isNotMainThread();
|
|
return future.get(STATUS_SMS_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
|
|
}
|
|
|
|
public PendingIntent getSentIntent() {
|
|
Intent intent = new Intent(ACTION_REQUEST_SENT_INTENT);
|
|
intent.setPackage(context.getPackageName());
|
|
// Because the receiver is registered dynamically, implicit intent must be used.
|
|
// There should only be a single status SMS request at a time.
|
|
return PendingIntent.getBroadcast(
|
|
context,
|
|
ACTION_REQUEST_SENT_REQUEST_CODE,
|
|
intent,
|
|
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
|
}
|
|
|
|
@Override
|
|
@MainThread
|
|
public void onReceive(Context context, Intent intent) {
|
|
Assert.isMainThread();
|
|
if (ACTION_REQUEST_SENT_INTENT.equals(intent.getAction())) {
|
|
int resultCode = getResultCode();
|
|
|
|
if (resultCode == Activity.RESULT_OK) {
|
|
VvmLog.d(TAG, "Request SMS successfully sent");
|
|
return;
|
|
}
|
|
|
|
VvmLog.e(TAG, "Request SMS send failed: " + sentSmsResultToString(resultCode));
|
|
future.cancel(true);
|
|
return;
|
|
}
|
|
|
|
VisualVoicemailSms sms = intent.getExtras().getParcelable(OmtpService.EXTRA_VOICEMAIL_SMS);
|
|
|
|
if (!phoneAccountHandle.equals(sms.getPhoneAccountHandle())) {
|
|
return;
|
|
}
|
|
String eventType = sms.getPrefix();
|
|
|
|
if (eventType.equals(OmtpConstants.STATUS_SMS_PREFIX)) {
|
|
future.complete(sms.getFields());
|
|
return;
|
|
}
|
|
|
|
if (eventType.equals(OmtpConstants.SYNC_SMS_PREFIX)) {
|
|
return;
|
|
}
|
|
|
|
VvmLog.i(
|
|
TAG,
|
|
"VVM SMS with event " + eventType + " received, attempting to translate to STATUS SMS");
|
|
OmtpVvmCarrierConfigHelper helper = new OmtpVvmCarrierConfigHelper(context, phoneAccountHandle);
|
|
VisualVoicemailProtocol protocol = helper.getProtocol();
|
|
if (protocol == null) {
|
|
return;
|
|
}
|
|
Bundle translatedBundle = protocol.translateStatusSmsBundle(helper, eventType, sms.getFields());
|
|
|
|
if (translatedBundle != null) {
|
|
VvmLog.i(TAG, "Translated to STATUS SMS");
|
|
future.complete(translatedBundle);
|
|
}
|
|
}
|
|
|
|
private static String sentSmsResultToString(int resultCode) {
|
|
switch (resultCode) {
|
|
case Activity.RESULT_OK:
|
|
return "OK";
|
|
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
|
|
return "RESULT_ERROR_GENERIC_FAILURE";
|
|
case SmsManager.RESULT_ERROR_NO_SERVICE:
|
|
return "RESULT_ERROR_GENERIC_FAILURE";
|
|
case SmsManager.RESULT_ERROR_NULL_PDU:
|
|
return "RESULT_ERROR_GENERIC_FAILURE";
|
|
case SmsManager.RESULT_ERROR_RADIO_OFF:
|
|
return "RESULT_ERROR_GENERIC_FAILURE";
|
|
default:
|
|
return "UNKNOWN CODE: " + resultCode;
|
|
}
|
|
}
|
|
}
|