blob: 043f657b7f2c9d0ceb9d3753ee3a9f694007da81 [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
Malcolm Chene4275582019-12-12 14:36:04 -080019import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
20
Ye Wend97e1fd2014-07-24 12:56:45 -070021import android.Manifest;
22import android.app.AppOpsManager;
23import android.app.PendingIntent;
24import android.content.ComponentName;
Tom Taylor86201db2014-11-24 09:36:43 -080025import android.content.ContentProvider;
Ye Wend97e1fd2014-07-24 12:56:45 -070026import android.content.ContentValues;
27import android.content.Context;
28import android.content.Intent;
29import android.content.ServiceConnection;
30import android.content.pm.PackageManager;
31import android.net.Uri;
32import android.os.Binder;
Shri Borde72379722014-09-02 09:48:49 -070033import android.os.Bundle;
Ye Wend97e1fd2014-07-24 12:56:45 -070034import android.os.Handler;
35import android.os.IBinder;
36import android.os.Message;
37import android.os.RemoteException;
Ye Wen724dbbd72014-10-07 15:33:51 -070038import android.os.SystemClock;
Tom Taylor86201db2014-11-24 09:36:43 -080039import android.os.UserHandle;
Cheuksan Wang5cec9202014-12-16 13:40:36 -080040import android.service.carrier.CarrierMessagingService;
Ye Wen61c8d232015-04-01 11:27:14 -070041import android.telephony.SmsManager;
Malcolm Chene4275582019-12-12 14:36:04 -080042import android.telephony.SubscriptionInfo;
Leland Miller02c85242019-07-08 15:31:02 -070043import android.telephony.SubscriptionManager;
Ye Wend97e1fd2014-07-24 12:56:45 -070044import android.telephony.TelephonyManager;
45import android.util.Slog;
46
Ye Wenbdc3a462014-11-11 11:17:28 -080047import com.android.internal.telephony.IMms;
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -070048import com.android.server.uri.UriGrantsManagerInternal;
Ye Wenbdc3a462014-11-11 11:17:28 -080049
Tom Taylor86201db2014-11-24 09:36:43 -080050import java.util.List;
51
Ye Wend97e1fd2014-07-24 12:56:45 -070052/**
53 * This class is a proxy for MmsService APIs. We need this because MmsService runs
54 * in phone process and may crash anytime. This manages a connection to the actual
55 * MmsService and bridges the public SMS/MMS APIs with MmsService implementation.
56 */
57public class MmsServiceBroker extends SystemService {
58 private static final String TAG = "MmsServiceBroker";
59
60 private static final ComponentName MMS_SERVICE_COMPONENT =
61 new ComponentName("com.android.mms.service", "com.android.mms.service.MmsService");
62
63 private static final int MSG_TRY_CONNECTING = 1;
64
Ye Wenfa58ac02014-07-31 17:15:30 -070065 private static final Uri FAKE_SMS_SENT_URI = Uri.parse("content://sms/sent/0");
66 private static final Uri FAKE_MMS_SENT_URI = Uri.parse("content://mms/sent/0");
67 private static final Uri FAKE_SMS_DRAFT_URI = Uri.parse("content://sms/draft/0");
68 private static final Uri FAKE_MMS_DRAFT_URI = Uri.parse("content://mms/draft/0");
69
Ye Wen724dbbd72014-10-07 15:33:51 -070070 private static final long SERVICE_CONNECTION_WAIT_TIME_MS = 4 * 1000L; // 4 seconds
71 private static final long RETRY_DELAY_ON_DISCONNECTION_MS = 3 * 1000L; // 3 seconds
72
Ye Wend97e1fd2014-07-24 12:56:45 -070073 private Context mContext;
74 // The actual MMS service instance to invoke
75 private volatile IMms mService;
Ye Wend97e1fd2014-07-24 12:56:45 -070076
77 // Cached system service instances
78 private volatile AppOpsManager mAppOpsManager = null;
79 private volatile PackageManager mPackageManager = null;
80 private volatile TelephonyManager mTelephonyManager = null;
81
82 private final Handler mConnectionHandler = new Handler() {
83 @Override
84 public void handleMessage(Message msg) {
85 switch (msg.what) {
86 case MSG_TRY_CONNECTING:
87 tryConnecting();
88 break;
89 default:
90 Slog.e(TAG, "Unknown message");
91 }
92 }
93 };
94
95 private ServiceConnection mConnection = new ServiceConnection() {
96 @Override
97 public void onServiceConnected(ComponentName name, IBinder service) {
98 Slog.i(TAG, "MmsService connected");
99 synchronized (MmsServiceBroker.this) {
Jeff Sharkey0a17db12016-11-04 11:23:46 -0600100 mService = IMms.Stub.asInterface(Binder.allowBlocking(service));
Ye Wen724dbbd72014-10-07 15:33:51 -0700101 MmsServiceBroker.this.notifyAll();
Ye Wend97e1fd2014-07-24 12:56:45 -0700102 }
103 }
104
105 @Override
106 public void onServiceDisconnected(ComponentName name) {
107 Slog.i(TAG, "MmsService unexpectedly disconnected");
108 synchronized (MmsServiceBroker.this) {
109 mService = null;
Ye Wen724dbbd72014-10-07 15:33:51 -0700110 MmsServiceBroker.this.notifyAll();
Ye Wend97e1fd2014-07-24 12:56:45 -0700111 }
Ye Wen724dbbd72014-10-07 15:33:51 -0700112 // Retry connecting, but not too eager (with a delay)
113 // since it may come back by itself.
114 mConnectionHandler.sendMessageDelayed(
115 mConnectionHandler.obtainMessage(MSG_TRY_CONNECTING),
116 RETRY_DELAY_ON_DISCONNECTION_MS);
Ye Wend97e1fd2014-07-24 12:56:45 -0700117 }
118 };
119
Ye Wen61c8d232015-04-01 11:27:14 -0700120 // Instance of IMms for returning failure to service API caller,
121 // used when MmsService cannot be connected.
122 private final IMms mServiceStubForFailure = new IMms() {
123
124 @Override
125 public IBinder asBinder() {
126 return null;
127 }
128
129 @Override
130 public void sendMessage(int subId, String callingPkg, Uri contentUri, String locationUrl,
Tom Taylor03079ec2020-01-24 10:21:50 -0800131 Bundle configOverrides, PendingIntent sentIntent, long messageId)
132 throws RemoteException {
Ye Wen61c8d232015-04-01 11:27:14 -0700133 returnPendingIntentWithError(sentIntent);
134 }
135
136 @Override
137 public void downloadMessage(int subId, String callingPkg, String locationUrl,
Tom Taylor03079ec2020-01-24 10:21:50 -0800138 Uri contentUri, Bundle configOverrides, PendingIntent downloadedIntent,
139 long messageId)
Ye Wen61c8d232015-04-01 11:27:14 -0700140 throws RemoteException {
141 returnPendingIntentWithError(downloadedIntent);
142 }
143
144 @Override
Ye Wen61c8d232015-04-01 11:27:14 -0700145 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,
Tom Taylor03079ec2020-01-24 10:21:50 -0800334 String locationUrl, Bundle configOverrides, PendingIntent sentIntent,
335 long messageId)
Leland Miller02c85242019-07-08 15:31:02 -0700336 throws RemoteException {
Ye Wenbdc3a462014-11-11 11:17:28 -0800337 Slog.d(TAG, "sendMessage() by " + callingPkg);
Ye Wend97e1fd2014-07-24 12:56:45 -0700338 mContext.enforceCallingPermission(Manifest.permission.SEND_SMS, "Send MMS message");
339 if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
340 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Sahin Caliskan7c766b22018-10-30 10:20:08 -0700341 Slog.e(TAG, callingPkg + " is not allowed to call sendMessage()");
Ye Wend97e1fd2014-07-24 12:56:45 -0700342 return;
343 }
Tom Taylor86201db2014-11-24 09:36:43 -0800344 contentUri = adjustUriForUserAndGrantPermission(contentUri,
Cheuksan Wang5cec9202014-12-16 13:40:36 -0800345 CarrierMessagingService.SERVICE_INTERFACE,
Leland Miller02c85242019-07-08 15:31:02 -0700346 Intent.FLAG_GRANT_READ_URI_PERMISSION,
347 subId);
Julian Odell31ef14d2014-08-25 17:53:52 -0700348 getServiceGuarded().sendMessage(subId, callingPkg, contentUri, locationUrl,
Tom Taylor03079ec2020-01-24 10:21:50 -0800349 configOverrides, sentIntent, messageId);
Ye Wend97e1fd2014-07-24 12:56:45 -0700350 }
351
352 @Override
Wink Saville63f03dd2014-10-23 10:44:45 -0700353 public void downloadMessage(int subId, String callingPkg, String locationUrl,
Ye Wen8179c2a2014-09-04 15:36:11 -0700354 Uri contentUri, Bundle configOverrides,
Tom Taylor03079ec2020-01-24 10:21:50 -0800355 PendingIntent downloadedIntent, long messageId) throws RemoteException {
Ye Wenbdc3a462014-11-11 11:17:28 -0800356 Slog.d(TAG, "downloadMessage() by " + callingPkg);
Ye Wend97e1fd2014-07-24 12:56:45 -0700357 mContext.enforceCallingPermission(Manifest.permission.RECEIVE_MMS,
358 "Download MMS message");
359 if (getAppOpsManager().noteOp(AppOpsManager.OP_RECEIVE_MMS, Binder.getCallingUid(),
360 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Sahin Caliskan7c766b22018-10-30 10:20:08 -0700361 Slog.e(TAG, callingPkg + " is not allowed to call downloadMessage()");
Ye Wend97e1fd2014-07-24 12:56:45 -0700362 return;
363 }
Tom Taylor86201db2014-11-24 09:36:43 -0800364 contentUri = adjustUriForUserAndGrantPermission(contentUri,
Cheuksan Wang5cec9202014-12-16 13:40:36 -0800365 CarrierMessagingService.SERVICE_INTERFACE,
Leland Miller02c85242019-07-08 15:31:02 -0700366 Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
367 subId);
Tom Taylor86201db2014-11-24 09:36:43 -0800368
Julian Odell31ef14d2014-08-25 17:53:52 -0700369 getServiceGuarded().downloadMessage(subId, callingPkg, locationUrl, contentUri,
Tom Taylor03079ec2020-01-24 10:21:50 -0800370 configOverrides, downloadedIntent, messageId);
Ye Wend97e1fd2014-07-24 12:56:45 -0700371 }
372
373 @Override
Ye Wend97e1fd2014-07-24 12:56:45 -0700374 public Uri importTextMessage(String callingPkg, String address, int type, String text,
375 long timestampMillis, boolean seen, boolean read) throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700376 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
377 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Ye Wenfa58ac02014-07-31 17:15:30 -0700378 // Silently fail AppOps failure due to not being the default SMS app
379 // while writing the TelephonyProvider
380 return FAKE_SMS_SENT_URI;
Ye Wend97e1fd2014-07-24 12:56:45 -0700381 }
382 return getServiceGuarded().importTextMessage(
383 callingPkg, address, type, text, timestampMillis, seen, read);
384 }
385
386 @Override
Julian Odell31ef14d2014-08-25 17:53:52 -0700387 public Uri importMultimediaMessage(String callingPkg, Uri contentUri,
388 String messageId, long timestampSecs, boolean seen, boolean read)
Leland Miller02c85242019-07-08 15:31:02 -0700389 throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700390 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
391 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Ye Wenfa58ac02014-07-31 17:15:30 -0700392 // Silently fail AppOps failure due to not being the default SMS app
393 // while writing the TelephonyProvider
394 return FAKE_MMS_SENT_URI;
Ye Wend97e1fd2014-07-24 12:56:45 -0700395 }
396 return getServiceGuarded().importMultimediaMessage(
Julian Odell31ef14d2014-08-25 17:53:52 -0700397 callingPkg, contentUri, messageId, timestampSecs, seen, read);
Ye Wend97e1fd2014-07-24 12:56:45 -0700398 }
399
400 @Override
401 public boolean deleteStoredMessage(String callingPkg, Uri messageUri)
402 throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700403 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
404 callingPkg) != AppOpsManager.MODE_ALLOWED) {
405 return false;
406 }
407 return getServiceGuarded().deleteStoredMessage(callingPkg, messageUri);
408 }
409
410 @Override
411 public boolean deleteStoredConversation(String callingPkg, long conversationId)
412 throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700413 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
414 callingPkg) != AppOpsManager.MODE_ALLOWED) {
415 return false;
416 }
417 return getServiceGuarded().deleteStoredConversation(callingPkg, conversationId);
418 }
419
420 @Override
421 public boolean updateStoredMessageStatus(String callingPkg, Uri messageUri,
422 ContentValues statusValues) throws RemoteException {
Svetoslav6c589572015-04-16 16:19:24 -0700423 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
424 callingPkg) != AppOpsManager.MODE_ALLOWED) {
425 return false;
426 }
Ye Wend97e1fd2014-07-24 12:56:45 -0700427 return getServiceGuarded()
428 .updateStoredMessageStatus(callingPkg, messageUri, statusValues);
429 }
430
431 @Override
Ye Wena3dbd102014-07-29 10:42:25 -0700432 public boolean archiveStoredConversation(String callingPkg, long conversationId,
433 boolean archived) throws RemoteException {
Svetoslav6c589572015-04-16 16:19:24 -0700434 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
435 callingPkg) != AppOpsManager.MODE_ALLOWED) {
436 return false;
437 }
Ye Wena3dbd102014-07-29 10:42:25 -0700438 return getServiceGuarded()
439 .archiveStoredConversation(callingPkg, conversationId, archived);
440 }
441
442 @Override
Ye Wend97e1fd2014-07-24 12:56:45 -0700443 public Uri addTextMessageDraft(String callingPkg, String address, String text)
444 throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700445 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
446 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Ye Wenfa58ac02014-07-31 17:15:30 -0700447 // Silently fail AppOps failure due to not being the default SMS app
448 // while writing the TelephonyProvider
449 return FAKE_SMS_DRAFT_URI;
Ye Wend97e1fd2014-07-24 12:56:45 -0700450 }
451 return getServiceGuarded().addTextMessageDraft(callingPkg, address, text);
452 }
453
454 @Override
Julian Odell31ef14d2014-08-25 17:53:52 -0700455 public Uri addMultimediaMessageDraft(String callingPkg, Uri contentUri)
456 throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700457 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
458 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Ye Wenfa58ac02014-07-31 17:15:30 -0700459 // Silently fail AppOps failure due to not being the default SMS app
460 // while writing the TelephonyProvider
461 return FAKE_MMS_DRAFT_URI;
Ye Wend97e1fd2014-07-24 12:56:45 -0700462 }
Julian Odell31ef14d2014-08-25 17:53:52 -0700463 return getServiceGuarded().addMultimediaMessageDraft(callingPkg, contentUri);
Ye Wend97e1fd2014-07-24 12:56:45 -0700464 }
465
466 @Override
Wink Saville63f03dd2014-10-23 10:44:45 -0700467 public void sendStoredMessage(int subId, String callingPkg, Uri messageUri,
Ye Wen8179c2a2014-09-04 15:36:11 -0700468 Bundle configOverrides, PendingIntent sentIntent) throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700469 if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
470 callingPkg) != AppOpsManager.MODE_ALLOWED) {
471 return;
472 }
Ye Wen63c00c42014-08-01 13:38:58 -0700473 getServiceGuarded().sendStoredMessage(subId, callingPkg, messageUri, configOverrides,
474 sentIntent);
Ye Wend97e1fd2014-07-24 12:56:45 -0700475 }
476
477 @Override
478 public void setAutoPersisting(String callingPkg, boolean enabled) throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700479 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
480 callingPkg) != AppOpsManager.MODE_ALLOWED) {
481 return;
482 }
483 getServiceGuarded().setAutoPersisting(callingPkg, enabled);
484 }
485
486 @Override
487 public boolean getAutoPersisting() throws RemoteException {
488 return getServiceGuarded().getAutoPersisting();
489 }
Tom Taylor86201db2014-11-24 09:36:43 -0800490
491 /**
492 * Modifies the Uri to contain the caller's userId, if necessary.
493 * Grants the phone package on primary user permission to access the contentUri,
494 * even if the caller is not in the primary user.
495 *
496 * @param contentUri The Uri to adjust
Leland Miller02c85242019-07-08 15:31:02 -0700497 * @param action The intent action used to find the associated carrier app
Tom Taylor86201db2014-11-24 09:36:43 -0800498 * @param permission The permission to add
499 * @return The adjusted Uri containing the calling userId.
500 */
501 private Uri adjustUriForUserAndGrantPermission(Uri contentUri, String action,
Leland Miller02c85242019-07-08 15:31:02 -0700502 int permission, int subId) {
Jeff Sharkey7ff418d2016-11-30 14:29:59 -0700503 final Intent grantIntent = new Intent();
504 grantIntent.setData(contentUri);
505 grantIntent.setFlags(permission);
506
507 final int callingUid = Binder.getCallingUid();
Tom Taylor86201db2014-11-24 09:36:43 -0800508 final int callingUserId = UserHandle.getCallingUserId();
Xiaohui Chen7c696362015-09-16 09:56:14 -0700509 if (callingUserId != UserHandle.USER_SYSTEM) {
Tom Taylor86201db2014-11-24 09:36:43 -0800510 contentUri = ContentProvider.maybeAddUserId(contentUri, callingUserId);
511 }
Jeff Sharkey7ff418d2016-11-30 14:29:59 -0700512
Tom Taylor86201db2014-11-24 09:36:43 -0800513 long token = Binder.clearCallingIdentity();
514 try {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700515 LocalServices.getService(UriGrantsManagerInternal.class)
Jeff Sharkey7ff418d2016-11-30 14:29:59 -0700516 .grantUriPermissionFromIntent(callingUid, PHONE_PACKAGE_NAME,
517 grantIntent, UserHandle.USER_SYSTEM);
Tom Taylor86201db2014-11-24 09:36:43 -0800518
519 // Grant permission for the carrier app.
520 Intent intent = new Intent(action);
Malcolm Chene4275582019-12-12 14:36:04 -0800521 TelephonyManager telephonyManager = (TelephonyManager)
522 mContext.getSystemService(Context.TELEPHONY_SERVICE);
523 List<String> carrierPackages = telephonyManager
524 .getCarrierPackageNamesForIntentAndPhone(
525 intent, getPhoneIdFromSubId(subId));
Tom Taylor86201db2014-11-24 09:36:43 -0800526 if (carrierPackages != null && carrierPackages.size() == 1) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700527 LocalServices.getService(UriGrantsManagerInternal.class)
Jeff Sharkey7ff418d2016-11-30 14:29:59 -0700528 .grantUriPermissionFromIntent(callingUid, carrierPackages.get(0),
529 grantIntent, UserHandle.USER_SYSTEM);
Tom Taylor86201db2014-11-24 09:36:43 -0800530 }
531 } finally {
532 Binder.restoreCallingIdentity(token);
533 }
534 return contentUri;
535 }
Ye Wend97e1fd2014-07-24 12:56:45 -0700536 }
Malcolm Chene4275582019-12-12 14:36:04 -0800537
538 private int getPhoneIdFromSubId(int subId) {
539 SubscriptionManager subManager = (SubscriptionManager)
540 mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
541 if (subManager == null) return INVALID_SIM_SLOT_INDEX;
542 SubscriptionInfo info = subManager.getActiveSubscriptionInfo(subId);
543 if (info == null) return INVALID_SIM_SLOT_INDEX;
544 return info.getSimSlotIndex();
545 }
Ye Wend97e1fd2014-07-24 12:56:45 -0700546}