1 /*
2  * Copyright (C) 2015 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 com.android.messaging.datamodel;
18 
19 import android.app.IntentService;
20 import android.content.Intent;
21 import android.net.Uri;
22 import android.os.Bundle;
23 import androidx.core.app.RemoteInput;
24 import android.telephony.TelephonyManager;
25 import android.text.TextUtils;
26 
27 import com.android.messaging.datamodel.action.InsertNewMessageAction;
28 import com.android.messaging.datamodel.action.UpdateMessageNotificationAction;
29 import com.android.messaging.datamodel.data.MessageData;
30 import com.android.messaging.datamodel.data.ParticipantData;
31 import com.android.messaging.sms.MmsUtils;
32 import com.android.messaging.ui.UIIntents;
33 import com.android.messaging.ui.conversationlist.ConversationListActivity;
34 import com.android.messaging.util.LogUtil;
35 
36 /**
37  * Respond to a special intent and send an SMS message without the user's intervention, unless
38  * the intent extra "showUI" is true.
39  */
40 public class NoConfirmationSmsSendService extends IntentService {
41     private static final String TAG = LogUtil.BUGLE_TAG;
42 
43     private static final String EXTRA_SUBSCRIPTION = "subscription";
44     public static final String EXTRA_SELF_ID = "self_id";
45 
NoConfirmationSmsSendService()46     public NoConfirmationSmsSendService() {
47         // Class name will be the thread name.
48         super(NoConfirmationSmsSendService.class.getName());
49 
50         // Intent should be redelivered if the process gets killed before completing the job.
51         setIntentRedelivery(true);
52     }
53 
54     @Override
onHandleIntent(final Intent intent)55     protected void onHandleIntent(final Intent intent) {
56         if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
57             LogUtil.v(TAG, "NoConfirmationSmsSendService onHandleIntent");
58         }
59 
60         final String action = intent.getAction();
61         if (!TelephonyManager.ACTION_RESPOND_VIA_MESSAGE.equals(action)) {
62             if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
63                 LogUtil.v(TAG, "NoConfirmationSmsSendService onHandleIntent wrong action: " +
64                     action);
65             }
66             return;
67         }
68         final Bundle extras = intent.getExtras();
69         if (extras == null) {
70             if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
71                 LogUtil.v(TAG, "Called to send SMS but no extras");
72             }
73             return;
74         }
75 
76         // Get all possible extras from intent
77         final String conversationId =
78                 intent.getStringExtra(UIIntents.UI_INTENT_EXTRA_CONVERSATION_ID);
79         final String selfId = intent.getStringExtra(EXTRA_SELF_ID);
80         final boolean requiresMms = intent.getBooleanExtra(UIIntents.UI_INTENT_EXTRA_REQUIRES_MMS,
81                 false);
82         final String message = getText(intent, Intent.EXTRA_TEXT);
83         final String subject = getText(intent, Intent.EXTRA_SUBJECT);
84         final int subId = extras.getInt(EXTRA_SUBSCRIPTION, ParticipantData.DEFAULT_SELF_SUB_ID);
85 
86         final Uri intentUri = intent.getData();
87         final String recipients = intentUri != null ? MmsUtils.getSmsRecipients(intentUri) : null;
88 
89         if (TextUtils.isEmpty(recipients) && TextUtils.isEmpty(conversationId)) {
90             if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
91                 LogUtil.v(TAG, "Both conversationId and recipient(s) cannot be empty");
92             }
93             return;
94         }
95 
96         if (extras.getBoolean("showUI", false)) {
97             startActivity(new Intent(this, ConversationListActivity.class));
98         } else {
99             if (TextUtils.isEmpty(message)) {
100                 if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
101                     LogUtil.v(TAG, "Message cannot be empty");
102                 }
103                 return;
104             }
105 
106             // TODO: it's possible that a long message would require sending it via mms,
107             // but we're not testing for that here and we're sending the message as an sms.
108 
109             if (TextUtils.isEmpty(conversationId)) {
110                 InsertNewMessageAction.insertNewMessage(subId, recipients, message, subject);
111             } else {
112                 MessageData messageData = null;
113                 if (requiresMms) {
114                     if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
115                         LogUtil.v(TAG, "Auto-sending MMS message in conversation: " +
116                                 conversationId);
117                     }
118                     messageData = MessageData.createDraftMmsMessage(conversationId, selfId, message,
119                             subject);
120                 } else {
121                     if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
122                         LogUtil.v(TAG, "Auto-sending SMS message in conversation: " +
123                                 conversationId);
124                     }
125                     messageData = MessageData.createDraftSmsMessage(conversationId, selfId,
126                             message);
127                 }
128                 InsertNewMessageAction.insertNewMessage(messageData);
129             }
130             UpdateMessageNotificationAction.updateMessageNotification();
131         }
132     }
133 
getText(final Intent intent, final String textType)134     private String getText(final Intent intent, final String textType) {
135         final String message = intent.getStringExtra(textType);
136         if (message == null) {
137             final Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
138             if (remoteInput != null) {
139                 final CharSequence extra = remoteInput.getCharSequence(textType);
140                 if (extra != null) {
141                     return extra.toString();
142                 }
143             }
144         }
145         return message;
146     }
147 
148 }
149