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