blob: 8402087cddae7998b55d955d29522413c34ad9c1 [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;
Jeff Sharkey7ff418d2016-11-30 14:29:59 -070020import android.app.ActivityManagerInternal;
Ye Wend97e1fd2014-07-24 12:56:45 -070021import android.app.AppOpsManager;
22import android.app.PendingIntent;
23import android.content.ComponentName;
Tom Taylor86201db2014-11-24 09:36:43 -080024import android.content.ContentProvider;
Ye Wend97e1fd2014-07-24 12:56:45 -070025import android.content.ContentValues;
26import android.content.Context;
27import android.content.Intent;
28import android.content.ServiceConnection;
29import android.content.pm.PackageManager;
30import android.net.Uri;
31import android.os.Binder;
Shri Borde72379722014-09-02 09:48:49 -070032import android.os.Bundle;
Ye Wend97e1fd2014-07-24 12:56:45 -070033import android.os.Handler;
34import android.os.IBinder;
35import android.os.Message;
36import android.os.RemoteException;
Ye Wen724dbbd72014-10-07 15:33:51 -070037import android.os.SystemClock;
Tom Taylor86201db2014-11-24 09:36:43 -080038import android.os.UserHandle;
Cheuksan Wang5cec9202014-12-16 13:40:36 -080039import android.service.carrier.CarrierMessagingService;
Ye Wen61c8d232015-04-01 11:27:14 -070040import android.telephony.SmsManager;
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;
45
Tom Taylor86201db2014-11-24 09:36:43 -080046import java.util.List;
47
Ye Wend97e1fd2014-07-24 12:56:45 -070048/**
49 * This class is a proxy for MmsService APIs. We need this because MmsService runs
50 * in phone process and may crash anytime. This manages a connection to the actual
51 * MmsService and bridges the public SMS/MMS APIs with MmsService implementation.
52 */
53public class MmsServiceBroker extends SystemService {
54 private static final String TAG = "MmsServiceBroker";
55
56 private static final ComponentName MMS_SERVICE_COMPONENT =
57 new ComponentName("com.android.mms.service", "com.android.mms.service.MmsService");
58
59 private static final int MSG_TRY_CONNECTING = 1;
60
Ye Wenfa58ac02014-07-31 17:15:30 -070061 private static final Uri FAKE_SMS_SENT_URI = Uri.parse("content://sms/sent/0");
62 private static final Uri FAKE_MMS_SENT_URI = Uri.parse("content://mms/sent/0");
63 private static final Uri FAKE_SMS_DRAFT_URI = Uri.parse("content://sms/draft/0");
64 private static final Uri FAKE_MMS_DRAFT_URI = Uri.parse("content://mms/draft/0");
65
Ye Wen724dbbd72014-10-07 15:33:51 -070066 private static final long SERVICE_CONNECTION_WAIT_TIME_MS = 4 * 1000L; // 4 seconds
67 private static final long RETRY_DELAY_ON_DISCONNECTION_MS = 3 * 1000L; // 3 seconds
68
Ye Wend97e1fd2014-07-24 12:56:45 -070069 private Context mContext;
70 // The actual MMS service instance to invoke
71 private volatile IMms mService;
Ye Wend97e1fd2014-07-24 12:56:45 -070072
73 // Cached system service instances
74 private volatile AppOpsManager mAppOpsManager = null;
75 private volatile PackageManager mPackageManager = null;
76 private volatile TelephonyManager mTelephonyManager = null;
77
78 private final Handler mConnectionHandler = new Handler() {
79 @Override
80 public void handleMessage(Message msg) {
81 switch (msg.what) {
82 case MSG_TRY_CONNECTING:
83 tryConnecting();
84 break;
85 default:
86 Slog.e(TAG, "Unknown message");
87 }
88 }
89 };
90
91 private ServiceConnection mConnection = new ServiceConnection() {
92 @Override
93 public void onServiceConnected(ComponentName name, IBinder service) {
94 Slog.i(TAG, "MmsService connected");
95 synchronized (MmsServiceBroker.this) {
Jeff Sharkey0a17db12016-11-04 11:23:46 -060096 mService = IMms.Stub.asInterface(Binder.allowBlocking(service));
Ye Wen724dbbd72014-10-07 15:33:51 -070097 MmsServiceBroker.this.notifyAll();
Ye Wend97e1fd2014-07-24 12:56:45 -070098 }
99 }
100
101 @Override
102 public void onServiceDisconnected(ComponentName name) {
103 Slog.i(TAG, "MmsService unexpectedly disconnected");
104 synchronized (MmsServiceBroker.this) {
105 mService = null;
Ye Wen724dbbd72014-10-07 15:33:51 -0700106 MmsServiceBroker.this.notifyAll();
Ye Wend97e1fd2014-07-24 12:56:45 -0700107 }
Ye Wen724dbbd72014-10-07 15:33:51 -0700108 // Retry connecting, but not too eager (with a delay)
109 // since it may come back by itself.
110 mConnectionHandler.sendMessageDelayed(
111 mConnectionHandler.obtainMessage(MSG_TRY_CONNECTING),
112 RETRY_DELAY_ON_DISCONNECTION_MS);
Ye Wend97e1fd2014-07-24 12:56:45 -0700113 }
114 };
115
Ye Wen61c8d232015-04-01 11:27:14 -0700116 // Instance of IMms for returning failure to service API caller,
117 // used when MmsService cannot be connected.
118 private final IMms mServiceStubForFailure = new IMms() {
119
120 @Override
121 public IBinder asBinder() {
122 return null;
123 }
124
125 @Override
126 public void sendMessage(int subId, String callingPkg, Uri contentUri, String locationUrl,
127 Bundle configOverrides, PendingIntent sentIntent) throws RemoteException {
128 returnPendingIntentWithError(sentIntent);
129 }
130
131 @Override
132 public void downloadMessage(int subId, String callingPkg, String locationUrl,
133 Uri contentUri, Bundle configOverrides, PendingIntent downloadedIntent)
134 throws RemoteException {
135 returnPendingIntentWithError(downloadedIntent);
136 }
137
138 @Override
139 public Bundle getCarrierConfigValues(int subId) throws RemoteException {
140 return null;
141 }
142
143 @Override
144 public Uri importTextMessage(String callingPkg, String address, int type, String text,
145 long timestampMillis, boolean seen, boolean read) throws RemoteException {
146 return null;
147 }
148
149 @Override
150 public Uri importMultimediaMessage(String callingPkg, Uri contentUri, String messageId,
151 long timestampSecs, boolean seen, boolean read) throws RemoteException {
152 return null;
153 }
154
155 @Override
156 public boolean deleteStoredMessage(String callingPkg, Uri messageUri)
157 throws RemoteException {
158 return false;
159 }
160
161 @Override
162 public boolean deleteStoredConversation(String callingPkg, long conversationId)
163 throws RemoteException {
164 return false;
165 }
166
167 @Override
168 public boolean updateStoredMessageStatus(String callingPkg, Uri messageUri,
169 ContentValues statusValues) throws RemoteException {
170 return false;
171 }
172
173 @Override
174 public boolean archiveStoredConversation(String callingPkg, long conversationId,
175 boolean archived) throws RemoteException {
176 return false;
177 }
178
179 @Override
180 public Uri addTextMessageDraft(String callingPkg, String address, String text)
181 throws RemoteException {
182 return null;
183 }
184
185 @Override
186 public Uri addMultimediaMessageDraft(String callingPkg, Uri contentUri)
187 throws RemoteException {
188 return null;
189 }
190
191 @Override
192 public void sendStoredMessage(int subId, String callingPkg, Uri messageUri,
193 Bundle configOverrides, PendingIntent sentIntent) throws RemoteException {
194 returnPendingIntentWithError(sentIntent);
195 }
196
197 @Override
198 public void setAutoPersisting(String callingPkg, boolean enabled) throws RemoteException {
199 // Do nothing
200 }
201
202 @Override
203 public boolean getAutoPersisting() throws RemoteException {
204 return false;
205 }
206
207 private void returnPendingIntentWithError(PendingIntent pendingIntent) {
208 try {
209 pendingIntent.send(mContext, SmsManager.MMS_ERROR_UNSPECIFIED, null);
210 } catch (PendingIntent.CanceledException e) {
211 Slog.e(TAG, "Failed to return pending intent result", e);
212 }
213 }
214 };
215
Ye Wend97e1fd2014-07-24 12:56:45 -0700216 public MmsServiceBroker(Context context) {
217 super(context);
218 mContext = context;
219 mService = null;
Ye Wend97e1fd2014-07-24 12:56:45 -0700220 }
221
222 @Override
223 public void onStart() {
224 publishBinderService("imms", new BinderService());
225 }
226
227 public void systemRunning() {
Ye Wenbdc3a462014-11-11 11:17:28 -0800228 Slog.i(TAG, "Delay connecting to MmsService until an API is called");
Ye Wend97e1fd2014-07-24 12:56:45 -0700229 }
230
231 private void tryConnecting() {
232 Slog.i(TAG, "Connecting to MmsService");
233 synchronized (this) {
Ye Wen724dbbd72014-10-07 15:33:51 -0700234 if (mService != null) {
235 Slog.d(TAG, "Already connected");
Ye Wend97e1fd2014-07-24 12:56:45 -0700236 return;
237 }
238 final Intent intent = new Intent();
239 intent.setComponent(MMS_SERVICE_COMPONENT);
240 try {
Ye Wen724dbbd72014-10-07 15:33:51 -0700241 if (!mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)) {
242 Slog.e(TAG, "Failed to bind to MmsService");
Ye Wend97e1fd2014-07-24 12:56:45 -0700243 }
244 } catch (SecurityException e) {
Ye Wen724dbbd72014-10-07 15:33:51 -0700245 Slog.e(TAG, "Forbidden to bind to MmsService", e);
Ye Wend97e1fd2014-07-24 12:56:45 -0700246 }
247 }
248 }
249
Ye Wen61c8d232015-04-01 11:27:14 -0700250 private IMms getOrConnectService() {
Ye Wen724dbbd72014-10-07 15:33:51 -0700251 synchronized (this) {
Ye Wen61c8d232015-04-01 11:27:14 -0700252 if (mService != null) {
253 return mService;
Ye Wen724dbbd72014-10-07 15:33:51 -0700254 }
Ye Wen61c8d232015-04-01 11:27:14 -0700255 // Service is not connected. Try blocking connecting.
256 Slog.w(TAG, "MmsService not connected. Try connecting...");
257 mConnectionHandler.sendMessage(
258 mConnectionHandler.obtainMessage(MSG_TRY_CONNECTING));
259 final long shouldEnd =
260 SystemClock.elapsedRealtime() + SERVICE_CONNECTION_WAIT_TIME_MS;
261 long waitTime = SERVICE_CONNECTION_WAIT_TIME_MS;
262 while (waitTime > 0) {
263 try {
264 // TODO: consider using Java concurrent construct instead of raw object wait
265 this.wait(waitTime);
266 } catch (InterruptedException e) {
267 Slog.w(TAG, "Connection wait interrupted", e);
268 }
269 if (mService != null) {
270 // Success
271 return mService;
272 }
273 // Calculate remaining waiting time to make sure we wait the full timeout period
274 waitTime = shouldEnd - SystemClock.elapsedRealtime();
275 }
276 // Timed out. Something's really wrong.
277 Slog.e(TAG, "Can not connect to MmsService (timed out)");
278 return null;
Ye Wend97e1fd2014-07-24 12:56:45 -0700279 }
280 }
281
282 /**
Ye Wen61c8d232015-04-01 11:27:14 -0700283 * Make sure to return a non-empty service instance. Return the connected MmsService
284 * instance, if not connected, try connecting. If fail to connect, return a fake service
285 * instance which returns failure to service caller.
286 *
287 * @return a non-empty service instance, real or fake
Ye Wend97e1fd2014-07-24 12:56:45 -0700288 */
289 private IMms getServiceGuarded() {
Ye Wen61c8d232015-04-01 11:27:14 -0700290 final IMms service = getOrConnectService();
291 if (service != null) {
292 return service;
293 }
294 return mServiceStubForFailure;
Ye Wend97e1fd2014-07-24 12:56:45 -0700295 }
296
297 private AppOpsManager getAppOpsManager() {
298 if (mAppOpsManager == null) {
299 mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
300 }
301 return mAppOpsManager;
302 }
303
304 private PackageManager getPackageManager() {
305 if (mPackageManager == null) {
306 mPackageManager = mContext.getPackageManager();
307 }
308 return mPackageManager;
309 }
310
311 private TelephonyManager getTelephonyManager() {
312 if (mTelephonyManager == null) {
313 mTelephonyManager = (TelephonyManager) mContext.getSystemService(
314 Context.TELEPHONY_SERVICE);
315 }
316 return mTelephonyManager;
317 }
318
Ye Wenbdc3a462014-11-11 11:17:28 -0800319 private String getCallingPackageName() {
320 final String[] packages = getPackageManager().getPackagesForUid(Binder.getCallingUid());
321 if (packages != null && packages.length > 0) {
322 return packages[0];
323 }
324 return "unknown";
325 }
326
Ye Wend97e1fd2014-07-24 12:56:45 -0700327 // Service API calls implementation, proxied to the real MmsService in "com.android.mms.service"
328 private final class BinderService extends IMms.Stub {
Tom Taylor86201db2014-11-24 09:36:43 -0800329 private static final String PHONE_PACKAGE_NAME = "com.android.phone";
330
Ye Wend97e1fd2014-07-24 12:56:45 -0700331 @Override
Wink Saville63f03dd2014-10-23 10:44:45 -0700332 public void sendMessage(int subId, String callingPkg, Uri contentUri,
Ye Wen8179c2a2014-09-04 15:36:11 -0700333 String locationUrl, Bundle configOverrides, PendingIntent sentIntent)
Julian Odell31ef14d2014-08-25 17:53:52 -0700334 throws RemoteException {
Ye Wenbdc3a462014-11-11 11:17:28 -0800335 Slog.d(TAG, "sendMessage() by " + callingPkg);
Ye Wend97e1fd2014-07-24 12:56:45 -0700336 mContext.enforceCallingPermission(Manifest.permission.SEND_SMS, "Send MMS message");
337 if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
338 callingPkg) != AppOpsManager.MODE_ALLOWED) {
339 return;
340 }
Tom Taylor86201db2014-11-24 09:36:43 -0800341 contentUri = adjustUriForUserAndGrantPermission(contentUri,
Cheuksan Wang5cec9202014-12-16 13:40:36 -0800342 CarrierMessagingService.SERVICE_INTERFACE,
Tom Taylor86201db2014-11-24 09:36:43 -0800343 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Julian Odell31ef14d2014-08-25 17:53:52 -0700344 getServiceGuarded().sendMessage(subId, callingPkg, contentUri, locationUrl,
345 configOverrides, sentIntent);
Ye Wend97e1fd2014-07-24 12:56:45 -0700346 }
347
348 @Override
Wink Saville63f03dd2014-10-23 10:44:45 -0700349 public void downloadMessage(int subId, String callingPkg, String locationUrl,
Ye Wen8179c2a2014-09-04 15:36:11 -0700350 Uri contentUri, Bundle configOverrides,
Julian Odell31ef14d2014-08-25 17:53:52 -0700351 PendingIntent downloadedIntent) throws RemoteException {
Ye Wenbdc3a462014-11-11 11:17:28 -0800352 Slog.d(TAG, "downloadMessage() by " + callingPkg);
Ye Wend97e1fd2014-07-24 12:56:45 -0700353 mContext.enforceCallingPermission(Manifest.permission.RECEIVE_MMS,
354 "Download MMS message");
355 if (getAppOpsManager().noteOp(AppOpsManager.OP_RECEIVE_MMS, Binder.getCallingUid(),
356 callingPkg) != AppOpsManager.MODE_ALLOWED) {
357 return;
358 }
Tom Taylor86201db2014-11-24 09:36:43 -0800359 contentUri = adjustUriForUserAndGrantPermission(contentUri,
Cheuksan Wang5cec9202014-12-16 13:40:36 -0800360 CarrierMessagingService.SERVICE_INTERFACE,
Tom Taylor86201db2014-11-24 09:36:43 -0800361 Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
362
Julian Odell31ef14d2014-08-25 17:53:52 -0700363 getServiceGuarded().downloadMessage(subId, callingPkg, locationUrl, contentUri,
364 configOverrides, downloadedIntent);
Ye Wend97e1fd2014-07-24 12:56:45 -0700365 }
366
367 @Override
Wink Saville63f03dd2014-10-23 10:44:45 -0700368 public Bundle getCarrierConfigValues(int subId) throws RemoteException {
Ye Wenbdc3a462014-11-11 11:17:28 -0800369 Slog.d(TAG, "getCarrierConfigValues() by " + getCallingPackageName());
Shri Borde72379722014-09-02 09:48:49 -0700370 return getServiceGuarded().getCarrierConfigValues(subId);
Ye Wend97e1fd2014-07-24 12:56:45 -0700371 }
372
373 @Override
374 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)
389 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
497 * @param action The intent action used to find the associated carrier app
498 * @param permission The permission to add
499 * @return The adjusted Uri containing the calling userId.
500 */
501 private Uri adjustUriForUserAndGrantPermission(Uri contentUri, String action,
502 int permission) {
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 {
Jeff Sharkey7ff418d2016-11-30 14:29:59 -0700515 LocalServices.getService(ActivityManagerInternal.class)
516 .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);
521 TelephonyManager telephonyManager =
522 (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
523 List<String> carrierPackages = telephonyManager.getCarrierPackageNamesForIntent(
524 intent);
525 if (carrierPackages != null && carrierPackages.size() == 1) {
Jeff Sharkey7ff418d2016-11-30 14:29:59 -0700526 LocalServices.getService(ActivityManagerInternal.class)
527 .grantUriPermissionFromIntent(callingUid, carrierPackages.get(0),
528 grantIntent, UserHandle.USER_SYSTEM);
Tom Taylor86201db2014-11-24 09:36:43 -0800529 }
530 } finally {
531 Binder.restoreCallingIdentity(token);
532 }
533 return contentUri;
534 }
Ye Wend97e1fd2014-07-24 12:56:45 -0700535 }
536}