blob: c0f10a3c86e1a222884ceb8fea3fd67bcd6b9bef [file] [log] [blame]
Ye Wend97e1fd2014-07-24 12:56:45 -07001/*
2 * Copyright (C) 2014 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
17package com.android.server;
18
Ye Wend97e1fd2014-07-24 12:56:45 -070019import android.Manifest;
20import android.app.AppOpsManager;
21import android.app.PendingIntent;
22import android.content.ComponentName;
Tom Taylor86201db2014-11-24 09:36:43 -080023import android.content.ContentProvider;
Ye Wend97e1fd2014-07-24 12:56:45 -070024import android.content.ContentValues;
25import android.content.Context;
26import android.content.Intent;
27import android.content.ServiceConnection;
28import android.content.pm.PackageManager;
29import android.net.Uri;
30import android.os.Binder;
Shri Borde72379722014-09-02 09:48:49 -070031import android.os.Bundle;
Ye Wend97e1fd2014-07-24 12:56:45 -070032import android.os.Handler;
33import android.os.IBinder;
34import android.os.Message;
35import android.os.RemoteException;
Ye Wen724dbbd72014-10-07 15:33:51 -070036import android.os.SystemClock;
Tom Taylor86201db2014-11-24 09:36:43 -080037import android.os.UserHandle;
Cheuksan Wang5cec9202014-12-16 13:40:36 -080038import android.service.carrier.CarrierMessagingService;
Ye Wen61c8d232015-04-01 11:27:14 -070039import android.telephony.SmsManager;
Leland Miller02c85242019-07-08 15:31:02 -070040import android.telephony.SubscriptionManager;
Ye Wend97e1fd2014-07-24 12:56:45 -070041import android.telephony.TelephonyManager;
42import android.util.Slog;
43
Ye Wenbdc3a462014-11-11 11:17:28 -080044import com.android.internal.telephony.IMms;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -070045import com.android.server.uri.UriGrantsManagerInternal;
Ye Wenbdc3a462014-11-11 11:17:28 -080046
Tom Taylor86201db2014-11-24 09:36:43 -080047import java.util.List;
48
Ye Wend97e1fd2014-07-24 12:56:45 -070049/**
50 * This class is a proxy for MmsService APIs. We need this because MmsService runs
51 * in phone process and may crash anytime. This manages a connection to the actual
52 * MmsService and bridges the public SMS/MMS APIs with MmsService implementation.
53 */
54public class MmsServiceBroker extends SystemService {
55 private static final String TAG = "MmsServiceBroker";
56
57 private static final ComponentName MMS_SERVICE_COMPONENT =
58 new ComponentName("com.android.mms.service", "com.android.mms.service.MmsService");
59
60 private static final int MSG_TRY_CONNECTING = 1;
61
Ye Wenfa58ac02014-07-31 17:15:30 -070062 private static final Uri FAKE_SMS_SENT_URI = Uri.parse("content://sms/sent/0");
63 private static final Uri FAKE_MMS_SENT_URI = Uri.parse("content://mms/sent/0");
64 private static final Uri FAKE_SMS_DRAFT_URI = Uri.parse("content://sms/draft/0");
65 private static final Uri FAKE_MMS_DRAFT_URI = Uri.parse("content://mms/draft/0");
66
Ye Wen724dbbd72014-10-07 15:33:51 -070067 private static final long SERVICE_CONNECTION_WAIT_TIME_MS = 4 * 1000L; // 4 seconds
68 private static final long RETRY_DELAY_ON_DISCONNECTION_MS = 3 * 1000L; // 3 seconds
69
Ye Wend97e1fd2014-07-24 12:56:45 -070070 private Context mContext;
71 // The actual MMS service instance to invoke
72 private volatile IMms mService;
Ye Wend97e1fd2014-07-24 12:56:45 -070073
74 // Cached system service instances
75 private volatile AppOpsManager mAppOpsManager = null;
76 private volatile PackageManager mPackageManager = null;
77 private volatile TelephonyManager mTelephonyManager = null;
78
79 private final Handler mConnectionHandler = new Handler() {
80 @Override
81 public void handleMessage(Message msg) {
82 switch (msg.what) {
83 case MSG_TRY_CONNECTING:
84 tryConnecting();
85 break;
86 default:
87 Slog.e(TAG, "Unknown message");
88 }
89 }
90 };
91
92 private ServiceConnection mConnection = new ServiceConnection() {
93 @Override
94 public void onServiceConnected(ComponentName name, IBinder service) {
95 Slog.i(TAG, "MmsService connected");
96 synchronized (MmsServiceBroker.this) {
Jeff Sharkey0a17db12016-11-04 11:23:46 -060097 mService = IMms.Stub.asInterface(Binder.allowBlocking(service));
Ye Wen724dbbd72014-10-07 15:33:51 -070098 MmsServiceBroker.this.notifyAll();
Ye Wend97e1fd2014-07-24 12:56:45 -070099 }
100 }
101
102 @Override
103 public void onServiceDisconnected(ComponentName name) {
104 Slog.i(TAG, "MmsService unexpectedly disconnected");
105 synchronized (MmsServiceBroker.this) {
106 mService = null;
Ye Wen724dbbd72014-10-07 15:33:51 -0700107 MmsServiceBroker.this.notifyAll();
Ye Wend97e1fd2014-07-24 12:56:45 -0700108 }
Ye Wen724dbbd72014-10-07 15:33:51 -0700109 // Retry connecting, but not too eager (with a delay)
110 // since it may come back by itself.
111 mConnectionHandler.sendMessageDelayed(
112 mConnectionHandler.obtainMessage(MSG_TRY_CONNECTING),
113 RETRY_DELAY_ON_DISCONNECTION_MS);
Ye Wend97e1fd2014-07-24 12:56:45 -0700114 }
115 };
116
Ye Wen61c8d232015-04-01 11:27:14 -0700117 // Instance of IMms for returning failure to service API caller,
118 // used when MmsService cannot be connected.
119 private final IMms mServiceStubForFailure = new IMms() {
120
121 @Override
122 public IBinder asBinder() {
123 return null;
124 }
125
126 @Override
127 public void sendMessage(int subId, String callingPkg, Uri contentUri, String locationUrl,
128 Bundle configOverrides, PendingIntent sentIntent) throws RemoteException {
129 returnPendingIntentWithError(sentIntent);
130 }
131
132 @Override
133 public void downloadMessage(int subId, String callingPkg, String locationUrl,
134 Uri contentUri, Bundle configOverrides, PendingIntent downloadedIntent)
135 throws RemoteException {
136 returnPendingIntentWithError(downloadedIntent);
137 }
138
139 @Override
140 public Bundle getCarrierConfigValues(int subId) throws RemoteException {
141 return null;
142 }
143
144 @Override
145 public Uri importTextMessage(String callingPkg, String address, int type, String text,
146 long timestampMillis, boolean seen, boolean read) throws RemoteException {
147 return null;
148 }
149
150 @Override
151 public Uri importMultimediaMessage(String callingPkg, Uri contentUri, String messageId,
152 long timestampSecs, boolean seen, boolean read) throws RemoteException {
153 return null;
154 }
155
156 @Override
157 public boolean deleteStoredMessage(String callingPkg, Uri messageUri)
158 throws RemoteException {
159 return false;
160 }
161
162 @Override
163 public boolean deleteStoredConversation(String callingPkg, long conversationId)
164 throws RemoteException {
165 return false;
166 }
167
168 @Override
169 public boolean updateStoredMessageStatus(String callingPkg, Uri messageUri,
170 ContentValues statusValues) throws RemoteException {
171 return false;
172 }
173
174 @Override
175 public boolean archiveStoredConversation(String callingPkg, long conversationId,
176 boolean archived) throws RemoteException {
177 return false;
178 }
179
180 @Override
181 public Uri addTextMessageDraft(String callingPkg, String address, String text)
182 throws RemoteException {
183 return null;
184 }
185
186 @Override
187 public Uri addMultimediaMessageDraft(String callingPkg, Uri contentUri)
188 throws RemoteException {
189 return null;
190 }
191
192 @Override
193 public void sendStoredMessage(int subId, String callingPkg, Uri messageUri,
194 Bundle configOverrides, PendingIntent sentIntent) throws RemoteException {
195 returnPendingIntentWithError(sentIntent);
196 }
197
198 @Override
199 public void setAutoPersisting(String callingPkg, boolean enabled) throws RemoteException {
200 // Do nothing
201 }
202
203 @Override
204 public boolean getAutoPersisting() throws RemoteException {
205 return false;
206 }
207
208 private void returnPendingIntentWithError(PendingIntent pendingIntent) {
209 try {
210 pendingIntent.send(mContext, SmsManager.MMS_ERROR_UNSPECIFIED, null);
211 } catch (PendingIntent.CanceledException e) {
212 Slog.e(TAG, "Failed to return pending intent result", e);
213 }
214 }
215 };
216
Ye Wend97e1fd2014-07-24 12:56:45 -0700217 public MmsServiceBroker(Context context) {
218 super(context);
219 mContext = context;
220 mService = null;
Ye Wend97e1fd2014-07-24 12:56:45 -0700221 }
222
223 @Override
224 public void onStart() {
225 publishBinderService("imms", new BinderService());
226 }
227
228 public void systemRunning() {
Ye Wenbdc3a462014-11-11 11:17:28 -0800229 Slog.i(TAG, "Delay connecting to MmsService until an API is called");
Ye Wend97e1fd2014-07-24 12:56:45 -0700230 }
231
232 private void tryConnecting() {
233 Slog.i(TAG, "Connecting to MmsService");
234 synchronized (this) {
Ye Wen724dbbd72014-10-07 15:33:51 -0700235 if (mService != null) {
236 Slog.d(TAG, "Already connected");
Ye Wend97e1fd2014-07-24 12:56:45 -0700237 return;
238 }
239 final Intent intent = new Intent();
240 intent.setComponent(MMS_SERVICE_COMPONENT);
241 try {
Ye Wen724dbbd72014-10-07 15:33:51 -0700242 if (!mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)) {
243 Slog.e(TAG, "Failed to bind to MmsService");
Ye Wend97e1fd2014-07-24 12:56:45 -0700244 }
245 } catch (SecurityException e) {
Ye Wen724dbbd72014-10-07 15:33:51 -0700246 Slog.e(TAG, "Forbidden to bind to MmsService", e);
Ye Wend97e1fd2014-07-24 12:56:45 -0700247 }
248 }
249 }
250
Ye Wen61c8d232015-04-01 11:27:14 -0700251 private IMms getOrConnectService() {
Ye Wen724dbbd72014-10-07 15:33:51 -0700252 synchronized (this) {
Ye Wen61c8d232015-04-01 11:27:14 -0700253 if (mService != null) {
254 return mService;
Ye Wen724dbbd72014-10-07 15:33:51 -0700255 }
Ye Wen61c8d232015-04-01 11:27:14 -0700256 // Service is not connected. Try blocking connecting.
257 Slog.w(TAG, "MmsService not connected. Try connecting...");
258 mConnectionHandler.sendMessage(
259 mConnectionHandler.obtainMessage(MSG_TRY_CONNECTING));
260 final long shouldEnd =
261 SystemClock.elapsedRealtime() + SERVICE_CONNECTION_WAIT_TIME_MS;
262 long waitTime = SERVICE_CONNECTION_WAIT_TIME_MS;
263 while (waitTime > 0) {
264 try {
265 // TODO: consider using Java concurrent construct instead of raw object wait
266 this.wait(waitTime);
267 } catch (InterruptedException e) {
268 Slog.w(TAG, "Connection wait interrupted", e);
269 }
270 if (mService != null) {
271 // Success
272 return mService;
273 }
274 // Calculate remaining waiting time to make sure we wait the full timeout period
275 waitTime = shouldEnd - SystemClock.elapsedRealtime();
276 }
277 // Timed out. Something's really wrong.
278 Slog.e(TAG, "Can not connect to MmsService (timed out)");
279 return null;
Ye Wend97e1fd2014-07-24 12:56:45 -0700280 }
281 }
282
283 /**
Ye Wen61c8d232015-04-01 11:27:14 -0700284 * Make sure to return a non-empty service instance. Return the connected MmsService
285 * instance, if not connected, try connecting. If fail to connect, return a fake service
286 * instance which returns failure to service caller.
287 *
288 * @return a non-empty service instance, real or fake
Ye Wend97e1fd2014-07-24 12:56:45 -0700289 */
290 private IMms getServiceGuarded() {
Ye Wen61c8d232015-04-01 11:27:14 -0700291 final IMms service = getOrConnectService();
292 if (service != null) {
293 return service;
294 }
295 return mServiceStubForFailure;
Ye Wend97e1fd2014-07-24 12:56:45 -0700296 }
297
298 private AppOpsManager getAppOpsManager() {
299 if (mAppOpsManager == null) {
300 mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
301 }
302 return mAppOpsManager;
303 }
304
305 private PackageManager getPackageManager() {
306 if (mPackageManager == null) {
307 mPackageManager = mContext.getPackageManager();
308 }
309 return mPackageManager;
310 }
311
312 private TelephonyManager getTelephonyManager() {
313 if (mTelephonyManager == null) {
314 mTelephonyManager = (TelephonyManager) mContext.getSystemService(
315 Context.TELEPHONY_SERVICE);
316 }
317 return mTelephonyManager;
318 }
319
Ye Wenbdc3a462014-11-11 11:17:28 -0800320 private String getCallingPackageName() {
321 final String[] packages = getPackageManager().getPackagesForUid(Binder.getCallingUid());
322 if (packages != null && packages.length > 0) {
323 return packages[0];
324 }
325 return "unknown";
326 }
327
Ye Wend97e1fd2014-07-24 12:56:45 -0700328 // Service API calls implementation, proxied to the real MmsService in "com.android.mms.service"
329 private final class BinderService extends IMms.Stub {
Tom Taylor86201db2014-11-24 09:36:43 -0800330 private static final String PHONE_PACKAGE_NAME = "com.android.phone";
331
Ye Wend97e1fd2014-07-24 12:56:45 -0700332 @Override
Wink Saville63f03dd2014-10-23 10:44:45 -0700333 public void sendMessage(int subId, String callingPkg, Uri contentUri,
Ye Wen8179c2a2014-09-04 15:36:11 -0700334 String locationUrl, Bundle configOverrides, PendingIntent sentIntent)
Leland Miller02c85242019-07-08 15:31:02 -0700335 throws RemoteException {
Ye Wenbdc3a462014-11-11 11:17:28 -0800336 Slog.d(TAG, "sendMessage() by " + callingPkg);
Ye Wend97e1fd2014-07-24 12:56:45 -0700337 mContext.enforceCallingPermission(Manifest.permission.SEND_SMS, "Send MMS message");
338 if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
339 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Sahin Caliskan7c766b22018-10-30 10:20:08 -0700340 Slog.e(TAG, callingPkg + " is not allowed to call sendMessage()");
Ye Wend97e1fd2014-07-24 12:56:45 -0700341 return;
342 }
Tom Taylor86201db2014-11-24 09:36:43 -0800343 contentUri = adjustUriForUserAndGrantPermission(contentUri,
Cheuksan Wang5cec9202014-12-16 13:40:36 -0800344 CarrierMessagingService.SERVICE_INTERFACE,
Leland Miller02c85242019-07-08 15:31:02 -0700345 Intent.FLAG_GRANT_READ_URI_PERMISSION,
346 subId);
Julian Odell31ef14d2014-08-25 17:53:52 -0700347 getServiceGuarded().sendMessage(subId, callingPkg, contentUri, locationUrl,
348 configOverrides, sentIntent);
Ye Wend97e1fd2014-07-24 12:56:45 -0700349 }
350
351 @Override
Wink Saville63f03dd2014-10-23 10:44:45 -0700352 public void downloadMessage(int subId, String callingPkg, String locationUrl,
Ye Wen8179c2a2014-09-04 15:36:11 -0700353 Uri contentUri, Bundle configOverrides,
Julian Odell31ef14d2014-08-25 17:53:52 -0700354 PendingIntent downloadedIntent) throws RemoteException {
Ye Wenbdc3a462014-11-11 11:17:28 -0800355 Slog.d(TAG, "downloadMessage() by " + callingPkg);
Ye Wend97e1fd2014-07-24 12:56:45 -0700356 mContext.enforceCallingPermission(Manifest.permission.RECEIVE_MMS,
357 "Download MMS message");
358 if (getAppOpsManager().noteOp(AppOpsManager.OP_RECEIVE_MMS, Binder.getCallingUid(),
359 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Sahin Caliskan7c766b22018-10-30 10:20:08 -0700360 Slog.e(TAG, callingPkg + " is not allowed to call downloadMessage()");
Ye Wend97e1fd2014-07-24 12:56:45 -0700361 return;
362 }
Tom Taylor86201db2014-11-24 09:36:43 -0800363 contentUri = adjustUriForUserAndGrantPermission(contentUri,
Cheuksan Wang5cec9202014-12-16 13:40:36 -0800364 CarrierMessagingService.SERVICE_INTERFACE,
Leland Miller02c85242019-07-08 15:31:02 -0700365 Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
366 subId);
Tom Taylor86201db2014-11-24 09:36:43 -0800367
Julian Odell31ef14d2014-08-25 17:53:52 -0700368 getServiceGuarded().downloadMessage(subId, callingPkg, locationUrl, contentUri,
369 configOverrides, downloadedIntent);
Ye Wend97e1fd2014-07-24 12:56:45 -0700370 }
371
372 @Override
Wink Saville63f03dd2014-10-23 10:44:45 -0700373 public Bundle getCarrierConfigValues(int subId) throws RemoteException {
Ye Wenbdc3a462014-11-11 11:17:28 -0800374 Slog.d(TAG, "getCarrierConfigValues() by " + getCallingPackageName());
Shri Borde72379722014-09-02 09:48:49 -0700375 return getServiceGuarded().getCarrierConfigValues(subId);
Ye Wend97e1fd2014-07-24 12:56:45 -0700376 }
377
378 @Override
379 public Uri importTextMessage(String callingPkg, String address, int type, String text,
380 long timestampMillis, boolean seen, boolean read) throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700381 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
382 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Ye Wenfa58ac02014-07-31 17:15:30 -0700383 // Silently fail AppOps failure due to not being the default SMS app
384 // while writing the TelephonyProvider
385 return FAKE_SMS_SENT_URI;
Ye Wend97e1fd2014-07-24 12:56:45 -0700386 }
387 return getServiceGuarded().importTextMessage(
388 callingPkg, address, type, text, timestampMillis, seen, read);
389 }
390
391 @Override
Julian Odell31ef14d2014-08-25 17:53:52 -0700392 public Uri importMultimediaMessage(String callingPkg, Uri contentUri,
393 String messageId, long timestampSecs, boolean seen, boolean read)
Leland Miller02c85242019-07-08 15:31:02 -0700394 throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700395 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
396 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Ye Wenfa58ac02014-07-31 17:15:30 -0700397 // Silently fail AppOps failure due to not being the default SMS app
398 // while writing the TelephonyProvider
399 return FAKE_MMS_SENT_URI;
Ye Wend97e1fd2014-07-24 12:56:45 -0700400 }
401 return getServiceGuarded().importMultimediaMessage(
Julian Odell31ef14d2014-08-25 17:53:52 -0700402 callingPkg, contentUri, messageId, timestampSecs, seen, read);
Ye Wend97e1fd2014-07-24 12:56:45 -0700403 }
404
405 @Override
406 public boolean deleteStoredMessage(String callingPkg, Uri messageUri)
407 throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700408 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
409 callingPkg) != AppOpsManager.MODE_ALLOWED) {
410 return false;
411 }
412 return getServiceGuarded().deleteStoredMessage(callingPkg, messageUri);
413 }
414
415 @Override
416 public boolean deleteStoredConversation(String callingPkg, long conversationId)
417 throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700418 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
419 callingPkg) != AppOpsManager.MODE_ALLOWED) {
420 return false;
421 }
422 return getServiceGuarded().deleteStoredConversation(callingPkg, conversationId);
423 }
424
425 @Override
426 public boolean updateStoredMessageStatus(String callingPkg, Uri messageUri,
427 ContentValues statusValues) throws RemoteException {
Svetoslav6c589572015-04-16 16:19:24 -0700428 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
429 callingPkg) != AppOpsManager.MODE_ALLOWED) {
430 return false;
431 }
Ye Wend97e1fd2014-07-24 12:56:45 -0700432 return getServiceGuarded()
433 .updateStoredMessageStatus(callingPkg, messageUri, statusValues);
434 }
435
436 @Override
Ye Wena3dbd102014-07-29 10:42:25 -0700437 public boolean archiveStoredConversation(String callingPkg, long conversationId,
438 boolean archived) throws RemoteException {
Svetoslav6c589572015-04-16 16:19:24 -0700439 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
440 callingPkg) != AppOpsManager.MODE_ALLOWED) {
441 return false;
442 }
Ye Wena3dbd102014-07-29 10:42:25 -0700443 return getServiceGuarded()
444 .archiveStoredConversation(callingPkg, conversationId, archived);
445 }
446
447 @Override
Ye Wend97e1fd2014-07-24 12:56:45 -0700448 public Uri addTextMessageDraft(String callingPkg, String address, String text)
449 throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700450 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
451 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Ye Wenfa58ac02014-07-31 17:15:30 -0700452 // Silently fail AppOps failure due to not being the default SMS app
453 // while writing the TelephonyProvider
454 return FAKE_SMS_DRAFT_URI;
Ye Wend97e1fd2014-07-24 12:56:45 -0700455 }
456 return getServiceGuarded().addTextMessageDraft(callingPkg, address, text);
457 }
458
459 @Override
Julian Odell31ef14d2014-08-25 17:53:52 -0700460 public Uri addMultimediaMessageDraft(String callingPkg, Uri contentUri)
461 throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700462 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
463 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Ye Wenfa58ac02014-07-31 17:15:30 -0700464 // Silently fail AppOps failure due to not being the default SMS app
465 // while writing the TelephonyProvider
466 return FAKE_MMS_DRAFT_URI;
Ye Wend97e1fd2014-07-24 12:56:45 -0700467 }
Julian Odell31ef14d2014-08-25 17:53:52 -0700468 return getServiceGuarded().addMultimediaMessageDraft(callingPkg, contentUri);
Ye Wend97e1fd2014-07-24 12:56:45 -0700469 }
470
471 @Override
Wink Saville63f03dd2014-10-23 10:44:45 -0700472 public void sendStoredMessage(int subId, String callingPkg, Uri messageUri,
Ye Wen8179c2a2014-09-04 15:36:11 -0700473 Bundle configOverrides, PendingIntent sentIntent) throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700474 if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
475 callingPkg) != AppOpsManager.MODE_ALLOWED) {
476 return;
477 }
Ye Wen63c00c42014-08-01 13:38:58 -0700478 getServiceGuarded().sendStoredMessage(subId, callingPkg, messageUri, configOverrides,
479 sentIntent);
Ye Wend97e1fd2014-07-24 12:56:45 -0700480 }
481
482 @Override
483 public void setAutoPersisting(String callingPkg, boolean enabled) throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700484 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
485 callingPkg) != AppOpsManager.MODE_ALLOWED) {
486 return;
487 }
488 getServiceGuarded().setAutoPersisting(callingPkg, enabled);
489 }
490
491 @Override
492 public boolean getAutoPersisting() throws RemoteException {
493 return getServiceGuarded().getAutoPersisting();
494 }
Tom Taylor86201db2014-11-24 09:36:43 -0800495
496 /**
497 * Modifies the Uri to contain the caller's userId, if necessary.
498 * Grants the phone package on primary user permission to access the contentUri,
499 * even if the caller is not in the primary user.
500 *
501 * @param contentUri The Uri to adjust
Leland Miller02c85242019-07-08 15:31:02 -0700502 * @param action The intent action used to find the associated carrier app
Tom Taylor86201db2014-11-24 09:36:43 -0800503 * @param permission The permission to add
504 * @return The adjusted Uri containing the calling userId.
505 */
506 private Uri adjustUriForUserAndGrantPermission(Uri contentUri, String action,
Leland Miller02c85242019-07-08 15:31:02 -0700507 int permission, int subId) {
Jeff Sharkey7ff418d2016-11-30 14:29:59 -0700508 final Intent grantIntent = new Intent();
509 grantIntent.setData(contentUri);
510 grantIntent.setFlags(permission);
511
512 final int callingUid = Binder.getCallingUid();
Tom Taylor86201db2014-11-24 09:36:43 -0800513 final int callingUserId = UserHandle.getCallingUserId();
Xiaohui Chen7c696362015-09-16 09:56:14 -0700514 if (callingUserId != UserHandle.USER_SYSTEM) {
Tom Taylor86201db2014-11-24 09:36:43 -0800515 contentUri = ContentProvider.maybeAddUserId(contentUri, callingUserId);
516 }
Jeff Sharkey7ff418d2016-11-30 14:29:59 -0700517
Tom Taylor86201db2014-11-24 09:36:43 -0800518 long token = Binder.clearCallingIdentity();
519 try {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700520 LocalServices.getService(UriGrantsManagerInternal.class)
Jeff Sharkey7ff418d2016-11-30 14:29:59 -0700521 .grantUriPermissionFromIntent(callingUid, PHONE_PACKAGE_NAME,
522 grantIntent, UserHandle.USER_SYSTEM);
Tom Taylor86201db2014-11-24 09:36:43 -0800523
524 // Grant permission for the carrier app.
525 Intent intent = new Intent(action);
526 TelephonyManager telephonyManager =
Leland Miller02c85242019-07-08 15:31:02 -0700527 (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
528 List<String> carrierPackages =
529 telephonyManager.getCarrierPackageNamesForIntentAndPhone(
530 intent, SubscriptionManager.getPhoneId(subId));
Tom Taylor86201db2014-11-24 09:36:43 -0800531 if (carrierPackages != null && carrierPackages.size() == 1) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700532 LocalServices.getService(UriGrantsManagerInternal.class)
Jeff Sharkey7ff418d2016-11-30 14:29:59 -0700533 .grantUriPermissionFromIntent(callingUid, carrierPackages.get(0),
534 grantIntent, UserHandle.USER_SYSTEM);
Tom Taylor86201db2014-11-24 09:36:43 -0800535 }
536 } finally {
537 Binder.restoreCallingIdentity(token);
538 }
539 return contentUri;
540 }
Ye Wend97e1fd2014-07-24 12:56:45 -0700541 }
542}