1 /*
2  * Copyright (C) 2008 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.cdma;
18 
19 import static com.android.internal.telephony.SmsResponse.NO_ERROR_CODE;
20 
21 import android.compat.annotation.UnsupportedAppUsage;
22 import android.os.Build;
23 import android.os.Message;
24 import android.telephony.ServiceState;
25 import android.telephony.TelephonyManager;
26 
27 import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
28 import com.android.internal.telephony.GsmCdmaPhone;
29 import com.android.internal.telephony.Phone;
30 import com.android.internal.telephony.PhoneConstants;
31 import com.android.internal.telephony.SMSDispatcher;
32 import com.android.internal.telephony.SmsConstants;
33 import com.android.internal.telephony.SmsController;
34 import com.android.internal.telephony.SmsDispatchersController;
35 import com.android.internal.telephony.SmsHeader;
36 import com.android.internal.telephony.SmsMessageBase;
37 import com.android.internal.telephony.util.SMSDispatcherUtil;
38 import com.android.telephony.Rlog;
39 
40 public class CdmaSMSDispatcher extends SMSDispatcher {
41     private static final String TAG = "CdmaSMSDispatcher";
42     private static final boolean VDBG = false;
43 
CdmaSMSDispatcher(Phone phone, SmsDispatchersController smsDispatchersController)44     public CdmaSMSDispatcher(Phone phone, SmsDispatchersController smsDispatchersController) {
45         super(phone, smsDispatchersController);
46         Rlog.d(TAG, "CdmaSMSDispatcher created");
47     }
48 
49     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
50     @Override
getFormat()51     public String getFormat() {
52         return SmsConstants.FORMAT_3GPP2;
53     }
54 
55     /**
56      * Send the SMS status report to the dispatcher thread to process.
57      * @param sms the CDMA SMS message containing the status report
58      */
sendStatusReportMessage(SmsMessage sms)59     public void sendStatusReportMessage(SmsMessage sms) {
60         if (VDBG) Rlog.d(TAG, "sending EVENT_NEW_SMS_STATUS_REPORT message");
61         sendMessage(obtainMessage(EVENT_NEW_SMS_STATUS_REPORT, sms));
62     }
63 
64     @Override
handleStatusReport(Object o)65     protected void handleStatusReport(Object o) {
66         if (o instanceof SmsMessage) {
67             byte[] pdu = ((SmsMessage) o).getPdu();
68             mSmsDispatchersController.handleSmsStatusReport(SmsConstants.FORMAT_3GPP2, pdu);
69         } else {
70             Rlog.e(TAG, "handleStatusReport() called for object type " + o.getClass().getName());
71         }
72     }
73 
74     @Override
shouldBlockSmsForEcbm()75     protected boolean shouldBlockSmsForEcbm() {
76         // We only block outgoing SMS during ECBM when using CDMA.
77         return mPhone.isInEcm() && isCdmaMo() && !isIms();
78     }
79 
80     @Override
getSubmitPdu(String scAddr, String destAddr, String message, boolean statusReportRequested, SmsHeader smsHeader, int priority, int validityPeriod)81     protected SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
82             String message, boolean statusReportRequested, SmsHeader smsHeader, int priority,
83             int validityPeriod) {
84         return SMSDispatcherUtil.getSubmitPduCdma(scAddr, destAddr, message,
85                 statusReportRequested, smsHeader, priority);
86     }
87 
88     @Override
getSubmitPdu(String scAddr, String destAddr, int destPort, byte[] message, boolean statusReportRequested)89     protected SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
90             int destPort, byte[] message, boolean statusReportRequested) {
91         return SMSDispatcherUtil.getSubmitPduCdma(scAddr, destAddr, destPort, message,
92                 statusReportRequested);
93     }
94 
95     @Override
getSubmitPdu(String scAddr, String destAddr, String message, boolean statusReportRequested, SmsHeader smsHeader, int priority, int validityPeriod, int messageRef)96     protected SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
97             String message, boolean statusReportRequested, SmsHeader smsHeader, int priority,
98             int validityPeriod, int messageRef) {
99         return SMSDispatcherUtil.getSubmitPduCdma(scAddr, destAddr, message,
100                 statusReportRequested, smsHeader, priority);
101     }
102 
103     @Override
getSubmitPdu(String scAddr, String destAddr, int destPort, byte[] message, boolean statusReportRequested, int messageRef)104     protected SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
105             int destPort, byte[] message, boolean statusReportRequested, int messageRef) {
106         return SMSDispatcherUtil.getSubmitPduCdma(scAddr, destAddr, destPort, message,
107                 statusReportRequested);
108     }
109 
110     @Override
calculateLength(CharSequence messageBody, boolean use7bitOnly)111     protected TextEncodingDetails calculateLength(CharSequence messageBody, boolean use7bitOnly) {
112         return SMSDispatcherUtil.calculateLengthCdma(messageBody, use7bitOnly);
113     }
114 
115     /** {@inheritDoc} */
116     @Override
sendSms(SmsTracker tracker)117     public void sendSms(SmsTracker tracker) {
118         int ss = mPhone.getServiceState().getState();
119 
120         Rlog.d(TAG, "sendSms: "
121                 + " isIms()=" + isIms()
122                 + " mRetryCount=" + tracker.mRetryCount
123                 + " mImsRetry=" + tracker.mImsRetry
124                 + " mMessageRef=" + tracker.mMessageRef
125                 + " mUsesImsServiceForIms=" + tracker.mUsesImsServiceForIms
126                 + " SS=" + ss
127                 + " " + SmsController.formatCrossStackMessageId(tracker.mMessageId));
128 
129         // if sms over IMS is not supported on data and voice is not available...
130         if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) {
131             tracker.onFailed(mContext, getNotInServiceError(ss), NO_ERROR_CODE);
132             notifySmsSentFailedToEmergencyStateTracker(tracker, false);
133             return;
134         }
135 
136         Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
137         byte[] pdu = (byte[]) tracker.getData().get("pdu");
138 
139         int currentDataNetwork = mPhone.getServiceState().getDataNetworkType();
140         boolean imsSmsDisabled = (currentDataNetwork == TelephonyManager.NETWORK_TYPE_EHRPD
141                 || (currentDataNetwork == TelephonyManager.NETWORK_TYPE_LTE
142                 || currentDataNetwork == TelephonyManager.NETWORK_TYPE_LTE_CA
143                 || currentDataNetwork == TelephonyManager.NETWORK_TYPE_NR)
144                 && !mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed())
145                 && mPhone.getServiceState().getVoiceNetworkType()
146                         == TelephonyManager.NETWORK_TYPE_1xRTT
147                 && ((GsmCdmaPhone) mPhone).mCT.mState != PhoneConstants.State.IDLE;
148 
149         // sms over cdma is used:
150         //   if sms over IMS is not supported AND
151         //   this is not a retry case after sms over IMS failed
152         //     indicated by mImsRetry > 0 OR
153         //   SMS over IMS is disabled because of the network type OR
154         //   SMS over IMS is being handled by the ImsSmsDispatcher implementation and has indicated
155         //   that the message should fall back to sending over CS.
156         if (0 == tracker.mImsRetry && !isIms() || imsSmsDisabled || tracker.mUsesImsServiceForIms) {
157             if (tracker.mRetryCount == 0 && tracker.mExpectMore) {
158                 mCi.sendCdmaSMSExpectMore(pdu, reply);
159             } else {
160                 mCi.sendCdmaSms(pdu, reply);
161             }
162         } else {
163             mCi.sendImsCdmaSms(pdu, tracker.mImsRetry, tracker.mMessageRef, reply);
164             // increment it here, so in case of SMS_FAIL_RETRY over IMS
165             // next retry will be sent using IMS request again.
166             tracker.mImsRetry++;
167         }
168     }
169 }
170