blob: 9b1326bc88d75737c5e24b10c3236661f8c9a0e3 [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,
131 Bundle configOverrides, PendingIntent sentIntent) throws RemoteException {
132 returnPendingIntentWithError(sentIntent);
133 }
134
135 @Override
136 public void downloadMessage(int subId, String callingPkg, String locationUrl,
137 Uri contentUri, Bundle configOverrides, PendingIntent downloadedIntent)
138 throws RemoteException {
139 returnPendingIntentWithError(downloadedIntent);
140 }
141
142 @Override
Ye Wen61c8d232015-04-01 11:27:14 -0700143 public Uri importTextMessage(String callingPkg, String address, int type, String text,
144 long timestampMillis, boolean seen, boolean read) throws RemoteException {
145 return null;
146 }
147
148 @Override
149 public Uri importMultimediaMessage(String callingPkg, Uri contentUri, String messageId,
150 long timestampSecs, boolean seen, boolean read) throws RemoteException {
151 return null;
152 }
153
154 @Override
155 public boolean deleteStoredMessage(String callingPkg, Uri messageUri)
156 throws RemoteException {
157 return false;
158 }
159
160 @Override
161 public boolean deleteStoredConversation(String callingPkg, long conversationId)
162 throws RemoteException {
163 return false;
164 }
165
166 @Override
167 public boolean updateStoredMessageStatus(String callingPkg, Uri messageUri,
168 ContentValues statusValues) throws RemoteException {
169 return false;
170 }
171
172 @Override
173 public boolean archiveStoredConversation(String callingPkg, long conversationId,
174 boolean archived) throws RemoteException {
175 return false;
176 }
177
178 @Override
179 public Uri addTextMessageDraft(String callingPkg, String address, String text)
180 throws RemoteException {
181 return null;
182 }
183
184 @Override
185 public Uri addMultimediaMessageDraft(String callingPkg, Uri contentUri)
186 throws RemoteException {
187 return null;
188 }
189
190 @Override
191 public void sendStoredMessage(int subId, String callingPkg, Uri messageUri,
192 Bundle configOverrides, PendingIntent sentIntent) throws RemoteException {
193 returnPendingIntentWithError(sentIntent);
194 }
195
196 @Override
197 public void setAutoPersisting(String callingPkg, boolean enabled) throws RemoteException {
198 // Do nothing
199 }
200
201 @Override
202 public boolean getAutoPersisting() throws RemoteException {
203 return false;
204 }
205
206 private void returnPendingIntentWithError(PendingIntent pendingIntent) {
207 try {
208 pendingIntent.send(mContext, SmsManager.MMS_ERROR_UNSPECIFIED, null);
209 } catch (PendingIntent.CanceledException e) {
210 Slog.e(TAG, "Failed to return pending intent result", e);
211 }
212 }
213 };
214
Ye Wend97e1fd2014-07-24 12:56:45 -0700215 public MmsServiceBroker(Context context) {
216 super(context);
217 mContext = context;
218 mService = null;
Ye Wend97e1fd2014-07-24 12:56:45 -0700219 }
220
221 @Override
222 public void onStart() {
223 publishBinderService("imms", new BinderService());
224 }
225
226 public void systemRunning() {
Ye Wenbdc3a462014-11-11 11:17:28 -0800227 Slog.i(TAG, "Delay connecting to MmsService until an API is called");
Ye Wend97e1fd2014-07-24 12:56:45 -0700228 }
229
230 private void tryConnecting() {
231 Slog.i(TAG, "Connecting to MmsService");
232 synchronized (this) {
Ye Wen724dbbd72014-10-07 15:33:51 -0700233 if (mService != null) {
234 Slog.d(TAG, "Already connected");
Ye Wend97e1fd2014-07-24 12:56:45 -0700235 return;
236 }
237 final Intent intent = new Intent();
238 intent.setComponent(MMS_SERVICE_COMPONENT);
239 try {
Ye Wen724dbbd72014-10-07 15:33:51 -0700240 if (!mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)) {
241 Slog.e(TAG, "Failed to bind to MmsService");
Ye Wend97e1fd2014-07-24 12:56:45 -0700242 }
243 } catch (SecurityException e) {
Ye Wen724dbbd72014-10-07 15:33:51 -0700244 Slog.e(TAG, "Forbidden to bind to MmsService", e);
Ye Wend97e1fd2014-07-24 12:56:45 -0700245 }
246 }
247 }
248
Ye Wen61c8d232015-04-01 11:27:14 -0700249 private IMms getOrConnectService() {
Ye Wen724dbbd72014-10-07 15:33:51 -0700250 synchronized (this) {
Ye Wen61c8d232015-04-01 11:27:14 -0700251 if (mService != null) {
252 return mService;
Ye Wen724dbbd72014-10-07 15:33:51 -0700253 }
Ye Wen61c8d232015-04-01 11:27:14 -0700254 // Service is not connected. Try blocking connecting.
255 Slog.w(TAG, "MmsService not connected. Try connecting...");
256 mConnectionHandler.sendMessage(
257 mConnectionHandler.obtainMessage(MSG_TRY_CONNECTING));
258 final long shouldEnd =
259 SystemClock.elapsedRealtime() + SERVICE_CONNECTION_WAIT_TIME_MS;
260 long waitTime = SERVICE_CONNECTION_WAIT_TIME_MS;
261 while (waitTime > 0) {
262 try {
263 // TODO: consider using Java concurrent construct instead of raw object wait
264 this.wait(waitTime);
265 } catch (InterruptedException e) {
266 Slog.w(TAG, "Connection wait interrupted", e);
267 }
268 if (mService != null) {
269 // Success
270 return mService;
271 }
272 // Calculate remaining waiting time to make sure we wait the full timeout period
273 waitTime = shouldEnd - SystemClock.elapsedRealtime();
274 }
275 // Timed out. Something's really wrong.
276 Slog.e(TAG, "Can not connect to MmsService (timed out)");
277 return null;
Ye Wend97e1fd2014-07-24 12:56:45 -0700278 }
279 }
280
281 /**
Ye Wen61c8d232015-04-01 11:27:14 -0700282 * Make sure to return a non-empty service instance. Return the connected MmsService
283 * instance, if not connected, try connecting. If fail to connect, return a fake service
284 * instance which returns failure to service caller.
285 *
286 * @return a non-empty service instance, real or fake
Ye Wend97e1fd2014-07-24 12:56:45 -0700287 */
288 private IMms getServiceGuarded() {
Ye Wen61c8d232015-04-01 11:27:14 -0700289 final IMms service = getOrConnectService();
290 if (service != null) {
291 return service;
292 }
293 return mServiceStubForFailure;
Ye Wend97e1fd2014-07-24 12:56:45 -0700294 }
295
296 private AppOpsManager getAppOpsManager() {
297 if (mAppOpsManager == null) {
298 mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
299 }
300 return mAppOpsManager;
301 }
302
303 private PackageManager getPackageManager() {
304 if (mPackageManager == null) {
305 mPackageManager = mContext.getPackageManager();
306 }
307 return mPackageManager;
308 }
309
310 private TelephonyManager getTelephonyManager() {
311 if (mTelephonyManager == null) {
312 mTelephonyManager = (TelephonyManager) mContext.getSystemService(
313 Context.TELEPHONY_SERVICE);
314 }
315 return mTelephonyManager;
316 }
317
Ye Wenbdc3a462014-11-11 11:17:28 -0800318 private String getCallingPackageName() {
319 final String[] packages = getPackageManager().getPackagesForUid(Binder.getCallingUid());
320 if (packages != null && packages.length > 0) {
321 return packages[0];
322 }
323 return "unknown";
324 }
325
Ye Wend97e1fd2014-07-24 12:56:45 -0700326 // Service API calls implementation, proxied to the real MmsService in "com.android.mms.service"
327 private final class BinderService extends IMms.Stub {
Tom Taylor86201db2014-11-24 09:36:43 -0800328 private static final String PHONE_PACKAGE_NAME = "com.android.phone";
329
Ye Wend97e1fd2014-07-24 12:56:45 -0700330 @Override
Wink Saville63f03dd2014-10-23 10:44:45 -0700331 public void sendMessage(int subId, String callingPkg, Uri contentUri,
Ye Wen8179c2a2014-09-04 15:36:11 -0700332 String locationUrl, Bundle configOverrides, PendingIntent sentIntent)
Leland Miller02c85242019-07-08 15:31:02 -0700333 throws RemoteException {
Ye Wenbdc3a462014-11-11 11:17:28 -0800334 Slog.d(TAG, "sendMessage() by " + callingPkg);
Ye Wend97e1fd2014-07-24 12:56:45 -0700335 mContext.enforceCallingPermission(Manifest.permission.SEND_SMS, "Send MMS message");
336 if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
337 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Sahin Caliskan7c766b22018-10-30 10:20:08 -0700338 Slog.e(TAG, callingPkg + " is not allowed to call sendMessage()");
Ye Wend97e1fd2014-07-24 12:56:45 -0700339 return;
340 }
Tom Taylor86201db2014-11-24 09:36:43 -0800341 contentUri = adjustUriForUserAndGrantPermission(contentUri,
Cheuksan Wang5cec9202014-12-16 13:40:36 -0800342 CarrierMessagingService.SERVICE_INTERFACE,
Leland Miller02c85242019-07-08 15:31:02 -0700343 Intent.FLAG_GRANT_READ_URI_PERMISSION,
344 subId);
Julian Odell31ef14d2014-08-25 17:53:52 -0700345 getServiceGuarded().sendMessage(subId, callingPkg, contentUri, locationUrl,
346 configOverrides, sentIntent);
Ye Wend97e1fd2014-07-24 12:56:45 -0700347 }
348
349 @Override
Wink Saville63f03dd2014-10-23 10:44:45 -0700350 public void downloadMessage(int subId, String callingPkg, String locationUrl,
Ye Wen8179c2a2014-09-04 15:36:11 -0700351 Uri contentUri, Bundle configOverrides,
Julian Odell31ef14d2014-08-25 17:53:52 -0700352 PendingIntent downloadedIntent) throws RemoteException {
Ye Wenbdc3a462014-11-11 11:17:28 -0800353 Slog.d(TAG, "downloadMessage() by " + callingPkg);
Ye Wend97e1fd2014-07-24 12:56:45 -0700354 mContext.enforceCallingPermission(Manifest.permission.RECEIVE_MMS,
355 "Download MMS message");
356 if (getAppOpsManager().noteOp(AppOpsManager.OP_RECEIVE_MMS, Binder.getCallingUid(),
357 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Sahin Caliskan7c766b22018-10-30 10:20:08 -0700358 Slog.e(TAG, callingPkg + " is not allowed to call downloadMessage()");
Ye Wend97e1fd2014-07-24 12:56:45 -0700359 return;
360 }
Tom Taylor86201db2014-11-24 09:36:43 -0800361 contentUri = adjustUriForUserAndGrantPermission(contentUri,
Cheuksan Wang5cec9202014-12-16 13:40:36 -0800362 CarrierMessagingService.SERVICE_INTERFACE,
Leland Miller02c85242019-07-08 15:31:02 -0700363 Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
364 subId);
Tom Taylor86201db2014-11-24 09:36:43 -0800365
Julian Odell31ef14d2014-08-25 17:53:52 -0700366 getServiceGuarded().downloadMessage(subId, callingPkg, locationUrl, contentUri,
367 configOverrides, downloadedIntent);
Ye Wend97e1fd2014-07-24 12:56:45 -0700368 }
369
370 @Override
Ye Wend97e1fd2014-07-24 12:56:45 -0700371 public Uri importTextMessage(String callingPkg, String address, int type, String text,
372 long timestampMillis, boolean seen, boolean read) throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700373 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
374 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Ye Wenfa58ac02014-07-31 17:15:30 -0700375 // Silently fail AppOps failure due to not being the default SMS app
376 // while writing the TelephonyProvider
377 return FAKE_SMS_SENT_URI;
Ye Wend97e1fd2014-07-24 12:56:45 -0700378 }
379 return getServiceGuarded().importTextMessage(
380 callingPkg, address, type, text, timestampMillis, seen, read);
381 }
382
383 @Override
Julian Odell31ef14d2014-08-25 17:53:52 -0700384 public Uri importMultimediaMessage(String callingPkg, Uri contentUri,
385 String messageId, long timestampSecs, boolean seen, boolean read)
Leland Miller02c85242019-07-08 15:31:02 -0700386 throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700387 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
388 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Ye Wenfa58ac02014-07-31 17:15:30 -0700389 // Silently fail AppOps failure due to not being the default SMS app
390 // while writing the TelephonyProvider
391 return FAKE_MMS_SENT_URI;
Ye Wend97e1fd2014-07-24 12:56:45 -0700392 }
393 return getServiceGuarded().importMultimediaMessage(
Julian Odell31ef14d2014-08-25 17:53:52 -0700394 callingPkg, contentUri, messageId, timestampSecs, seen, read);
Ye Wend97e1fd2014-07-24 12:56:45 -0700395 }
396
397 @Override
398 public boolean deleteStoredMessage(String callingPkg, Uri messageUri)
399 throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700400 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
401 callingPkg) != AppOpsManager.MODE_ALLOWED) {
402 return false;
403 }
404 return getServiceGuarded().deleteStoredMessage(callingPkg, messageUri);
405 }
406
407 @Override
408 public boolean deleteStoredConversation(String callingPkg, long conversationId)
409 throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700410 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
411 callingPkg) != AppOpsManager.MODE_ALLOWED) {
412 return false;
413 }
414 return getServiceGuarded().deleteStoredConversation(callingPkg, conversationId);
415 }
416
417 @Override
418 public boolean updateStoredMessageStatus(String callingPkg, Uri messageUri,
419 ContentValues statusValues) throws RemoteException {
Svetoslav6c589572015-04-16 16:19:24 -0700420 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
421 callingPkg) != AppOpsManager.MODE_ALLOWED) {
422 return false;
423 }
Ye Wend97e1fd2014-07-24 12:56:45 -0700424 return getServiceGuarded()
425 .updateStoredMessageStatus(callingPkg, messageUri, statusValues);
426 }
427
428 @Override
Ye Wena3dbd102014-07-29 10:42:25 -0700429 public boolean archiveStoredConversation(String callingPkg, long conversationId,
430 boolean archived) throws RemoteException {
Svetoslav6c589572015-04-16 16:19:24 -0700431 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
432 callingPkg) != AppOpsManager.MODE_ALLOWED) {
433 return false;
434 }
Ye Wena3dbd102014-07-29 10:42:25 -0700435 return getServiceGuarded()
436 .archiveStoredConversation(callingPkg, conversationId, archived);
437 }
438
439 @Override
Ye Wend97e1fd2014-07-24 12:56:45 -0700440 public Uri addTextMessageDraft(String callingPkg, String address, String text)
441 throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700442 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
443 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Ye Wenfa58ac02014-07-31 17:15:30 -0700444 // Silently fail AppOps failure due to not being the default SMS app
445 // while writing the TelephonyProvider
446 return FAKE_SMS_DRAFT_URI;
Ye Wend97e1fd2014-07-24 12:56:45 -0700447 }
448 return getServiceGuarded().addTextMessageDraft(callingPkg, address, text);
449 }
450
451 @Override
Julian Odell31ef14d2014-08-25 17:53:52 -0700452 public Uri addMultimediaMessageDraft(String callingPkg, Uri contentUri)
453 throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700454 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
455 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Ye Wenfa58ac02014-07-31 17:15:30 -0700456 // Silently fail AppOps failure due to not being the default SMS app
457 // while writing the TelephonyProvider
458 return FAKE_MMS_DRAFT_URI;
Ye Wend97e1fd2014-07-24 12:56:45 -0700459 }
Julian Odell31ef14d2014-08-25 17:53:52 -0700460 return getServiceGuarded().addMultimediaMessageDraft(callingPkg, contentUri);
Ye Wend97e1fd2014-07-24 12:56:45 -0700461 }
462
463 @Override
Wink Saville63f03dd2014-10-23 10:44:45 -0700464 public void sendStoredMessage(int subId, String callingPkg, Uri messageUri,
Ye Wen8179c2a2014-09-04 15:36:11 -0700465 Bundle configOverrides, PendingIntent sentIntent) throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700466 if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
467 callingPkg) != AppOpsManager.MODE_ALLOWED) {
468 return;
469 }
Ye Wen63c00c42014-08-01 13:38:58 -0700470 getServiceGuarded().sendStoredMessage(subId, callingPkg, messageUri, configOverrides,
471 sentIntent);
Ye Wend97e1fd2014-07-24 12:56:45 -0700472 }
473
474 @Override
475 public void setAutoPersisting(String callingPkg, boolean enabled) throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700476 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
477 callingPkg) != AppOpsManager.MODE_ALLOWED) {
478 return;
479 }
480 getServiceGuarded().setAutoPersisting(callingPkg, enabled);
481 }
482
483 @Override
484 public boolean getAutoPersisting() throws RemoteException {
485 return getServiceGuarded().getAutoPersisting();
486 }
Tom Taylor86201db2014-11-24 09:36:43 -0800487
488 /**
489 * Modifies the Uri to contain the caller's userId, if necessary.
490 * Grants the phone package on primary user permission to access the contentUri,
491 * even if the caller is not in the primary user.
492 *
493 * @param contentUri The Uri to adjust
Leland Miller02c85242019-07-08 15:31:02 -0700494 * @param action The intent action used to find the associated carrier app
Tom Taylor86201db2014-11-24 09:36:43 -0800495 * @param permission The permission to add
496 * @return The adjusted Uri containing the calling userId.
497 */
498 private Uri adjustUriForUserAndGrantPermission(Uri contentUri, String action,
Leland Miller02c85242019-07-08 15:31:02 -0700499 int permission, int subId) {
Jeff Sharkey7ff418d2016-11-30 14:29:59 -0700500 final Intent grantIntent = new Intent();
501 grantIntent.setData(contentUri);
502 grantIntent.setFlags(permission);
503
504 final int callingUid = Binder.getCallingUid();
Tom Taylor86201db2014-11-24 09:36:43 -0800505 final int callingUserId = UserHandle.getCallingUserId();
Xiaohui Chen7c696362015-09-16 09:56:14 -0700506 if (callingUserId != UserHandle.USER_SYSTEM) {
Tom Taylor86201db2014-11-24 09:36:43 -0800507 contentUri = ContentProvider.maybeAddUserId(contentUri, callingUserId);
508 }
Jeff Sharkey7ff418d2016-11-30 14:29:59 -0700509
Tom Taylor86201db2014-11-24 09:36:43 -0800510 long token = Binder.clearCallingIdentity();
511 try {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700512 LocalServices.getService(UriGrantsManagerInternal.class)
Jeff Sharkey7ff418d2016-11-30 14:29:59 -0700513 .grantUriPermissionFromIntent(callingUid, PHONE_PACKAGE_NAME,
514 grantIntent, UserHandle.USER_SYSTEM);
Tom Taylor86201db2014-11-24 09:36:43 -0800515
516 // Grant permission for the carrier app.
517 Intent intent = new Intent(action);
Malcolm Chene4275582019-12-12 14:36:04 -0800518 TelephonyManager telephonyManager = (TelephonyManager)
519 mContext.getSystemService(Context.TELEPHONY_SERVICE);
520 List<String> carrierPackages = telephonyManager
521 .getCarrierPackageNamesForIntentAndPhone(
522 intent, getPhoneIdFromSubId(subId));
Tom Taylor86201db2014-11-24 09:36:43 -0800523 if (carrierPackages != null && carrierPackages.size() == 1) {
Wale Ogunwale6d50dcc2018-07-21 23:00:40 -0700524 LocalServices.getService(UriGrantsManagerInternal.class)
Jeff Sharkey7ff418d2016-11-30 14:29:59 -0700525 .grantUriPermissionFromIntent(callingUid, carrierPackages.get(0),
526 grantIntent, UserHandle.USER_SYSTEM);
Tom Taylor86201db2014-11-24 09:36:43 -0800527 }
528 } finally {
529 Binder.restoreCallingIdentity(token);
530 }
531 return contentUri;
532 }
Ye Wend97e1fd2014-07-24 12:56:45 -0700533 }
Malcolm Chene4275582019-12-12 14:36:04 -0800534
535 private int getPhoneIdFromSubId(int subId) {
536 SubscriptionManager subManager = (SubscriptionManager)
537 mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
538 if (subManager == null) return INVALID_SIM_SLOT_INDEX;
539 SubscriptionInfo info = subManager.getActiveSubscriptionInfo(subId);
540 if (info == null) return INVALID_SIM_SLOT_INDEX;
541 return info.getSimSlotIndex();
542 }
Ye Wend97e1fd2014-07-24 12:56:45 -0700543}