Add VisualVoicemailService
VisualVoicemailService can be implemennted by the default dialer to provide a visual voicemail client similar to the OMTP visual voicemail spec. Other APIs such as the SMS filter and hidden text SMS sending are made public and consolidated into the service interface. Test: make. CTS tests in a follow up CL Change-Id: Ib5e9aa15fc098f4c13b15e5dbecf9ab646e0e400
This commit is contained in:
@@ -38,6 +38,7 @@ package android {
|
||||
field public static final java.lang.String BIND_TELECOM_CONNECTION_SERVICE = "android.permission.BIND_TELECOM_CONNECTION_SERVICE";
|
||||
field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
|
||||
field public static final java.lang.String BIND_TV_INPUT = "android.permission.BIND_TV_INPUT";
|
||||
field public static final java.lang.String BIND_VISUAL_VOICEMAIL_SERVICE = "android.permission.BIND_VISUAL_VOICEMAIL_SERVICE";
|
||||
field public static final java.lang.String BIND_VOICE_INTERACTION = "android.permission.BIND_VOICE_INTERACTION";
|
||||
field public static final java.lang.String BIND_VPN_SERVICE = "android.permission.BIND_VPN_SERVICE";
|
||||
field public static final java.lang.String BIND_VR_LISTENER_SERVICE = "android.permission.BIND_VR_LISTENER_SERVICE";
|
||||
@@ -37933,6 +37934,54 @@ package android.telephony {
|
||||
method public void onReceiveUssdResponseFailed(java.lang.String, int);
|
||||
}
|
||||
|
||||
public abstract class VisualVoicemailService extends android.app.Service {
|
||||
ctor public VisualVoicemailService();
|
||||
method public android.os.IBinder onBind(android.content.Intent);
|
||||
method public abstract void onCellServiceConnected(android.telephony.VisualVoicemailService.VisualVoicemailTask, android.telecom.PhoneAccountHandle);
|
||||
method public abstract void onSimRemoved(android.telephony.VisualVoicemailService.VisualVoicemailTask, android.telecom.PhoneAccountHandle);
|
||||
method public abstract void onSmsReceived(android.telephony.VisualVoicemailService.VisualVoicemailTask, android.telephony.VisualVoicemailSms);
|
||||
method public abstract void onStopped(android.telephony.VisualVoicemailService.VisualVoicemailTask);
|
||||
method public static final void sendVisualVoicemailSms(android.content.Context, android.telecom.PhoneAccountHandle, java.lang.String, short, java.lang.String, android.app.PendingIntent);
|
||||
method public static final void setSmsFilterSettings(android.content.Context, android.telecom.PhoneAccountHandle, android.telephony.VisualVoicemailSmsFilterSettings);
|
||||
field public static final java.lang.String SERVICE_INTERFACE = "android.telephony.VisualVoicemailService";
|
||||
}
|
||||
|
||||
public static class VisualVoicemailService.VisualVoicemailTask {
|
||||
method public final void finish();
|
||||
}
|
||||
|
||||
public final class VisualVoicemailSms implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public android.os.Bundle getFields();
|
||||
method public java.lang.String getMessageBody();
|
||||
method public android.telecom.PhoneAccountHandle getPhoneAccountHandle();
|
||||
method public java.lang.String getPrefix();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator<android.telephony.VisualVoicemailSms> CREATOR;
|
||||
}
|
||||
|
||||
public final class VisualVoicemailSmsFilterSettings implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator<android.telephony.VisualVoicemailSmsFilterSettings> CREATOR;
|
||||
field public static final java.lang.String DEFAULT_CLIENT_PREFIX = "//VVM";
|
||||
field public static final int DEFAULT_DESTINATION_PORT = -1; // 0xffffffff
|
||||
field public static final java.util.List<java.lang.String> DEFAULT_ORIGINATING_NUMBERS;
|
||||
field public static final int DESTINATION_PORT_ANY = -1; // 0xffffffff
|
||||
field public static final int DESTINATION_PORT_DATA_SMS = -2; // 0xfffffffe
|
||||
field public final java.lang.String clientPrefix;
|
||||
field public final int destinationPort;
|
||||
field public final java.util.List<java.lang.String> originatingNumbers;
|
||||
}
|
||||
|
||||
public static class VisualVoicemailSmsFilterSettings.Builder {
|
||||
ctor public VisualVoicemailSmsFilterSettings.Builder();
|
||||
method public android.telephony.VisualVoicemailSmsFilterSettings build();
|
||||
method public android.telephony.VisualVoicemailSmsFilterSettings.Builder setClientPrefix(java.lang.String);
|
||||
method public android.telephony.VisualVoicemailSmsFilterSettings.Builder setDestinationPort(int);
|
||||
method public android.telephony.VisualVoicemailSmsFilterSettings.Builder setOriginatingNumbers(java.util.List<java.lang.String>);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
package android.telephony.cdma {
|
||||
|
||||
@@ -55,6 +55,7 @@ package android {
|
||||
field public static final java.lang.String BIND_TRUST_AGENT = "android.permission.BIND_TRUST_AGENT";
|
||||
field public static final java.lang.String BIND_TV_INPUT = "android.permission.BIND_TV_INPUT";
|
||||
field public static final java.lang.String BIND_TV_REMOTE_SERVICE = "android.permission.BIND_TV_REMOTE_SERVICE";
|
||||
field public static final java.lang.String BIND_VISUAL_VOICEMAIL_SERVICE = "android.permission.BIND_VISUAL_VOICEMAIL_SERVICE";
|
||||
field public static final java.lang.String BIND_VOICE_INTERACTION = "android.permission.BIND_VOICE_INTERACTION";
|
||||
field public static final java.lang.String BIND_VPN_SERVICE = "android.permission.BIND_VPN_SERVICE";
|
||||
field public static final java.lang.String BIND_VR_LISTENER_SERVICE = "android.permission.BIND_VR_LISTENER_SERVICE";
|
||||
@@ -41084,6 +41085,54 @@ package android.telephony {
|
||||
method public void onReceiveUssdResponseFailed(java.lang.String, int);
|
||||
}
|
||||
|
||||
public abstract class VisualVoicemailService extends android.app.Service {
|
||||
ctor public VisualVoicemailService();
|
||||
method public android.os.IBinder onBind(android.content.Intent);
|
||||
method public abstract void onCellServiceConnected(android.telephony.VisualVoicemailService.VisualVoicemailTask, android.telecom.PhoneAccountHandle);
|
||||
method public abstract void onSimRemoved(android.telephony.VisualVoicemailService.VisualVoicemailTask, android.telecom.PhoneAccountHandle);
|
||||
method public abstract void onSmsReceived(android.telephony.VisualVoicemailService.VisualVoicemailTask, android.telephony.VisualVoicemailSms);
|
||||
method public abstract void onStopped(android.telephony.VisualVoicemailService.VisualVoicemailTask);
|
||||
method public static final void sendVisualVoicemailSms(android.content.Context, android.telecom.PhoneAccountHandle, java.lang.String, short, java.lang.String, android.app.PendingIntent);
|
||||
method public static final void setSmsFilterSettings(android.content.Context, android.telecom.PhoneAccountHandle, android.telephony.VisualVoicemailSmsFilterSettings);
|
||||
field public static final java.lang.String SERVICE_INTERFACE = "android.telephony.VisualVoicemailService";
|
||||
}
|
||||
|
||||
public static class VisualVoicemailService.VisualVoicemailTask {
|
||||
method public final void finish();
|
||||
}
|
||||
|
||||
public final class VisualVoicemailSms implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public android.os.Bundle getFields();
|
||||
method public java.lang.String getMessageBody();
|
||||
method public android.telecom.PhoneAccountHandle getPhoneAccountHandle();
|
||||
method public java.lang.String getPrefix();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator<android.telephony.VisualVoicemailSms> CREATOR;
|
||||
}
|
||||
|
||||
public final class VisualVoicemailSmsFilterSettings implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator<android.telephony.VisualVoicemailSmsFilterSettings> CREATOR;
|
||||
field public static final java.lang.String DEFAULT_CLIENT_PREFIX = "//VVM";
|
||||
field public static final int DEFAULT_DESTINATION_PORT = -1; // 0xffffffff
|
||||
field public static final java.util.List<java.lang.String> DEFAULT_ORIGINATING_NUMBERS;
|
||||
field public static final int DESTINATION_PORT_ANY = -1; // 0xffffffff
|
||||
field public static final int DESTINATION_PORT_DATA_SMS = -2; // 0xfffffffe
|
||||
field public final java.lang.String clientPrefix;
|
||||
field public final int destinationPort;
|
||||
field public final java.util.List<java.lang.String> originatingNumbers;
|
||||
}
|
||||
|
||||
public static class VisualVoicemailSmsFilterSettings.Builder {
|
||||
ctor public VisualVoicemailSmsFilterSettings.Builder();
|
||||
method public android.telephony.VisualVoicemailSmsFilterSettings build();
|
||||
method public android.telephony.VisualVoicemailSmsFilterSettings.Builder setClientPrefix(java.lang.String);
|
||||
method public android.telephony.VisualVoicemailSmsFilterSettings.Builder setDestinationPort(int);
|
||||
method public android.telephony.VisualVoicemailSmsFilterSettings.Builder setOriginatingNumbers(java.util.List<java.lang.String>);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
package android.telephony.cdma {
|
||||
|
||||
@@ -38,6 +38,7 @@ package android {
|
||||
field public static final java.lang.String BIND_TELECOM_CONNECTION_SERVICE = "android.permission.BIND_TELECOM_CONNECTION_SERVICE";
|
||||
field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
|
||||
field public static final java.lang.String BIND_TV_INPUT = "android.permission.BIND_TV_INPUT";
|
||||
field public static final java.lang.String BIND_VISUAL_VOICEMAIL_SERVICE = "android.permission.BIND_VISUAL_VOICEMAIL_SERVICE";
|
||||
field public static final java.lang.String BIND_VOICE_INTERACTION = "android.permission.BIND_VOICE_INTERACTION";
|
||||
field public static final java.lang.String BIND_VPN_SERVICE = "android.permission.BIND_VPN_SERVICE";
|
||||
field public static final java.lang.String BIND_VR_LISTENER_SERVICE = "android.permission.BIND_VR_LISTENER_SERVICE";
|
||||
@@ -38029,6 +38030,54 @@ package android.telephony {
|
||||
method public void onReceiveUssdResponseFailed(java.lang.String, int);
|
||||
}
|
||||
|
||||
public abstract class VisualVoicemailService extends android.app.Service {
|
||||
ctor public VisualVoicemailService();
|
||||
method public android.os.IBinder onBind(android.content.Intent);
|
||||
method public abstract void onCellServiceConnected(android.telephony.VisualVoicemailService.VisualVoicemailTask, android.telecom.PhoneAccountHandle);
|
||||
method public abstract void onSimRemoved(android.telephony.VisualVoicemailService.VisualVoicemailTask, android.telecom.PhoneAccountHandle);
|
||||
method public abstract void onSmsReceived(android.telephony.VisualVoicemailService.VisualVoicemailTask, android.telephony.VisualVoicemailSms);
|
||||
method public abstract void onStopped(android.telephony.VisualVoicemailService.VisualVoicemailTask);
|
||||
method public static final void sendVisualVoicemailSms(android.content.Context, android.telecom.PhoneAccountHandle, java.lang.String, short, java.lang.String, android.app.PendingIntent);
|
||||
method public static final void setSmsFilterSettings(android.content.Context, android.telecom.PhoneAccountHandle, android.telephony.VisualVoicemailSmsFilterSettings);
|
||||
field public static final java.lang.String SERVICE_INTERFACE = "android.telephony.VisualVoicemailService";
|
||||
}
|
||||
|
||||
public static class VisualVoicemailService.VisualVoicemailTask {
|
||||
method public final void finish();
|
||||
}
|
||||
|
||||
public final class VisualVoicemailSms implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public android.os.Bundle getFields();
|
||||
method public java.lang.String getMessageBody();
|
||||
method public android.telecom.PhoneAccountHandle getPhoneAccountHandle();
|
||||
method public java.lang.String getPrefix();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator<android.telephony.VisualVoicemailSms> CREATOR;
|
||||
}
|
||||
|
||||
public final class VisualVoicemailSmsFilterSettings implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator<android.telephony.VisualVoicemailSmsFilterSettings> CREATOR;
|
||||
field public static final java.lang.String DEFAULT_CLIENT_PREFIX = "//VVM";
|
||||
field public static final int DEFAULT_DESTINATION_PORT = -1; // 0xffffffff
|
||||
field public static final java.util.List<java.lang.String> DEFAULT_ORIGINATING_NUMBERS;
|
||||
field public static final int DESTINATION_PORT_ANY = -1; // 0xffffffff
|
||||
field public static final int DESTINATION_PORT_DATA_SMS = -2; // 0xfffffffe
|
||||
field public final java.lang.String clientPrefix;
|
||||
field public final int destinationPort;
|
||||
field public final java.util.List<java.lang.String> originatingNumbers;
|
||||
}
|
||||
|
||||
public static class VisualVoicemailSmsFilterSettings.Builder {
|
||||
ctor public VisualVoicemailSmsFilterSettings.Builder();
|
||||
method public android.telephony.VisualVoicemailSmsFilterSettings build();
|
||||
method public android.telephony.VisualVoicemailSmsFilterSettings.Builder setClientPrefix(java.lang.String);
|
||||
method public android.telephony.VisualVoicemailSmsFilterSettings.Builder setDestinationPort(int);
|
||||
method public android.telephony.VisualVoicemailSmsFilterSettings.Builder setOriginatingNumbers(java.util.List<java.lang.String>);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
package android.telephony.cdma {
|
||||
|
||||
@@ -106,15 +106,7 @@ public class VoicemailContract {
|
||||
|
||||
/**
|
||||
* Broadcast intent to inform a new visual voicemail SMS has been received. This intent will
|
||||
* only be delivered to the voicemail client. The intent will have the following extra values:
|
||||
*
|
||||
* <ul>
|
||||
* <li><em>{@link #EXTRA_VOICEMAIL_SMS_TYPE}</em> - (String) The event type of the SMS. Common
|
||||
* values are "SYNC" or "STATUS"</li>
|
||||
* <li><em>{@link #EXTRA_VOICEMAIL_SMS_DATA}</em> - (Bundle) The fields sent by the SMS</li>
|
||||
* <li><em>{@link #EXTRA_VOICEMAIL_SMS_SUBID}</em> - (Integer) The subscription ID of the
|
||||
* phone account that received the SMS</li>
|
||||
* </ul>
|
||||
* only be delivered to the telephony service. {@link #EXTRA_VOICEMAIL_SMS} will be included.
|
||||
*/
|
||||
/** @hide */
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@@ -122,42 +114,11 @@ public class VoicemailContract {
|
||||
"android.intent.action.VOICEMAIL_SMS_RECEIVED";
|
||||
|
||||
/**
|
||||
* Optional extra included in {@link #ACTION_VOICEMAIL_SMS_RECEIVED} broadcast intents to
|
||||
* indicate the event type of the SMS. Common values are "SYNC" or "STATUS". The extra will not
|
||||
* exist if the framework cannot parse the SMS as voicemail but the carrier pattern indicates
|
||||
* it is.
|
||||
*/
|
||||
/** @hide */
|
||||
public static final String EXTRA_VOICEMAIL_SMS_PREFIX =
|
||||
"com.android.voicemail.extra.VOICEMAIL_SMS_PREFIX";
|
||||
|
||||
/**
|
||||
* Optional extra included in {@link #ACTION_VOICEMAIL_SMS_RECEIVED} broadcast intents to
|
||||
* indicate the fields sent by the SMS. The extra will not exist if the framework cannot
|
||||
* parse the SMS as voicemail but the carrier pattern indicates it is.
|
||||
*/
|
||||
/** @hide */
|
||||
public static final String EXTRA_VOICEMAIL_SMS_FIELDS =
|
||||
"com.android.voicemail.extra.VOICEMAIL_SMS_FIELDS";
|
||||
|
||||
/**
|
||||
* Extra included in {@link #ACTION_VOICEMAIL_SMS_RECEIVED} broadcast intents to indicate the
|
||||
* message body of the SMS. This extra is included if the framework cannot
|
||||
* parse the SMS as voicemail but the carrier pattern indicates it is.
|
||||
*/
|
||||
/**
|
||||
* Extra in {@link #ACTION_VOICEMAIL_SMS_RECEIVED} indicating the content of the SMS.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String EXTRA_VOICEMAIL_SMS_MESSAGE_BODY =
|
||||
"com.android.voicemail.extra.VOICEMAIL_SMS_MESSAGE_BODY";
|
||||
|
||||
/**
|
||||
* Extra included in {@link #ACTION_VOICEMAIL_SMS_RECEIVED} broadcast intents to indicate he
|
||||
* subscription ID of the phone account that received the SMS.
|
||||
*/
|
||||
/** @hide */
|
||||
public static final String EXTRA_VOICEMAIL_SMS_SUBID =
|
||||
"com.android.voicemail.extra.VOICEMAIL_SMS_SUBID";
|
||||
public static final String EXTRA_VOICEMAIL_SMS = "android.provider.extra.VOICEMAIL_SMS";
|
||||
|
||||
/**
|
||||
* Extra included in {@link Intent#ACTION_PROVIDER_CHANGED} broadcast intents to indicate if the
|
||||
|
||||
@@ -1540,6 +1540,14 @@
|
||||
<permission android:name="android.permission.BIND_INCALL_SERVICE"
|
||||
android:protectionLevel="signature|privileged" />
|
||||
|
||||
<!-- Must be required by a link {@link android.telephony.VisualVoicemailService} to ensure that
|
||||
only the system can bind to it.
|
||||
<p>Protection level: signature|privileged
|
||||
-->
|
||||
<permission
|
||||
android:name="android.permission.BIND_VISUAL_VOICEMAIL_SERVICE"
|
||||
android:protectionLevel="signature|privileged"/>
|
||||
|
||||
<!-- Must be required by a {@link android.telecom.CallScreeningService},
|
||||
to ensure that only the system can bind to it.
|
||||
<p>Protection level: signature|privileged
|
||||
|
||||
@@ -24,12 +24,14 @@ import android.annotation.SystemApi;
|
||||
import android.annotation.SdkConstant;
|
||||
import android.annotation.SdkConstant.SdkConstantType;
|
||||
import android.app.ActivityThread;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.Uri;
|
||||
import android.os.BatteryStats;
|
||||
import android.os.Binder;
|
||||
import android.provider.Settings;
|
||||
import android.provider.Settings.SettingNotFoundException;
|
||||
import android.os.Bundle;
|
||||
@@ -57,6 +59,7 @@ import com.android.internal.telephony.TelephonyProperties;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -2703,18 +2706,17 @@ public class TelephonyManager {
|
||||
|
||||
/**
|
||||
* @returns the settings of the visual voicemail SMS filter for a phone account set by the
|
||||
* package, or {@code null} if the filter is disabled.
|
||||
* current active visual voicemail client, or {@code null} if the filter is disabled.
|
||||
*
|
||||
* <p>Requires the calling app to have READ_PRIVILEGED_PHONE_STATE permission.
|
||||
*/
|
||||
/** @hide */
|
||||
@Nullable
|
||||
public VisualVoicemailSmsFilterSettings getVisualVoicemailSmsFilterSettings(String packageName,
|
||||
int subId) {
|
||||
public VisualVoicemailSmsFilterSettings getActiveVisualVoicemailSmsFilterSettings(int subId) {
|
||||
try {
|
||||
ITelephony telephony = getITelephony();
|
||||
if (telephony != null) {
|
||||
return telephony.getSystemVisualVoicemailSmsFilterSettings(packageName, subId);
|
||||
return telephony.getActiveVisualVoicemailSmsFilterSettings(subId);
|
||||
}
|
||||
} catch (RemoteException ex) {
|
||||
} catch (NullPointerException ex) {
|
||||
@@ -2723,6 +2725,35 @@ public class TelephonyManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a visual voicemail SMS. The IPC caller must be the current default dialer.
|
||||
*
|
||||
* <p>Requires Permission:
|
||||
* {@link android.Manifest.permission#SEND_SMS SEND_SMS}
|
||||
*
|
||||
* @param phoneAccountHandle The account to send the SMS with.
|
||||
* @param number The destination number.
|
||||
* @param port The destination port for data SMS, or 0 for text SMS.
|
||||
* @param text The message content. For data sms, it will be encoded as a UTF-8 byte stream.
|
||||
* @param sentIntent The sent intent passed to the {@link SmsManager}
|
||||
*
|
||||
* @see SmsManager#sendDataMessage(String, String, short, byte[], PendingIntent, PendingIntent)
|
||||
* @see SmsManager#sendTextMessage(String, String, String, PendingIntent, PendingIntent)
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public void sendVisualVoicemailSmsForSubscriber(int subId, String number, int port,
|
||||
String text, PendingIntent sentIntent) {
|
||||
try {
|
||||
ITelephony telephony = getITelephony();
|
||||
if (telephony != null) {
|
||||
telephony.sendVisualVoicemailSmsForSubscriber(
|
||||
mContext.getOpPackageName(), subId, number, port, text, sentIntent);
|
||||
}
|
||||
} catch (RemoteException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the voice mail count. Return 0 if unavailable, -1 if there are unread voice messages
|
||||
* but the count is unknown.
|
||||
|
||||
281
telephony/java/android/telephony/VisualVoicemailService.java
Normal file
281
telephony/java/android/telephony/VisualVoicemailService.java
Normal file
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
* 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 android.telephony;
|
||||
|
||||
import android.annotation.MainThread;
|
||||
import android.annotation.SdkConstant;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.os.RemoteException;
|
||||
import android.telecom.PhoneAccountHandle;
|
||||
import android.telecom.TelecomManager;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* This service is implemented by dialer apps that wishes to handle OMTP or similar visual
|
||||
* voicemails. Telephony binds to this service when the cell service is first connected, a visual
|
||||
* voicemail SMS has been received, or when a SIM has been removed. Telephony will only bind to the
|
||||
* default dialer for such events (See {@link TelecomManager#getDefaultDialerPackage()}). The
|
||||
* {@link android.service.carrier.CarrierMessagingService} precedes the VisualVoicemailService in
|
||||
* the SMS filtering chain and may intercept the visual voicemail SMS before it reaches this
|
||||
* service.
|
||||
* <p>
|
||||
* Below is an example manifest registration for a {@code VisualVoicemailService}.
|
||||
* <pre>
|
||||
* {@code
|
||||
* <service android:name="your.package.YourVisualVoicemailServiceImplementation"
|
||||
* android:permission="android.permission.BIND_VISUAL_VOICEMAIL_SERVICE">
|
||||
* <intent-filter>
|
||||
* <action android:name="android.telephony.VisualVoicemailService"/>
|
||||
* </intent-filter>
|
||||
* </service>
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public abstract class VisualVoicemailService extends Service {
|
||||
|
||||
private static final String TAG = "VvmService";
|
||||
|
||||
/**
|
||||
* The {@link Intent} that must be declared as handled by the service.
|
||||
*/
|
||||
@SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
|
||||
public static final String SERVICE_INTERFACE = "android.telephony.VisualVoicemailService";
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public static final int MSG_ON_CELL_SERVICE_CONNECTED = 1;
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public static final int MSG_ON_SMS_RECEIVED = 2;
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public static final int MSG_ON_SIM_REMOVED = 3;
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public static final int MSG_TASK_ENDED = 4;
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public static final int MSG_TASK_STOPPED = 5;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public static final String DATA_PHONE_ACCOUNT_HANDLE = "data_phone_account_handle";
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public static final String DATA_SMS = "data_sms";
|
||||
|
||||
/**
|
||||
* Represents a visual voicemail event which needs to be handled. While the task is being
|
||||
* processed telephony will hold a wakelock for the VisualVoicemailService. The service can
|
||||
* unblock the main thread and pass the task to a worker thread. Once the task is finished,
|
||||
* {@link VisualVoicemailTask#finish()} should be called to signal telephony to release the
|
||||
* resources. Telephony will call {@link VisualVoicemailService#onStopped(VisualVoicemailTask)}
|
||||
* when the task is going to be terminated before completion.
|
||||
*
|
||||
* @see #onCellServiceConnected(VisualVoicemailTask, PhoneAccountHandle)
|
||||
* @see #onSmsReceived(VisualVoicemailTask, VisualVoicemailSms)
|
||||
* @see #onSimRemoved(VisualVoicemailTask, PhoneAccountHandle)
|
||||
* @see #onStopped(VisualVoicemailTask)
|
||||
*/
|
||||
public static class VisualVoicemailTask {
|
||||
|
||||
private final int mTaskId;
|
||||
private final Messenger mReplyTo;
|
||||
|
||||
private VisualVoicemailTask(Messenger replyTo, int taskId) {
|
||||
mTaskId = taskId;
|
||||
mReplyTo = replyTo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call to signal telephony the task has completed. Must be called for every task.
|
||||
*/
|
||||
public final void finish() {
|
||||
Message message = Message.obtain();
|
||||
try {
|
||||
message.what = MSG_TASK_ENDED;
|
||||
message.arg1 = mTaskId;
|
||||
mReplyTo.send(message);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG,
|
||||
"Cannot send MSG_TASK_ENDED, remote handler no longer exist");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof VisualVoicemailTask)) {
|
||||
return false;
|
||||
}
|
||||
return mTaskId == ((VisualVoicemailTask) obj).mTaskId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mTaskId;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles messages sent by telephony.
|
||||
*/
|
||||
private final Messenger mMessenger = new Messenger(new Handler() {
|
||||
@Override
|
||||
public void handleMessage(final Message msg) {
|
||||
final PhoneAccountHandle handle = msg.getData()
|
||||
.getParcelable(DATA_PHONE_ACCOUNT_HANDLE);
|
||||
VisualVoicemailTask task = new VisualVoicemailTask(msg.replyTo, msg.arg1);
|
||||
switch (msg.what) {
|
||||
case MSG_ON_CELL_SERVICE_CONNECTED:
|
||||
onCellServiceConnected(task, handle);
|
||||
break;
|
||||
case MSG_ON_SMS_RECEIVED:
|
||||
VisualVoicemailSms sms = msg.getData().getParcelable(DATA_SMS);
|
||||
onSmsReceived(task, sms);
|
||||
break;
|
||||
case MSG_ON_SIM_REMOVED:
|
||||
onSimRemoved(task, handle);
|
||||
break;
|
||||
case MSG_TASK_STOPPED:
|
||||
onStopped(task);
|
||||
break;
|
||||
default:
|
||||
super.handleMessage(msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return mMessenger.getBinder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the cellular service is connected on a {@link PhoneAccountHandle} for the first
|
||||
* time, or when the carrier config has changed. It will not be called when the signal is lost
|
||||
* then restored.
|
||||
*
|
||||
* @param task The task representing this event. {@link VisualVoicemailTask#finish()} must be
|
||||
* called when the task is completed.
|
||||
* @param phoneAccountHandle The {@link PhoneAccountHandle} triggering this event.
|
||||
*/
|
||||
@MainThread
|
||||
public abstract void onCellServiceConnected(VisualVoicemailTask task,
|
||||
PhoneAccountHandle phoneAccountHandle);
|
||||
|
||||
/**
|
||||
* Called when a SMS matching the {@link VisualVoicemailSmsFilterSettings} set by
|
||||
* {@link #setSmsFilterSettings(Context, PhoneAccountHandle, VisualVoicemailSmsFilterSettings)}
|
||||
* is received.
|
||||
*
|
||||
* @param task The task representing this event. {@link VisualVoicemailTask#finish()} must be
|
||||
* called when the task is completed.
|
||||
* @param sms The content of the received SMS.
|
||||
*/
|
||||
@MainThread
|
||||
public abstract void onSmsReceived(VisualVoicemailTask task,
|
||||
VisualVoicemailSms sms);
|
||||
|
||||
/**
|
||||
* Called when a SIM is removed.
|
||||
*
|
||||
* @param task The task representing this event. {@link VisualVoicemailTask#finish()} must be
|
||||
* called when the task is completed.
|
||||
* @param phoneAccountHandle The {@link PhoneAccountHandle} triggering this event.
|
||||
*/
|
||||
@MainThread
|
||||
public abstract void onSimRemoved(VisualVoicemailTask task,
|
||||
PhoneAccountHandle phoneAccountHandle);
|
||||
|
||||
/**
|
||||
* Called before the system is about to terminate a task. The service should persist any
|
||||
* necessary data and call finish on the task immediately.
|
||||
*/
|
||||
@MainThread
|
||||
public abstract void onStopped(VisualVoicemailTask task);
|
||||
|
||||
/**
|
||||
* Set the visual voicemail SMS filter settings for the VisualVoicemailService.
|
||||
* {@link #onSmsReceived(VisualVoicemailTask, VisualVoicemailSms)} will be called when
|
||||
* a SMS matching the settings is received. The caller should have
|
||||
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} and implements a
|
||||
* VisualVoicemailService.
|
||||
* <p>
|
||||
* <p>Requires Permission:
|
||||
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
|
||||
*
|
||||
* @param phoneAccountHandle The account to apply the settings to.
|
||||
* @param settings The settings for the filter, or {@code null} to disable the filter.
|
||||
*/
|
||||
public final static void setSmsFilterSettings(Context context,
|
||||
PhoneAccountHandle phoneAccountHandle,
|
||||
VisualVoicemailSmsFilterSettings settings) {
|
||||
TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
|
||||
int subId = getSubId(context, phoneAccountHandle);
|
||||
if (settings == null) {
|
||||
telephonyManager.disableVisualVoicemailSmsFilter(subId);
|
||||
} else {
|
||||
telephonyManager.enableVisualVoicemailSmsFilter(subId, settings);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a visual voicemail SMS. The caller must be the current default dialer.
|
||||
* <p>
|
||||
* <p>Requires Permission:
|
||||
* {@link android.Manifest.permission#SEND_SMS SEND_SMS}
|
||||
*
|
||||
* @param phoneAccountHandle The account to send the SMS with.
|
||||
* @param number The destination number.
|
||||
* @param port The destination port for data SMS, or 0 for text SMS.
|
||||
* @param text The message content. For data sms, it will be encoded as a UTF-8 byte stream.
|
||||
* @param sentIntent The sent intent passed to the {@link SmsManager}
|
||||
* @see SmsManager#sendDataMessage(String, String, short, byte[], PendingIntent, PendingIntent)
|
||||
* @see SmsManager#sendTextMessage(String, String, String, PendingIntent, PendingIntent)
|
||||
*/
|
||||
public final static void sendVisualVoicemailSms(Context context,
|
||||
PhoneAccountHandle phoneAccountHandle, String number,
|
||||
short port, String text, PendingIntent sentIntent) {
|
||||
TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
|
||||
telephonyManager.sendVisualVoicemailSmsForSubscriber(getSubId(context, phoneAccountHandle),
|
||||
number, port, text, sentIntent);
|
||||
}
|
||||
|
||||
private static int getSubId(Context context, PhoneAccountHandle phoneAccountHandle) {
|
||||
TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
|
||||
TelecomManager telecomManager = context.getSystemService(TelecomManager.class);
|
||||
return telephonyManager
|
||||
.getSubIdForPhoneAccount(telecomManager.getPhoneAccount(phoneAccountHandle));
|
||||
}
|
||||
|
||||
}
|
||||
148
telephony/java/android/telephony/VisualVoicemailSms.java
Normal file
148
telephony/java/android/telephony/VisualVoicemailSms.java
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* 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 android.telephony;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.telecom.PhoneAccountHandle;
|
||||
import android.telephony.VisualVoicemailService.VisualVoicemailTask;
|
||||
|
||||
/**
|
||||
* Represents the content of a visual voicemail SMS. If a incoming SMS matches the {@link
|
||||
* VisualVoicemailSmsFilterSettings} set by the default dialer, {@link
|
||||
* VisualVoicemailService#onSmsReceived(VisualVoicemailTask, VisualVoicemailSms)} will be called.
|
||||
*/
|
||||
public final class VisualVoicemailSms implements Parcelable {
|
||||
|
||||
private final PhoneAccountHandle mPhoneAccountHandle;
|
||||
@Nullable
|
||||
private final String mPrefix;
|
||||
|
||||
@Nullable
|
||||
private final Bundle mFields;
|
||||
|
||||
private final String mMessageBody;
|
||||
|
||||
VisualVoicemailSms(Builder builder) {
|
||||
mPhoneAccountHandle = builder.mPhoneAccountHandle;
|
||||
mPrefix = builder.mPrefix;
|
||||
mFields = builder.mFields;
|
||||
mMessageBody = builder.mMessageBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link PhoneAccountHandle} that received the SMS.
|
||||
*/
|
||||
public PhoneAccountHandle getPhoneAccountHandle() {
|
||||
return mPhoneAccountHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* The event type of the SMS or {@code null} if the framework cannot parse the SMS as voicemail
|
||||
* but the carrier pattern indicates it is. Common values are "SYNC" or "STATUS".
|
||||
*/
|
||||
public String getPrefix() {
|
||||
return mPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* The key-value pairs sent by the SMS, or {@code null} if the framework cannot parse the SMS as
|
||||
* voicemail but the carrier pattern indicates it is.
|
||||
*/
|
||||
public Bundle getFields() {
|
||||
return mFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw message body of the received SMS.
|
||||
*/
|
||||
public String getMessageBody() {
|
||||
return mMessageBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for the {@link VisualVoicemailSms}. Internal use only.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static class Builder {
|
||||
|
||||
private PhoneAccountHandle mPhoneAccountHandle;
|
||||
private String mPrefix;
|
||||
private Bundle mFields;
|
||||
private String mMessageBody;
|
||||
|
||||
public VisualVoicemailSms build() {
|
||||
return new VisualVoicemailSms(this);
|
||||
}
|
||||
|
||||
public Builder setPhoneAccountHandle(PhoneAccountHandle phoneAccountHandle) {
|
||||
this.mPhoneAccountHandle = phoneAccountHandle;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPrefix(String prefix) {
|
||||
this.mPrefix = prefix;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setFields(Bundle fields) {
|
||||
this.mFields = fields;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setMessageBody(String messageBody) {
|
||||
this.mMessageBody = messageBody;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static final Creator<VisualVoicemailSms> CREATOR =
|
||||
new Creator<VisualVoicemailSms>() {
|
||||
@Override
|
||||
public VisualVoicemailSms createFromParcel(Parcel in) {
|
||||
return new Builder()
|
||||
.setPhoneAccountHandle((PhoneAccountHandle) in.readParcelable(null))
|
||||
.setPrefix(in.readString())
|
||||
.setFields(in.readBundle())
|
||||
.setMessageBody(in.readString())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VisualVoicemailSms[] newArray(int size) {
|
||||
return new VisualVoicemailSms[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeParcelable(getPhoneAccountHandle(), flags);
|
||||
dest.writeString(getPrefix());
|
||||
dest.writeBundle(getFields());
|
||||
dest.writeString(getMessageBody());
|
||||
}
|
||||
}
|
||||
@@ -15,9 +15,13 @@
|
||||
*/
|
||||
package android.telephony;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import android.telecom.PhoneAccountHandle;
|
||||
import android.telephony.VisualVoicemailService.VisualVoicemailTask;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -28,31 +32,26 @@ import java.util.List;
|
||||
* <p>[clientPrefix]:[prefix]:([key]=[value];)*
|
||||
*
|
||||
* <p>will be regarded as a visual voicemail SMS, and removed before reaching the SMS provider. The
|
||||
* intent {@link android.provider.VoicemailContract#ACTION_VOICEMAIL_SMS_RECEIVED} will then be sent
|
||||
* to the default dialer with the information extracted from the SMS.
|
||||
* {@link VisualVoicemailService} in the current default dialer will be bound and
|
||||
* {@link VisualVoicemailService#onSmsReceived(VisualVoicemailTask, VisualVoicemailSms)}
|
||||
* will called with the information extracted from the SMS.
|
||||
*
|
||||
* <p>Use {@link android.telephony.VisualVoicemailSmsFilterSettings.Builder} to construct this
|
||||
* class.
|
||||
*
|
||||
* @see android.telephony.TelephonyManager#enableVisualVoicemailSmsFilter
|
||||
*
|
||||
* @hide
|
||||
* @see VisualVoicemailService#setSmsFilterSettings(Context, PhoneAccountHandle, VisualVoicemailSmsFilterSettings)
|
||||
*/
|
||||
public class VisualVoicemailSmsFilterSettings implements Parcelable {
|
||||
public final class VisualVoicemailSmsFilterSettings implements Parcelable {
|
||||
|
||||
|
||||
/**
|
||||
* The visual voicemail SMS message does not have to be a data SMS, and can be directed to any
|
||||
* port.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int DESTINATION_PORT_ANY = -1;
|
||||
|
||||
/**
|
||||
* The visual voicemail SMS message can be directed to any port, but must be a data SMS.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int DESTINATION_PORT_DATA_SMS = -2;
|
||||
|
||||
@@ -62,8 +61,6 @@ public class VisualVoicemailSmsFilterSettings implements Parcelable {
|
||||
|
||||
/**
|
||||
* Builder class for {@link VisualVoicemailSmsFilterSettings} objects.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static class Builder {
|
||||
|
||||
@@ -171,4 +168,13 @@ public class VisualVoicemailSmsFilterSettings implements Parcelable {
|
||||
dest.writeInt(destinationPort);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "[VisualVoicemailSmsFilterSettings "
|
||||
+ "clientPrefix=" + clientPrefix
|
||||
+ ", originatingNumbers=" + originatingNumbers
|
||||
+ ", destinationPort=" + destinationPort
|
||||
+ "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.internal.telephony;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.ResultReceiver;
|
||||
@@ -481,9 +482,18 @@ interface ITelephony {
|
||||
VisualVoicemailSmsFilterSettings getVisualVoicemailSmsFilterSettings(String callingPackage,
|
||||
int subId);
|
||||
|
||||
// Get settings set by the package, requires READ_PRIVILEGED_PHONE_STATE permission
|
||||
VisualVoicemailSmsFilterSettings getSystemVisualVoicemailSmsFilterSettings(String packageName,
|
||||
int subId);
|
||||
/**
|
||||
* Get settings set by the current default dialer, Internal use only.
|
||||
* Requires READ_PRIVILEGED_PHONE_STATE permission.
|
||||
*/
|
||||
VisualVoicemailSmsFilterSettings getActiveVisualVoicemailSmsFilterSettings(int subId);
|
||||
|
||||
/**
|
||||
* Send a visual voicemail SMS. Internal use only.
|
||||
* Requires caller to be the default dialer and have SEND_SMS permission
|
||||
*/
|
||||
oneway void sendVisualVoicemailSmsForSubscriber(in String callingPackage, in int subId,
|
||||
in String number, in int port, in String text, in PendingIntent sentIntent);
|
||||
|
||||
/**
|
||||
* Returns the network type for data transmission
|
||||
|
||||
Reference in New Issue
Block a user