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