blob: e0352e091af7c8cf6ec06479c3bdcf03630a45c4 [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 {
Ye Wend97e1fd2014-07-24 12:56:45 -0700375 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
376 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Ye Wenfa58ac02014-07-31 17:15:30 -0700377 // Silently fail AppOps failure due to not being the default SMS app
378 // while writing the TelephonyProvider
379 return FAKE_SMS_SENT_URI;
Ye Wend97e1fd2014-07-24 12:56:45 -0700380 }
381 return getServiceGuarded().importTextMessage(
382 callingPkg, address, type, text, timestampMillis, seen, read);
383 }
384
385 @Override
Julian Odell31ef14d2014-08-25 17:53:52 -0700386 public Uri importMultimediaMessage(String callingPkg, Uri contentUri,
387 String messageId, long timestampSecs, boolean seen, boolean read)
388 throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700389 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
390 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Ye Wenfa58ac02014-07-31 17:15:30 -0700391 // Silently fail AppOps failure due to not being the default SMS app
392 // while writing the TelephonyProvider
393 return FAKE_MMS_SENT_URI;
Ye Wend97e1fd2014-07-24 12:56:45 -0700394 }
395 return getServiceGuarded().importMultimediaMessage(
Julian Odell31ef14d2014-08-25 17:53:52 -0700396 callingPkg, contentUri, messageId, timestampSecs, seen, read);
Ye Wend97e1fd2014-07-24 12:56:45 -0700397 }
398
399 @Override
400 public boolean deleteStoredMessage(String callingPkg, Uri messageUri)
401 throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700402 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
403 callingPkg) != AppOpsManager.MODE_ALLOWED) {
404 return false;
405 }
406 return getServiceGuarded().deleteStoredMessage(callingPkg, messageUri);
407 }
408
409 @Override
410 public boolean deleteStoredConversation(String callingPkg, long conversationId)
411 throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700412 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
413 callingPkg) != AppOpsManager.MODE_ALLOWED) {
414 return false;
415 }
416 return getServiceGuarded().deleteStoredConversation(callingPkg, conversationId);
417 }
418
419 @Override
420 public boolean updateStoredMessageStatus(String callingPkg, Uri messageUri,
421 ContentValues statusValues) throws RemoteException {
Svetoslav6c589572015-04-16 16:19:24 -0700422 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
423 callingPkg) != AppOpsManager.MODE_ALLOWED) {
424 return false;
425 }
Ye Wend97e1fd2014-07-24 12:56:45 -0700426 return getServiceGuarded()
427 .updateStoredMessageStatus(callingPkg, messageUri, statusValues);
428 }
429
430 @Override
Ye Wena3dbd102014-07-29 10:42:25 -0700431 public boolean archiveStoredConversation(String callingPkg, long conversationId,
432 boolean archived) throws RemoteException {
Svetoslav6c589572015-04-16 16:19:24 -0700433 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
434 callingPkg) != AppOpsManager.MODE_ALLOWED) {
435 return false;
436 }
Ye Wena3dbd102014-07-29 10:42:25 -0700437 return getServiceGuarded()
438 .archiveStoredConversation(callingPkg, conversationId, archived);
439 }
440
441 @Override
Ye Wend97e1fd2014-07-24 12:56:45 -0700442 public Uri addTextMessageDraft(String callingPkg, String address, String text)
443 throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700444 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
445 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Ye Wenfa58ac02014-07-31 17:15:30 -0700446 // Silently fail AppOps failure due to not being the default SMS app
447 // while writing the TelephonyProvider
448 return FAKE_SMS_DRAFT_URI;
Ye Wend97e1fd2014-07-24 12:56:45 -0700449 }
450 return getServiceGuarded().addTextMessageDraft(callingPkg, address, text);
451 }
452
453 @Override
Julian Odell31ef14d2014-08-25 17:53:52 -0700454 public Uri addMultimediaMessageDraft(String callingPkg, Uri contentUri)
455 throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700456 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
457 callingPkg) != AppOpsManager.MODE_ALLOWED) {
Ye Wenfa58ac02014-07-31 17:15:30 -0700458 // Silently fail AppOps failure due to not being the default SMS app
459 // while writing the TelephonyProvider
460 return FAKE_MMS_DRAFT_URI;
Ye Wend97e1fd2014-07-24 12:56:45 -0700461 }
Julian Odell31ef14d2014-08-25 17:53:52 -0700462 return getServiceGuarded().addMultimediaMessageDraft(callingPkg, contentUri);
Ye Wend97e1fd2014-07-24 12:56:45 -0700463 }
464
465 @Override
Wink Saville63f03dd2014-10-23 10:44:45 -0700466 public void sendStoredMessage(int subId, String callingPkg, Uri messageUri,
Ye Wen8179c2a2014-09-04 15:36:11 -0700467 Bundle configOverrides, PendingIntent sentIntent) throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700468 if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
469 callingPkg) != AppOpsManager.MODE_ALLOWED) {
470 return;
471 }
Ye Wen63c00c42014-08-01 13:38:58 -0700472 getServiceGuarded().sendStoredMessage(subId, callingPkg, messageUri, configOverrides,
473 sentIntent);
Ye Wend97e1fd2014-07-24 12:56:45 -0700474 }
475
476 @Override
477 public void setAutoPersisting(String callingPkg, boolean enabled) throws RemoteException {
Ye Wend97e1fd2014-07-24 12:56:45 -0700478 if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
479 callingPkg) != AppOpsManager.MODE_ALLOWED) {
480 return;
481 }
482 getServiceGuarded().setAutoPersisting(callingPkg, enabled);
483 }
484
485 @Override
486 public boolean getAutoPersisting() throws RemoteException {
487 return getServiceGuarded().getAutoPersisting();
488 }
Tom Taylor86201db2014-11-24 09:36:43 -0800489
490 /**
491 * Modifies the Uri to contain the caller's userId, if necessary.
492 * Grants the phone package on primary user permission to access the contentUri,
493 * even if the caller is not in the primary user.
494 *
495 * @param contentUri The Uri to adjust
496 * @param action The intent action used to find the associated carrier app
497 * @param permission The permission to add
498 * @return The adjusted Uri containing the calling userId.
499 */
500 private Uri adjustUriForUserAndGrantPermission(Uri contentUri, String action,
501 int permission) {
502 final int callingUserId = UserHandle.getCallingUserId();
503 if (callingUserId != UserHandle.USER_OWNER) {
504 contentUri = ContentProvider.maybeAddUserId(contentUri, callingUserId);
505 }
506 long token = Binder.clearCallingIdentity();
507 try {
508 mContext.grantUriPermission(PHONE_PACKAGE_NAME, contentUri, permission);
509
510 // Grant permission for the carrier app.
511 Intent intent = new Intent(action);
512 TelephonyManager telephonyManager =
513 (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
514 List<String> carrierPackages = telephonyManager.getCarrierPackageNamesForIntent(
515 intent);
516 if (carrierPackages != null && carrierPackages.size() == 1) {
517 mContext.grantUriPermission(carrierPackages.get(0), contentUri, permission);
518 }
519 } finally {
520 Binder.restoreCallingIdentity(token);
521 }
522 return contentUri;
523 }
Ye Wend97e1fd2014-07-24 12:56:45 -0700524 }
525}