1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.telephony; 18 19 import android.annotation.MainThread; 20 import android.annotation.SdkConstant; 21 import android.annotation.SystemApi; 22 import android.app.PendingIntent; 23 import android.app.Service; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.os.Bundle; 27 import android.os.Handler; 28 import android.os.IBinder; 29 import android.os.Message; 30 import android.os.Messenger; 31 import android.os.RemoteException; 32 import android.telecom.PhoneAccountHandle; 33 import android.telecom.TelecomManager; 34 import android.util.Log; 35 36 /** 37 * This service is implemented by dialer apps that wishes to handle OMTP or similar visual 38 * voicemails. Telephony binds to this service when the cell service is first connected, a visual 39 * voicemail SMS has been received, or when a SIM has been removed. Telephony will only bind to the 40 * default dialer for such events (See {@link TelecomManager#getDefaultDialerPackage()}). The 41 * {@link android.service.carrier.CarrierMessagingService} precedes the VisualVoicemailService in 42 * the SMS filtering chain and may intercept the visual voicemail SMS before it reaches this 43 * service. 44 * <p> 45 * To extend this class, The service must be declared in the manifest file with 46 * the {@link android.Manifest.permission#BIND_VISUAL_VOICEMAIL_SERVICE} permission and include an 47 * intent filter with the {@link #SERVICE_INTERFACE} action. 48 * <p> 49 * Below is an example manifest registration for a {@code VisualVoicemailService}. 50 * <pre> 51 * {@code 52 * <service android:name="your.package.YourVisualVoicemailServiceImplementation" 53 * android:permission="android.permission.BIND_VISUAL_VOICEMAIL_SERVICE"> 54 * <intent-filter> 55 * <action android:name="android.telephony.VisualVoicemailService"/> 56 * </intent-filter> 57 * </service> 58 * } 59 * </pre> 60 */ 61 public abstract class VisualVoicemailService extends Service { 62 63 private static final String TAG = "VvmService"; 64 65 /** 66 * The {@link Intent} that must be declared as handled by the service. 67 */ 68 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) 69 public static final String SERVICE_INTERFACE = "android.telephony.VisualVoicemailService"; 70 71 /** 72 * @hide 73 */ 74 public static final int MSG_ON_CELL_SERVICE_CONNECTED = 1; 75 /** 76 * @hide 77 */ 78 public static final int MSG_ON_SMS_RECEIVED = 2; 79 /** 80 * @hide 81 */ 82 public static final int MSG_ON_SIM_REMOVED = 3; 83 /** 84 * @hide 85 */ 86 public static final int MSG_TASK_ENDED = 4; 87 /** 88 * @hide 89 */ 90 public static final int MSG_TASK_STOPPED = 5; 91 92 /** 93 * @hide 94 */ 95 public static final String DATA_PHONE_ACCOUNT_HANDLE = "data_phone_account_handle"; 96 /** 97 * @hide 98 */ 99 public static final String DATA_SMS = "data_sms"; 100 101 /** 102 * Represents a visual voicemail event which needs to be handled. While the task is being 103 * processed telephony will hold a wakelock for the VisualVoicemailService. The service can 104 * unblock the main thread and pass the task to a worker thread. Once the task is finished, 105 * {@link VisualVoicemailTask#finish()} should be called to signal telephony to release the 106 * resources. Telephony will call {@link VisualVoicemailService#onStopped(VisualVoicemailTask)} 107 * when the task is going to be terminated before completion. 108 * 109 * @see #onCellServiceConnected(VisualVoicemailTask, PhoneAccountHandle) 110 * @see #onSmsReceived(VisualVoicemailTask, VisualVoicemailSms) 111 * @see #onSimRemoved(VisualVoicemailTask, PhoneAccountHandle) 112 * @see #onStopped(VisualVoicemailTask) 113 */ 114 public static class VisualVoicemailTask { 115 116 private final int mTaskId; 117 private final Messenger mReplyTo; 118 VisualVoicemailTask(Messenger replyTo, int taskId)119 private VisualVoicemailTask(Messenger replyTo, int taskId) { 120 mTaskId = taskId; 121 mReplyTo = replyTo; 122 } 123 124 /** 125 * Call to signal telephony the task has completed. Must be called for every task. 126 */ finish()127 public final void finish() { 128 Message message = Message.obtain(); 129 try { 130 message.what = MSG_TASK_ENDED; 131 message.arg1 = mTaskId; 132 mReplyTo.send(message); 133 } catch (RemoteException e) { 134 Log.e(TAG, 135 "Cannot send MSG_TASK_ENDED, remote handler no longer exist"); 136 } 137 } 138 139 @Override equals(Object obj)140 public boolean equals(Object obj) { 141 if (!(obj instanceof VisualVoicemailTask)) { 142 return false; 143 } 144 return mTaskId == ((VisualVoicemailTask) obj).mTaskId; 145 } 146 147 @Override hashCode()148 public int hashCode() { 149 return mTaskId; 150 } 151 } 152 153 /** 154 * Handles messages sent by telephony. 155 */ 156 private final Messenger mMessenger = new Messenger(new Handler() { 157 @Override 158 public void handleMessage(final Message msg) { 159 final PhoneAccountHandle handle = msg.getData() 160 .getParcelable(DATA_PHONE_ACCOUNT_HANDLE); 161 VisualVoicemailTask task = new VisualVoicemailTask(msg.replyTo, msg.arg1); 162 switch (msg.what) { 163 case MSG_ON_CELL_SERVICE_CONNECTED: 164 onCellServiceConnected(task, handle); 165 break; 166 case MSG_ON_SMS_RECEIVED: 167 VisualVoicemailSms sms = msg.getData().getParcelable(DATA_SMS); 168 onSmsReceived(task, sms); 169 break; 170 case MSG_ON_SIM_REMOVED: 171 onSimRemoved(task, handle); 172 break; 173 case MSG_TASK_STOPPED: 174 onStopped(task); 175 break; 176 default: 177 super.handleMessage(msg); 178 break; 179 } 180 } 181 }); 182 183 @Override onBind(Intent intent)184 public IBinder onBind(Intent intent) { 185 return mMessenger.getBinder(); 186 } 187 188 /** 189 * Called when the cellular service is connected on a {@link PhoneAccountHandle} for the first 190 * time, or when the carrier config has changed. It will not be called when the signal is lost 191 * then restored. 192 * 193 * @param task The task representing this event. {@link VisualVoicemailTask#finish()} must be 194 * called when the task is completed. 195 * @param phoneAccountHandle The {@link PhoneAccountHandle} triggering this event. 196 */ 197 @MainThread onCellServiceConnected(VisualVoicemailTask task, PhoneAccountHandle phoneAccountHandle)198 public abstract void onCellServiceConnected(VisualVoicemailTask task, 199 PhoneAccountHandle phoneAccountHandle); 200 201 /** 202 * Called when a SMS matching the {@link VisualVoicemailSmsFilterSettings} set by 203 * {@link TelephonyManager#setVisualVoicemailSmsFilterSettings(VisualVoicemailSmsFilterSettings) 204 * } 205 * is received. 206 * 207 * @param task The task representing this event. {@link VisualVoicemailTask#finish()} must be 208 * called when the task is completed. 209 * @param sms The content of the received SMS. 210 */ 211 @MainThread onSmsReceived(VisualVoicemailTask task, VisualVoicemailSms sms)212 public abstract void onSmsReceived(VisualVoicemailTask task, 213 VisualVoicemailSms sms); 214 215 /** 216 * Called when a SIM is removed. 217 * 218 * @param task The task representing this event. {@link VisualVoicemailTask#finish()} must be 219 * called when the task is completed. 220 * @param phoneAccountHandle The {@link PhoneAccountHandle} triggering this event. 221 */ 222 @MainThread onSimRemoved(VisualVoicemailTask task, PhoneAccountHandle phoneAccountHandle)223 public abstract void onSimRemoved(VisualVoicemailTask task, 224 PhoneAccountHandle phoneAccountHandle); 225 226 /** 227 * Called before the system is about to terminate a task. The service should persist any 228 * necessary data and call finish on the task immediately. 229 */ 230 @MainThread onStopped(VisualVoicemailTask task)231 public abstract void onStopped(VisualVoicemailTask task); 232 233 /** 234 * Set the visual voicemail SMS filter settings for the VisualVoicemailService. 235 * {@link #onSmsReceived(VisualVoicemailTask, VisualVoicemailSms)} will be called when 236 * a SMS matching the settings is received. The caller should have 237 * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} and implements a 238 * VisualVoicemailService. 239 * <p> 240 * <p>Requires Permission: 241 * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} 242 * 243 * @param phoneAccountHandle The account to apply the settings to. 244 * @param settings The settings for the filter, or {@code null} to disable the filter. 245 * 246 * @hide 247 */ 248 @SystemApi setSmsFilterSettings(Context context, PhoneAccountHandle phoneAccountHandle, VisualVoicemailSmsFilterSettings settings)249 public static final void setSmsFilterSettings(Context context, 250 PhoneAccountHandle phoneAccountHandle, 251 VisualVoicemailSmsFilterSettings settings) { 252 TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 253 int subId = getSubId(context, phoneAccountHandle); 254 if (settings == null) { 255 telephonyManager.disableVisualVoicemailSmsFilter(subId); 256 } else { 257 telephonyManager.enableVisualVoicemailSmsFilter(subId, settings); 258 } 259 } 260 261 /** 262 * Send a visual voicemail SMS. The caller must be the current default dialer. 263 * <p> 264 * <p>Requires Permission: 265 * {@link android.Manifest.permission#SEND_SMS SEND_SMS} 266 * 267 * @param phoneAccountHandle The account to send the SMS with. 268 * @param number The destination number. 269 * @param port The destination port for data SMS, or 0 for text SMS. 270 * @param text The message content. For data sms, it will be encoded as a UTF-8 byte stream. 271 * @param sentIntent The sent intent passed to the {@link SmsManager} 272 * 273 * @throws SecurityException if the caller is not the current default dialer 274 * 275 * @see SmsManager#sendDataMessage(String, String, short, byte[], PendingIntent, PendingIntent) 276 * @see SmsManager#sendTextMessage(String, String, String, PendingIntent, PendingIntent) 277 * 278 * @hide 279 */ 280 @SystemApi sendVisualVoicemailSms(Context context, PhoneAccountHandle phoneAccountHandle, String number, short port, String text, PendingIntent sentIntent)281 public static final void sendVisualVoicemailSms(Context context, 282 PhoneAccountHandle phoneAccountHandle, String number, 283 short port, String text, PendingIntent sentIntent) { 284 TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 285 telephonyManager.sendVisualVoicemailSmsForSubscriber(getSubId(context, phoneAccountHandle), 286 number, port, text, sentIntent); 287 } 288 getSubId(Context context, PhoneAccountHandle phoneAccountHandle)289 private static int getSubId(Context context, PhoneAccountHandle phoneAccountHandle) { 290 TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 291 TelecomManager telecomManager = context.getSystemService(TelecomManager.class); 292 return telephonyManager 293 .getSubIdForPhoneAccount(telecomManager.getPhoneAccount(phoneAccountHandle)); 294 } 295 296 } 297