1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
4  * Not a Contribution.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 package com.android.internal.telephony;
20 
21 import android.annotation.Nullable;
22 import android.app.ActivityThread;
23 import android.app.PendingIntent;
24 import android.content.Context;
25 import android.net.Uri;
26 import android.os.Binder;
27 import android.os.RemoteException;
28 import android.os.ServiceManager;
29 import android.provider.Telephony.Sms.Intents;
30 import android.telephony.Rlog;
31 import android.telephony.SmsManager;
32 import android.telephony.SubscriptionInfo;
33 import android.telephony.SubscriptionManager;
34 import android.telephony.TelephonyManager;
35 
36 import java.util.List;
37 
38 /**
39  * UiccSmsController to provide an inter-process communication to
40  * access Sms in Icc.
41  */
42 public class UiccSmsController extends ISms.Stub {
43     static final String LOG_TAG = "RIL_UiccSmsController";
44 
45     protected Phone[] mPhone;
46 
UiccSmsController(Phone[] phone)47     protected UiccSmsController(Phone[] phone){
48         mPhone = phone;
49 
50         if (ServiceManager.getService("isms") == null) {
51             ServiceManager.addService("isms", this);
52         }
53     }
54 
55     @Override
56     public boolean
updateMessageOnIccEfForSubscriber(int subId, String callingPackage, int index, int status, byte[] pdu)57     updateMessageOnIccEfForSubscriber(int subId, String callingPackage, int index, int status,
58                 byte[] pdu) throws android.os.RemoteException {
59         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
60         if (iccSmsIntMgr != null) {
61             return iccSmsIntMgr.updateMessageOnIccEf(callingPackage, index, status, pdu);
62         } else {
63             Rlog.e(LOG_TAG,"updateMessageOnIccEfForSubscriber iccSmsIntMgr is null" +
64                           " for Subscription: " + subId);
65             return false;
66         }
67     }
68 
69     @Override
copyMessageToIccEfForSubscriber(int subId, String callingPackage, int status, byte[] pdu, byte[] smsc)70     public boolean copyMessageToIccEfForSubscriber(int subId, String callingPackage, int status,
71             byte[] pdu, byte[] smsc) throws android.os.RemoteException {
72         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
73         if (iccSmsIntMgr != null) {
74             return iccSmsIntMgr.copyMessageToIccEf(callingPackage, status, pdu, smsc);
75         } else {
76             Rlog.e(LOG_TAG,"copyMessageToIccEfForSubscriber iccSmsIntMgr is null" +
77                           " for Subscription: " + subId);
78             return false;
79         }
80     }
81 
82     @Override
getAllMessagesFromIccEfForSubscriber(int subId, String callingPackage)83     public List<SmsRawData> getAllMessagesFromIccEfForSubscriber(int subId, String callingPackage)
84                 throws android.os.RemoteException {
85         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
86         if (iccSmsIntMgr != null) {
87             return iccSmsIntMgr.getAllMessagesFromIccEf(callingPackage);
88         } else {
89             Rlog.e(LOG_TAG,"getAllMessagesFromIccEfForSubscriber iccSmsIntMgr is" +
90                           " null for Subscription: " + subId);
91             return null;
92         }
93     }
94 
95     @Override
sendDataForSubscriber(int subId, String callingPackage, String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent)96     public void sendDataForSubscriber(int subId, String callingPackage, String destAddr,
97             String scAddr, int destPort, byte[] data, PendingIntent sentIntent,
98             PendingIntent deliveryIntent) {
99         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
100         if (iccSmsIntMgr != null) {
101             iccSmsIntMgr.sendData(callingPackage, destAddr, scAddr, destPort, data,
102                     sentIntent, deliveryIntent);
103         } else {
104             Rlog.e(LOG_TAG,"sendDataForSubscriber iccSmsIntMgr is null for" +
105                           " Subscription: " + subId);
106             // TODO: Use a more specific error code to replace RESULT_ERROR_GENERIC_FAILURE.
107             sendErrorInPendingIntent(sentIntent, SmsManager.RESULT_ERROR_GENERIC_FAILURE);
108         }
109     }
110 
sendDataForSubscriberWithSelfPermissions(int subId, String callingPackage, String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent)111     public void sendDataForSubscriberWithSelfPermissions(int subId, String callingPackage,
112             String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent,
113             PendingIntent deliveryIntent) {
114         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
115         if (iccSmsIntMgr != null) {
116             iccSmsIntMgr.sendDataWithSelfPermissions(callingPackage, destAddr, scAddr, destPort, data,
117                     sentIntent, deliveryIntent);
118         } else {
119             Rlog.e(LOG_TAG,"sendText iccSmsIntMgr is null for" +
120                           " Subscription: " + subId);
121         }
122     }
123 
sendText(String callingPackage, String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent)124     public void sendText(String callingPackage, String destAddr, String scAddr,
125             String text, PendingIntent sentIntent, PendingIntent deliveryIntent) {
126         sendTextForSubscriber(getPreferredSmsSubscription(), callingPackage, destAddr, scAddr,
127             text, sentIntent, deliveryIntent, true /* persistMessageForNonDefaultSmsApp*/);
128     }
129 
130     @Override
sendTextForSubscriber(int subId, String callingPackage, String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessageForNonDefaultSmsApp)131     public void sendTextForSubscriber(int subId, String callingPackage, String destAddr,
132             String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent,
133             boolean persistMessageForNonDefaultSmsApp) {
134         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
135         if (iccSmsIntMgr != null) {
136             iccSmsIntMgr.sendText(callingPackage, destAddr, scAddr, text, sentIntent,
137                     deliveryIntent, persistMessageForNonDefaultSmsApp);
138         } else {
139             Rlog.e(LOG_TAG,"sendTextForSubscriber iccSmsIntMgr is null for" +
140                           " Subscription: " + subId);
141             sendErrorInPendingIntent(sentIntent, SmsManager.RESULT_ERROR_GENERIC_FAILURE);
142         }
143     }
144 
sendTextForSubscriberWithSelfPermissions(int subId, String callingPackage, String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessage)145     public void sendTextForSubscriberWithSelfPermissions(int subId, String callingPackage,
146             String destAddr, String scAddr, String text, PendingIntent sentIntent,
147             PendingIntent deliveryIntent, boolean persistMessage) {
148         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
149         if (iccSmsIntMgr != null) {
150             iccSmsIntMgr.sendTextWithSelfPermissions(callingPackage, destAddr, scAddr, text,
151                     sentIntent, deliveryIntent, persistMessage);
152         } else {
153             Rlog.e(LOG_TAG,"sendText iccSmsIntMgr is null for" +
154                           " Subscription: " + subId);
155         }
156     }
157 
sendMultipartText(String callingPackage, String destAddr, String scAddr, List<String> parts, List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents)158     public void sendMultipartText(String callingPackage, String destAddr, String scAddr,
159             List<String> parts, List<PendingIntent> sentIntents,
160             List<PendingIntent> deliveryIntents) throws android.os.RemoteException {
161          sendMultipartTextForSubscriber(getPreferredSmsSubscription(), callingPackage, destAddr,
162                  scAddr, parts, sentIntents, deliveryIntents,
163                  true /* persistMessageForNonDefaultSmsApp */);
164     }
165 
166     @Override
sendMultipartTextForSubscriber(int subId, String callingPackage, String destAddr, String scAddr, List<String> parts, List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents, boolean persistMessageForNonDefaultSmsApp)167     public void sendMultipartTextForSubscriber(int subId, String callingPackage, String destAddr,
168             String scAddr, List<String> parts, List<PendingIntent> sentIntents,
169             List<PendingIntent> deliveryIntents, boolean persistMessageForNonDefaultSmsApp)
170             throws android.os.RemoteException {
171         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
172         if (iccSmsIntMgr != null ) {
173             iccSmsIntMgr.sendMultipartText(callingPackage, destAddr, scAddr, parts, sentIntents,
174                     deliveryIntents, persistMessageForNonDefaultSmsApp);
175         } else {
176             Rlog.e(LOG_TAG,"sendMultipartTextForSubscriber iccSmsIntMgr is null for" +
177                           " Subscription: " + subId);
178             sendErrorInPendingIntents(sentIntents, SmsManager.RESULT_ERROR_GENERIC_FAILURE);
179         }
180     }
181 
182     @Override
enableCellBroadcastForSubscriber(int subId, int messageIdentifier, int ranType)183     public boolean enableCellBroadcastForSubscriber(int subId, int messageIdentifier, int ranType)
184                 throws android.os.RemoteException {
185         return enableCellBroadcastRangeForSubscriber(subId, messageIdentifier, messageIdentifier,
186                 ranType);
187     }
188 
189     @Override
enableCellBroadcastRangeForSubscriber(int subId, int startMessageId, int endMessageId, int ranType)190     public boolean enableCellBroadcastRangeForSubscriber(int subId, int startMessageId,
191             int endMessageId, int ranType) throws android.os.RemoteException {
192         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
193         if (iccSmsIntMgr != null ) {
194             return iccSmsIntMgr.enableCellBroadcastRange(startMessageId, endMessageId, ranType);
195         } else {
196             Rlog.e(LOG_TAG,"enableCellBroadcastRangeForSubscriber iccSmsIntMgr is null for" +
197                           " Subscription: " + subId);
198         }
199         return false;
200     }
201 
202     @Override
disableCellBroadcastForSubscriber(int subId, int messageIdentifier, int ranType)203     public boolean disableCellBroadcastForSubscriber(int subId, int messageIdentifier, int ranType)
204                 throws android.os.RemoteException {
205         return disableCellBroadcastRangeForSubscriber(subId, messageIdentifier, messageIdentifier,
206                 ranType);
207     }
208 
209     @Override
disableCellBroadcastRangeForSubscriber(int subId, int startMessageId, int endMessageId, int ranType)210     public boolean disableCellBroadcastRangeForSubscriber(int subId, int startMessageId,
211             int endMessageId, int ranType) throws android.os.RemoteException {
212         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
213         if (iccSmsIntMgr != null ) {
214             return iccSmsIntMgr.disableCellBroadcastRange(startMessageId, endMessageId, ranType);
215         } else {
216             Rlog.e(LOG_TAG,"disableCellBroadcastRangeForSubscriber iccSmsIntMgr is null for" +
217                           " Subscription:"+subId);
218         }
219        return false;
220     }
221 
222     @Override
getPremiumSmsPermission(String packageName)223     public int getPremiumSmsPermission(String packageName) {
224         return getPremiumSmsPermissionForSubscriber(getPreferredSmsSubscription(), packageName);
225     }
226 
227     @Override
getPremiumSmsPermissionForSubscriber(int subId, String packageName)228     public int getPremiumSmsPermissionForSubscriber(int subId, String packageName) {
229         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
230         if (iccSmsIntMgr != null ) {
231             return iccSmsIntMgr.getPremiumSmsPermission(packageName);
232         } else {
233             Rlog.e(LOG_TAG, "getPremiumSmsPermissionForSubscriber iccSmsIntMgr is null");
234         }
235         //TODO Rakesh
236         return 0;
237     }
238 
239     @Override
setPremiumSmsPermission(String packageName, int permission)240     public void setPremiumSmsPermission(String packageName, int permission) {
241          setPremiumSmsPermissionForSubscriber(getPreferredSmsSubscription(), packageName, permission);
242     }
243 
244     @Override
setPremiumSmsPermissionForSubscriber(int subId, String packageName, int permission)245     public void setPremiumSmsPermissionForSubscriber(int subId, String packageName, int permission) {
246         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
247         if (iccSmsIntMgr != null ) {
248             iccSmsIntMgr.setPremiumSmsPermission(packageName, permission);
249         } else {
250             Rlog.e(LOG_TAG, "setPremiumSmsPermissionForSubscriber iccSmsIntMgr is null");
251         }
252     }
253 
254     @Override
isImsSmsSupportedForSubscriber(int subId)255     public boolean isImsSmsSupportedForSubscriber(int subId) {
256         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
257         if (iccSmsIntMgr != null ) {
258             return iccSmsIntMgr.isImsSmsSupported();
259         } else {
260             Rlog.e(LOG_TAG, "isImsSmsSupportedForSubscriber iccSmsIntMgr is null");
261         }
262         return false;
263     }
264 
265     @Override
isSmsSimPickActivityNeeded(int subId)266     public boolean isSmsSimPickActivityNeeded(int subId) {
267         final Context context = ActivityThread.currentApplication().getApplicationContext();
268         TelephonyManager telephonyManager =
269                 (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
270         List<SubscriptionInfo> subInfoList;
271         final long identity = Binder.clearCallingIdentity();
272         try {
273             subInfoList = SubscriptionManager.from(context).getActiveSubscriptionInfoList();
274         } finally {
275             Binder.restoreCallingIdentity(identity);
276         }
277 
278         if (subInfoList != null) {
279             final int subInfoLength = subInfoList.size();
280 
281             for (int i = 0; i < subInfoLength; ++i) {
282                 final SubscriptionInfo sir = subInfoList.get(i);
283                 if (sir != null && sir.getSubscriptionId() == subId) {
284                     // The subscription id is valid, sms sim pick activity not needed
285                     return false;
286                 }
287             }
288 
289             // If reached here and multiple SIMs and subs present, sms sim pick activity is needed
290             if (subInfoLength > 0 && telephonyManager.getSimCount() > 1) {
291                 return true;
292             }
293         }
294 
295         return false;
296     }
297 
298     @Override
getImsSmsFormatForSubscriber(int subId)299     public String getImsSmsFormatForSubscriber(int subId) {
300         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
301         if (iccSmsIntMgr != null ) {
302             return iccSmsIntMgr.getImsSmsFormat();
303         } else {
304             Rlog.e(LOG_TAG, "getImsSmsFormatForSubscriber iccSmsIntMgr is null");
305         }
306         return null;
307     }
308 
309     @Override
injectSmsPduForSubscriber( int subId, byte[] pdu, String format, PendingIntent receivedIntent)310     public void injectSmsPduForSubscriber(
311             int subId, byte[] pdu, String format, PendingIntent receivedIntent) {
312         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
313         if (iccSmsIntMgr != null) {
314             iccSmsIntMgr.injectSmsPdu(pdu, format, receivedIntent);
315         } else {
316             Rlog.e(LOG_TAG, "injectSmsPduForSubscriber iccSmsIntMgr is null");
317             // RESULT_SMS_GENERIC_ERROR is documented for injectSmsPdu
318             sendErrorInPendingIntent(receivedIntent, Intents.RESULT_SMS_GENERIC_ERROR);
319         }
320     }
321 
322     /**
323      * get sms interface manager object based on subscription.
324      **/
getIccSmsInterfaceManager(int subId)325     private @Nullable IccSmsInterfaceManager getIccSmsInterfaceManager(int subId) {
326         if (!isActiveSubId(subId)) {
327             Rlog.e(LOG_TAG, "Subscription " + subId + " is inactive.");
328             return null;
329         }
330 
331         int phoneId = SubscriptionController.getInstance().getPhoneId(subId) ;
332         //Fixme: for multi-subscription case
333         if (!SubscriptionManager.isValidPhoneId(phoneId)
334                 || phoneId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
335             phoneId = 0;
336         }
337 
338         try {
339             return (IccSmsInterfaceManager)
340                 ((Phone)mPhone[(int)phoneId]).getIccSmsInterfaceManager();
341         } catch (NullPointerException e) {
342             Rlog.e(LOG_TAG, "Exception is :"+e.toString()+" For subscription :"+subId );
343             e.printStackTrace();
344             return null;
345         } catch (ArrayIndexOutOfBoundsException e) {
346             Rlog.e(LOG_TAG, "Exception is :"+e.toString()+" For subscription :"+subId );
347             e.printStackTrace();
348             return null;
349         }
350     }
351 
352     /**
353        Gets User preferred SMS subscription */
354     @Override
getPreferredSmsSubscription()355     public int getPreferredSmsSubscription() {
356         return SubscriptionController.getInstance().getDefaultSmsSubId();
357     }
358 
359     /**
360      * Get SMS prompt property,  enabled or not
361      **/
362     @Override
isSMSPromptEnabled()363     public boolean isSMSPromptEnabled() {
364         return PhoneFactory.isSMSPromptEnabled();
365     }
366 
367     @Override
sendStoredText(int subId, String callingPkg, Uri messageUri, String scAddress, PendingIntent sentIntent, PendingIntent deliveryIntent)368     public void sendStoredText(int subId, String callingPkg, Uri messageUri, String scAddress,
369             PendingIntent sentIntent, PendingIntent deliveryIntent) throws RemoteException {
370         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
371         if (iccSmsIntMgr != null) {
372             iccSmsIntMgr.sendStoredText(callingPkg, messageUri, scAddress, sentIntent,
373                     deliveryIntent);
374         } else {
375             Rlog.e(LOG_TAG,"sendStoredText iccSmsIntMgr is null for subscription: " + subId);
376             sendErrorInPendingIntent(sentIntent, SmsManager.RESULT_ERROR_GENERIC_FAILURE);
377         }
378     }
379 
380     @Override
sendStoredMultipartText(int subId, String callingPkg, Uri messageUri, String scAddress, List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents)381     public void sendStoredMultipartText(int subId, String callingPkg, Uri messageUri,
382             String scAddress, List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents)
383             throws RemoteException {
384         IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
385         if (iccSmsIntMgr != null ) {
386             iccSmsIntMgr.sendStoredMultipartText(callingPkg, messageUri, scAddress, sentIntents,
387                     deliveryIntents);
388         } else {
389             Rlog.e(LOG_TAG,"sendStoredMultipartText iccSmsIntMgr is null for subscription: "
390                     + subId);
391             sendErrorInPendingIntents(sentIntents, SmsManager.RESULT_ERROR_GENERIC_FAILURE);
392         }
393     }
394 
395     @Override
createAppSpecificSmsToken(int subId, String callingPkg, PendingIntent intent)396     public String createAppSpecificSmsToken(int subId, String callingPkg, PendingIntent intent) {
397         if (!isActiveSubId(subId)) {
398             Rlog.e(LOG_TAG, "Subscription " + subId + " is inactive.");
399             return null;
400         }
401 
402         int phoneId = SubscriptionController.getInstance().getPhoneId(subId);
403         //Fixme: for multi-subscription case
404         if (!SubscriptionManager.isValidPhoneId(phoneId)
405                 || phoneId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
406             phoneId = 0;
407         }
408         if (phoneId < 0 || phoneId >= mPhone.length || mPhone[phoneId] == null) {
409             Rlog.e(LOG_TAG, "phoneId " + phoneId + " points to an invalid phone");
410             return null;
411         }
412         AppSmsManager appSmsManager = mPhone[phoneId].getAppSmsManager();
413         return appSmsManager.createAppSpecificSmsToken(callingPkg, intent);
414     }
415 
416     /*
417      * @return true if the subId is active.
418      */
isActiveSubId(int subId)419     private boolean isActiveSubId(int subId) {
420         return SubscriptionController.getInstance().isActiveSubId(subId);
421     }
422 
sendErrorInPendingIntent(@ullable PendingIntent intent, int errorCode)423     private void sendErrorInPendingIntent(@Nullable PendingIntent intent, int errorCode) {
424         if (intent != null) {
425             try {
426                 intent.send(errorCode);
427             } catch (PendingIntent.CanceledException ex) {
428             }
429         }
430     }
431 
sendErrorInPendingIntents(List<PendingIntent> intents, int errorCode)432     private void sendErrorInPendingIntents(List<PendingIntent> intents, int errorCode) {
433         for (PendingIntent intent : intents) {
434             sendErrorInPendingIntent(intent, errorCode);
435         }
436     }
437 }
438