1 /*
2  * Copyright (C) 2006 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 
17 package com.android.internal.telephony.gsm;
18 
19 import static com.android.internal.telephony.SmsResponse.NO_ERROR_CODE;
20 
21 import android.compat.annotation.UnsupportedAppUsage;
22 import android.os.AsyncResult;
23 import android.os.Build;
24 import android.os.Message;
25 import android.telephony.ServiceState;
26 
27 import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
28 import com.android.internal.telephony.InboundSmsHandler;
29 import com.android.internal.telephony.Phone;
30 import com.android.internal.telephony.SMSDispatcher;
31 import com.android.internal.telephony.SmsConstants;
32 import com.android.internal.telephony.SmsController;
33 import com.android.internal.telephony.SmsDispatchersController;
34 import com.android.internal.telephony.SmsHeader;
35 import com.android.internal.telephony.SmsMessageBase;
36 import com.android.internal.telephony.uicc.IccRecords;
37 import com.android.internal.telephony.uicc.IccUtils;
38 import com.android.internal.telephony.uicc.UiccCardApplication;
39 import com.android.internal.telephony.uicc.UiccController;
40 import com.android.internal.telephony.util.SMSDispatcherUtil;
41 import com.android.telephony.Rlog;
42 
43 import java.util.HashMap;
44 import java.util.concurrent.atomic.AtomicReference;
45 
46 public final class GsmSMSDispatcher extends SMSDispatcher {
47     private static final String TAG = "GsmSMSDispatcher";
48     protected UiccController mUiccController = null;
49     private AtomicReference<IccRecords> mIccRecords = new AtomicReference<IccRecords>();
50     private AtomicReference<UiccCardApplication> mUiccApplication =
51             new AtomicReference<UiccCardApplication>();
52     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
53     private GsmInboundSmsHandler mGsmInboundSmsHandler;
54 
GsmSMSDispatcher(Phone phone, SmsDispatchersController smsDispatchersController, GsmInboundSmsHandler gsmInboundSmsHandler)55     public GsmSMSDispatcher(Phone phone, SmsDispatchersController smsDispatchersController,
56             GsmInboundSmsHandler gsmInboundSmsHandler) {
57         super(phone, smsDispatchersController);
58         mCi.setOnSmsStatus(this, EVENT_NEW_SMS_STATUS_REPORT, null);
59         mGsmInboundSmsHandler = gsmInboundSmsHandler;
60         mUiccController = UiccController.getInstance();
61         mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
62         Rlog.d(TAG, "GsmSMSDispatcher created");
63     }
64 
65     @Override
dispose()66     public void dispose() {
67         super.dispose();
68         mCi.unSetOnSmsStatus(this);
69         mUiccController.unregisterForIccChanged(this);
70     }
71 
72     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
73     @Override
getFormat()74     protected String getFormat() {
75         return SmsConstants.FORMAT_3GPP;
76     }
77 
78     /**
79      * Handles 3GPP format-specific events coming from the phone stack.
80      * Other events are handled by {@link SMSDispatcher#handleMessage}.
81      *
82      * @param msg the message to handle
83      */
84     @Override
handleMessage(Message msg)85     public void handleMessage(Message msg) {
86         switch (msg.what) {
87             case EVENT_NEW_ICC_SMS:
88                 // pass to InboundSmsHandler to process
89                 mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, msg.obj);
90                 break;
91 
92             case EVENT_ICC_CHANGED:
93                 onUpdateIccAvailability();
94                 break;
95 
96             default:
97                 super.handleMessage(msg);
98         }
99     }
100 
101     @Override
shouldBlockSmsForEcbm()102     protected boolean shouldBlockSmsForEcbm() {
103         // There is no such thing as ECBM for GSM. This only applies to CDMA.
104         return false;
105     }
106 
107     @Override
getSubmitPdu(String scAddr, String destAddr, String message, boolean statusReportRequested, SmsHeader smsHeader, int priority, int validityPeriod)108     protected SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
109             String message, boolean statusReportRequested, SmsHeader smsHeader, int priority,
110             int validityPeriod) {
111         return SMSDispatcherUtil.getSubmitPduGsm(scAddr, destAddr, message, statusReportRequested,
112                 validityPeriod);
113     }
114 
115     @Override
getSubmitPdu(String scAddr, String destAddr, int destPort, byte[] message, boolean statusReportRequested)116     protected SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
117             int destPort, byte[] message, boolean statusReportRequested) {
118         return SMSDispatcherUtil.getSubmitPduGsm(scAddr, destAddr, destPort, message,
119                 statusReportRequested);
120     }
121 
122     @Override
getSubmitPdu(String scAddr, String destAddr, String message, boolean statusReportRequested, SmsHeader smsHeader, int priority, int validityPeriod, int messageRef)123     protected SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
124             String message, boolean statusReportRequested, SmsHeader smsHeader, int priority,
125             int validityPeriod, int messageRef) {
126         return SMSDispatcherUtil.getSubmitPduGsm(scAddr, destAddr, message, statusReportRequested,
127                 validityPeriod, messageRef);
128     }
129 
130     @Override
getSubmitPdu(String scAddr, String destAddr, int destPort, byte[] message, boolean statusReportRequested, int messageRef)131     protected SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
132             int destPort, byte[] message, boolean statusReportRequested, int messageRef) {
133         return SMSDispatcherUtil.getSubmitPduGsm(scAddr, destAddr, destPort, message,
134                 statusReportRequested, messageRef);
135     }
136 
137     @Override
calculateLength(CharSequence messageBody, boolean use7bitOnly)138     protected TextEncodingDetails calculateLength(CharSequence messageBody, boolean use7bitOnly) {
139         return SMSDispatcherUtil.calculateLengthGsm(messageBody, use7bitOnly);
140     }
141 
142     @Override
handleStatusReport(Object o)143     protected void handleStatusReport(Object o) {
144         if (o instanceof AsyncResult) {
145             byte[] pdu = (byte[]) ((AsyncResult) o).result;
146             mSmsDispatchersController.handleSmsStatusReport(SmsConstants.FORMAT_3GPP, pdu);
147             mCi.acknowledgeLastIncomingGsmSms(true, 0 /* cause */, null);
148         } else {
149             Rlog.e(TAG, "handleStatusReport() called for object type " + o.getClass().getName());
150         }
151     }
152 
153     /** {@inheritDoc} */
154     @UnsupportedAppUsage
155     @Override
sendSms(SmsTracker tracker)156     protected void sendSms(SmsTracker tracker) {
157         int ss = mPhone.getServiceState().getState();
158 
159         Rlog.d(TAG, "sendSms: "
160                 + " isIms()=" + isIms()
161                 + " mRetryCount=" + tracker.mRetryCount
162                 + " mImsRetry=" + tracker.mImsRetry
163                 + " mMessageRef=" + tracker.mMessageRef
164                 + " mUsesImsServiceForIms=" + tracker.mUsesImsServiceForIms
165                 + " SS=" + ss
166                 + " " + SmsController.formatCrossStackMessageId(tracker.mMessageId));
167 
168         // if sms over IMS is not supported on data and voice is not available...
169         if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) {
170         //In 5G case only Data Rat is reported.
171             if(mPhone.getServiceState().getRilDataRadioTechnology()
172                     != ServiceState.RIL_RADIO_TECHNOLOGY_NR) {
173                 tracker.onFailed(mContext, getNotInServiceError(ss), NO_ERROR_CODE);
174                 notifySmsSentFailedToEmergencyStateTracker(tracker, false);
175                 return;
176             }
177         }
178 
179         Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
180         HashMap<String, Object> map = tracker.getData();
181         byte pdu[] = (byte[]) map.get("pdu");
182         byte smsc[] = (byte[]) map.get("smsc");
183         if (tracker.mRetryCount > 0) {
184             // per TS 23.040 Section 9.2.3.6:  If TP-MTI SMS-SUBMIT (0x01) type
185             //   TP-RD (bit 2) is 1 for retry
186             //   and TP-MR is set to previously failed sms TP-MR
187             if (((0x01 & pdu[0]) == 0x01)) {
188                 pdu[0] |= 0x04; // TP-RD
189                 pdu[1] = (byte) tracker.mMessageRef; // TP-MR
190             }
191         }
192 
193         // sms over gsm is used:
194         //   if sms over IMS is not supported AND
195         //   this is not a retry case after sms over IMS failed
196         //     indicated by mImsRetry > 0 OR
197         //   this tracker uses ImsSmsDispatcher to handle SMS over IMS. This dispatcher has received
198         //     this message because the ImsSmsDispatcher has indicated that the message needs to
199         //     fall back to sending over CS.
200         if (0 == tracker.mImsRetry && !isIms() || tracker.mUsesImsServiceForIms) {
201             if (tracker.mRetryCount == 0 && tracker.mExpectMore) {
202                 mCi.sendSMSExpectMore(IccUtils.bytesToHexString(smsc),
203                         IccUtils.bytesToHexString(pdu), reply);
204             } else {
205                 mCi.sendSMS(IccUtils.bytesToHexString(smsc),
206                         IccUtils.bytesToHexString(pdu), reply);
207             }
208         } else {
209             mCi.sendImsGsmSms(IccUtils.bytesToHexString(smsc),
210                     IccUtils.bytesToHexString(pdu), tracker.mImsRetry,
211                     tracker.mMessageRef, reply);
212             // increment it here, so in case of SMS_FAIL_RETRY over IMS
213             // next retry will be sent using IMS request again.
214             tracker.mImsRetry++;
215         }
216     }
217 
getUiccCardApplication()218     protected UiccCardApplication getUiccCardApplication() {
219             Rlog.d(TAG, "GsmSMSDispatcher: subId = " + mPhone.getSubId()
220                     + " slotId = " + mPhone.getPhoneId());
221                 return mUiccController.getUiccCardApplication(mPhone.getPhoneId(),
222                         UiccController.APP_FAM_3GPP);
223     }
224 
onUpdateIccAvailability()225     private void onUpdateIccAvailability() {
226         if (mUiccController == null ) {
227             return;
228         }
229 
230         UiccCardApplication newUiccApplication = getUiccCardApplication();
231 
232         UiccCardApplication app = mUiccApplication.get();
233         if (app != newUiccApplication) {
234             if (app != null) {
235                 Rlog.d(TAG, "Removing stale icc objects.");
236                 if (mIccRecords.get() != null) {
237                     mIccRecords.get().unregisterForNewSms(this);
238                 }
239                 mIccRecords.set(null);
240                 mUiccApplication.set(null);
241             }
242             if (newUiccApplication != null) {
243                 Rlog.d(TAG, "New Uicc application found");
244                 mUiccApplication.set(newUiccApplication);
245                 mIccRecords.set(newUiccApplication.getIccRecords());
246                 if (mIccRecords.get() != null) {
247                     mIccRecords.get().registerForNewSms(this, EVENT_NEW_ICC_SMS, null);
248                 }
249             }
250         }
251     }
252 }
253