blob: 94096152670d752309abe0d1c1be5b9b312daf56 [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;
Ye Wend97e1fd2014-07-24 12:56:45 -070040import android.telephony.TelephonyManager;
41import android.util.Slog;
42
Ye Wenbdc3a462014-11-11 11:17:28 -080043import com.android.internal.telephony.IMms;
44
Tom Taylor86201db2014-11-24 09:36:43 -080045import java.util.List;
46
Ye Wend97e1fd2014-07-24 12:56:45 -070047/**
48 * This class is a proxy for MmsService APIs. We need this because MmsService runs
49 * in phone process and may crash anytime. This manages a connection to the actual
50 * MmsService and bridges the public SMS/MMS APIs with MmsService implementation.
51 */
52public class MmsServiceBroker extends SystemService {
53 private static final String TAG = "MmsServiceBroker";
54
55 private static final ComponentName MMS_SERVICE_COMPONENT =
56 new ComponentName("com.android.mms.service", "com.android.mms.service.MmsService");
57
58 private static final int MSG_TRY_CONNECTING = 1;
59
Ye Wenfa58ac02014-07-31 17:15:30 -070060 private static final Uri FAKE_SMS_SENT_URI = Uri.parse("content://sms/sent/0");
61 private static final Uri FAKE_MMS_SENT_URI = Uri.parse("content://mms/sent/0");
62 private static final Uri FAKE_SMS_DRAFT_URI = Uri.parse("content://sms/draft/0");
63 private static final Uri FAKE_MMS_DRAFT_URI = Uri.parse("content://mms/draft/0");
64
Ye Wen724dbbd72014-10-07 15:33:51 -070065 private static final long SERVICE_CONNECTION_WAIT_TIME_MS = 4 * 1000L; // 4 seconds
66 private static final long RETRY_DELAY_ON_DISCONNECTION_MS = 3 * 1000L; // 3 seconds
67
Ye Wend97e1fd2014-07-24 12:56:45 -070068 private Context mContext;
69 // The actual MMS service instance to invoke
70 private volatile IMms mService;
Ye Wend97e1fd2014-07-24 12:56:45 -070071
72 // Cached system service instances
73 private volatile AppOpsManager mAppOpsManager = null;
74 private volatile PackageManager mPackageManager = null;
75 private volatile TelephonyManager mTelephonyManager = null;
76
77 private final Handler mConnectionHandler = new Handler() {
78 @Override
79 public void handleMessage(Message msg) {
80 switch (msg.what) {
81 case MSG_TRY_CONNECTING:
82 tryConnecting();
83 break;
84 default:
85 Slog.e(TAG, "Unknown message");
86 }
87 }
88 };
89
90 private ServiceConnection mConnection = new ServiceConnection() {
91 @Override
92 public void onServiceConnected(ComponentName name, IBinder service) {
93 Slog.i(TAG, "MmsService connected");
94 synchronized (MmsServiceBroker.this) {
95 mService = IMms.Stub.asInterface(service);
Ye Wen724dbbd72014-10-07 15:33:51 -070096 MmsServiceBroker.this.notifyAll();
Ye Wend97e1fd2014-07-24 12:56:45 -070097 }
98 }
99
100 @Override
101 public void onServiceDisconnected(ComponentName name) {
102 Slog.i(TAG, "MmsService unexpectedly disconnected");
103 synchronized (MmsServiceBroker.this) {
104 mService = null;
Ye Wen724dbbd72014-10-07 15:33:51 -0700105 MmsServiceBroker.this.notifyAll();
Ye Wend97e1fd2014-07-24 12:56:45 -0700106 }
Ye Wen724dbbd72014-10-07 15:33:51 -0700107 // Retry connecting, but not too eager (with a delay)
108 // since it may come back by itself.
109 mConnectionHandler.sendMessageDelayed(
110 mConnectionHandler.obtainMessage(MSG_TRY_CONNECTING),
111 RETRY_DELAY_ON_DISCONNECTION_MS);
Ye Wend97e1fd2014-07-24 12:56:45 -0700112 }
113 };
114
Ye Wen61c8d232015-04-01 11:27:14 -0700115 // Instance of IMms for returning failure to service API caller,
116 // used when MmsService cannot be connected.
117 private final IMms mServiceStubForFailure = new IMms() {
118
119 @Override
120 public IBinder asBinder() {
121 return null;
122 }
123
124 @Override
125 public void sendMessage(int subId, String callingPkg, Uri contentUri, String locationUrl,
126 Bundle configOverrides, PendingIntent sentIntent) throws RemoteException {
127 returnPendingIntentWithError(sentIntent);
128 }
129
130 @Override
131 public void downloadMessage(int subId, String callingPkg, String locationUrl,
132 Uri contentUri, Bundle configOverrides, PendingIntent downloadedIntent)
133 throws RemoteException {
134 returnPendingIntentWithError(downloadedIntent);
135 }
136
137 @Override
138 public Bundle getCarrierConfigValues(int subId) throws RemoteException {
139 return null;
140 }
141
142 @Override
143 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)
Julian Odell31ef14d2014-08-25 17:53:52 -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) {
338 return;
339 }
Tom Taylor86201db2014-11-24 09:36:43 -0800340 contentUri = adjustUriForUserAndGrantPermission(contentUri,
Cheuksan Wang5cec9202014-12-16 13:40:36 -0800341 CarrierMessagingService.SERVICE_INTERFACE,
Tom Taylor86201db2014-11-24 09:36:43 -0800342 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Julian Odell31ef14d2014-08-25 17:53:52 -0700343 getServiceGuarded().sendMessage(subId, callingPkg, contentUri, locationUrl,
344 configOverrides, sentIntent);
Ye Wend97e1fd2014-07-24 12:56:45 -0700345 }
346
347 @Override
Wink Saville63f03dd2014-10-23 10:44:45 -0700348 public void downloadMessage(int subId, String callingPkg, String locationUrl,
Ye Wen8179c2a2014-09-04 15:36:11 -0700349 Uri contentUri, Bundle configOverrides,
Julian Odell31ef14d2014-08-25 17:53:52 -0700350 PendingIntent downloadedIntent) throws RemoteException {
Ye Wenbdc3a462014-11-11 11:17:28 -0800351 Slog.d(TAG, "downloadMessage() by " + callingPkg);
Ye Wend97e1fd2014-07-24 12:56:45 -0700352 mContext.enforceCallingPermission(Manifest.permission.RECEIVE_MMS,
353 "Download MMS message");
354 if (getAppOpsManager().noteOp(AppOpsManager.OP_RECEIVE_MMS, Binder.getCallingUid(),
355 callingPkg) != AppOpsManager.MODE_ALLOWED) {
356 return;
357 }
Tom Taylor86201db2014-11-24 09:36:43 -0800358 contentUri = adjustUriForUserAndGrantPermission(contentUri,
Cheuksan Wang5cec9202014-12-16 13:40:36 -0800359 CarrierMessagingService.SERVICE_INTERFACE,
Tom Taylor86201db2014-11-24 09:36:43 -0800360 Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
361
Julian Odell31ef14d2014-08-25 17:53:52 -0700362 getServiceGuarded().downloadMessage(subId, callingPkg, locationUrl, contentUri,
363 configOverrides, downloadedIntent);
Ye Wend97e1fd2014-07-24 12:56:45 -0700364 }
365
366 @Override
Wink Saville63f03dd2014-10-23 10:44:45 -0700367 public Bundle getCarrierConfigValues(int subId) throws RemoteException {
Ye Wenbdc3a462014-11-11 11:17:28 -0800368 Slog.d(TAG, "getCarrierConfigValues() by " + getCallingPackageName());
Shri Borde72379722014-09-02 09:48:49 -0700369 return getServiceGuarded().getCarrierConfigValues(subId);
Ye Wend97e1fd2014-07-24 12:56:45 -0700370 }
371
372 @Override
373 public Uri importTextMessage(String callingPkg, String address, int type, String text,
374 long timestampMillis, boolean seen, boolean read) throws RemoteException {
375 mContext.enforceCallingPermission(Manifest.permission.WRITE_SMS, "Import SMS message");
376 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 mContext.enforceCallingPermission(Manifest.permission.WRITE_SMS, "Import MMS message");
391 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
392 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Ye Wenfa58ac02014-07-31 17:15:30 -0700393 // Silently fail AppOps failure due to not being the default SMS app
394 // while writing the TelephonyProvider
395 return FAKE_MMS_SENT_URI;
Ye Wend97e1fd2014-07-24 12:56:45 -0700396 }
397 return getServiceGuarded().importMultimediaMessage(
Julian Odell31ef14d2014-08-25 17:53:52 -0700398 callingPkg, contentUri, messageId, timestampSecs, seen, read);
Ye Wend97e1fd2014-07-24 12:56:45 -0700399 }
400
401 @Override
402 public boolean deleteStoredMessage(String callingPkg, Uri messageUri)
403 throws RemoteException {
404 mContext.enforceCallingPermission(Manifest.permission.WRITE_SMS,
405 "Delete SMS/MMS message");
406 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
407 callingPkg) != AppOpsManager.MODE_ALLOWED) {
408 return false;
409 }
410 return getServiceGuarded().deleteStoredMessage(callingPkg, messageUri);
411 }
412
413 @Override
414 public boolean deleteStoredConversation(String callingPkg, long conversationId)
415 throws RemoteException {
416 mContext.enforceCallingPermission(Manifest.permission.WRITE_SMS, "Delete conversation");
417 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
418 callingPkg) != AppOpsManager.MODE_ALLOWED) {
419 return false;
420 }
421 return getServiceGuarded().deleteStoredConversation(callingPkg, conversationId);
422 }
423
424 @Override
425 public boolean updateStoredMessageStatus(String callingPkg, Uri messageUri,
426 ContentValues statusValues) throws RemoteException {
427 mContext.enforceCallingPermission(Manifest.permission.WRITE_SMS,
428 "Update SMS/MMS message");
429 return getServiceGuarded()
430 .updateStoredMessageStatus(callingPkg, messageUri, statusValues);
431 }
432
433 @Override
Ye Wena3dbd102014-07-29 10:42:25 -0700434 public boolean archiveStoredConversation(String callingPkg, long conversationId,
435 boolean archived) throws RemoteException {
436 mContext.enforceCallingPermission(Manifest.permission.WRITE_SMS,
437 "Update SMS/MMS message");
438 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 {
445 mContext.enforceCallingPermission(Manifest.permission.WRITE_SMS, "Add SMS draft");
446 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
447 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Ye Wenfa58ac02014-07-31 17:15:30 -0700448 // Silently fail AppOps failure due to not being the default SMS app
449 // while writing the TelephonyProvider
450 return FAKE_SMS_DRAFT_URI;
Ye Wend97e1fd2014-07-24 12:56:45 -0700451 }
452 return getServiceGuarded().addTextMessageDraft(callingPkg, address, text);
453 }
454
455 @Override
Julian Odell31ef14d2014-08-25 17:53:52 -0700456 public Uri addMultimediaMessageDraft(String callingPkg, Uri contentUri)
457 throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700458 mContext.enforceCallingPermission(Manifest.permission.WRITE_SMS, "Add MMS draft");
459 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
460 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Ye Wenfa58ac02014-07-31 17:15:30 -0700461 // Silently fail AppOps failure due to not being the default SMS app
462 // while writing the TelephonyProvider
463 return FAKE_MMS_DRAFT_URI;
Ye Wend97e1fd2014-07-24 12:56:45 -0700464 }
Julian Odell31ef14d2014-08-25 17:53:52 -0700465 return getServiceGuarded().addMultimediaMessageDraft(callingPkg, contentUri);
Ye Wend97e1fd2014-07-24 12:56:45 -0700466 }
467
468 @Override
Wink Saville63f03dd2014-10-23 10:44:45 -0700469 public void sendStoredMessage(int subId, String callingPkg, Uri messageUri,
Ye Wen8179c2a2014-09-04 15:36:11 -0700470 Bundle configOverrides, PendingIntent sentIntent) throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700471 mContext.enforceCallingPermission(Manifest.permission.SEND_SMS,
472 "Send stored MMS message");
473 if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
474 callingPkg) != AppOpsManager.MODE_ALLOWED) {
475 return;
476 }
Ye Wen63c00c42014-08-01 13:38:58 -0700477 getServiceGuarded().sendStoredMessage(subId, callingPkg, messageUri, configOverrides,
478 sentIntent);
Ye Wend97e1fd2014-07-24 12:56:45 -0700479 }
480
481 @Override
482 public void setAutoPersisting(String callingPkg, boolean enabled) throws RemoteException {
483 mContext.enforceCallingPermission(Manifest.permission.WRITE_SMS, "Set auto persist");
484 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
502 * @param action The intent action used to find the associated carrier app
503 * @param permission The permission to add
504 * @return The adjusted Uri containing the calling userId.
505 */
506 private Uri adjustUriForUserAndGrantPermission(Uri contentUri, String action,
507 int permission) {
508 final int callingUserId = UserHandle.getCallingUserId();
509 if (callingUserId != UserHandle.USER_OWNER) {
510 contentUri = ContentProvider.maybeAddUserId(contentUri, callingUserId);
511 }
512 long token = Binder.clearCallingIdentity();
513 try {
514 mContext.grantUriPermission(PHONE_PACKAGE_NAME, contentUri, permission);
515
516 // Grant permission for the carrier app.
517 Intent intent = new Intent(action);
518 TelephonyManager telephonyManager =
519 (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
520 List<String> carrierPackages = telephonyManager.getCarrierPackageNamesForIntent(
521 intent);
522 if (carrierPackages != null && carrierPackages.size() == 1) {
523 mContext.grantUriPermission(carrierPackages.get(0), contentUri, permission);
524 }
525 } finally {
526 Binder.restoreCallingIdentity(token);
527 }
528 return contentUri;
529 }
Ye Wend97e1fd2014-07-24 12:56:45 -0700530 }
531}