10d4bcdf379842af4b6304809156971e926f374f0Jake Hamby/*
20d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Copyright (C) 2013 The Android Open Source Project
30d4bcdf379842af4b6304809156971e926f374f0Jake Hamby *
40d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Licensed under the Apache License, Version 2.0 (the "License");
50d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * you may not use this file except in compliance with the License.
60d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * You may obtain a copy of the License at
70d4bcdf379842af4b6304809156971e926f374f0Jake Hamby *
80d4bcdf379842af4b6304809156971e926f374f0Jake Hamby *      http://www.apache.org/licenses/LICENSE-2.0
90d4bcdf379842af4b6304809156971e926f374f0Jake Hamby *
100d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Unless required by applicable law or agreed to in writing, software
110d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * distributed under the License is distributed on an "AS IS" BASIS,
120d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * See the License for the specific language governing permissions and
140d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * limitations under the License.
150d4bcdf379842af4b6304809156971e926f374f0Jake Hamby */
160d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
170d4bcdf379842af4b6304809156971e926f374f0Jake Hambypackage com.android.internal.telephony.gsm;
180d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
190d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.app.Activity;
200d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.content.Context;
210d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.os.Message;
220d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.provider.Telephony.Sms.Intents;
230d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
240d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.CommandsInterface;
250d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.InboundSmsHandler;
261a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yuimport com.android.internal.telephony.Phone;
270d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.SmsConstants;
280aa683b47dfd8590f71d88e0814dade4503f0b5dTa-wei Yenimport com.android.internal.telephony.SmsHeader;
290d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.SmsMessageBase;
300d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.SmsStorageMonitor;
310aa683b47dfd8590f71d88e0814dade4503f0b5dTa-wei Yenimport com.android.internal.telephony.VisualVoicemailSmsFilter;
3226a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowaimport com.android.internal.telephony.uicc.IccRecords;
3326a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowaimport com.android.internal.telephony.uicc.UiccController;
340d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.uicc.UsimServiceTable;
350d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
360d4bcdf379842af4b6304809156971e926f374f0Jake Hamby/**
370d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * This class broadcasts incoming SMS messages to interested apps after storing them in
380d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * the SmsProvider "raw" table and ACKing them to the SMSC. After each message has been
390d4bcdf379842af4b6304809156971e926f374f0Jake Hamby */
400d4bcdf379842af4b6304809156971e926f374f0Jake Hambypublic class GsmInboundSmsHandler extends InboundSmsHandler {
410d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
420d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /** Handler for SMS-PP data download messages to UICC. */
430d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    private final UsimDataDownloadHandler mDataDownloadHandler;
440d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
450d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
460d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Create a new GSM inbound SMS handler.
470d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
480d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    private GsmInboundSmsHandler(Context context, SmsStorageMonitor storageMonitor,
491a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu            Phone phone) {
50d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville        super("GsmInboundSmsHandler", context, storageMonitor, phone,
51d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville                GsmCellBroadcastHandler.makeGsmCellBroadcastHandler(context, phone));
520d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        phone.mCi.setOnNewGsmSms(getHandler(), EVENT_NEW_SMS, null);
530d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        mDataDownloadHandler = new UsimDataDownloadHandler(phone.mCi);
540d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
550d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
560d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
570d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Unregister for GSM SMS.
580d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
590d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    @Override
600d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    protected void onQuitting() {
610d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        mPhone.mCi.unSetOnNewGsmSms(getHandler());
62d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville        mCellBroadcastHandler.dispose();
630d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
640d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        if (DBG) log("unregistered for 3GPP SMS");
650d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        super.onQuitting();     // release wakelock
660d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
670d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
680d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
690d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Wait for state machine to enter startup state. We can't send any messages until then.
700d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
710d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    public static GsmInboundSmsHandler makeInboundSmsHandler(Context context,
721a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu            SmsStorageMonitor storageMonitor, Phone phone) {
730d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        GsmInboundSmsHandler handler = new GsmInboundSmsHandler(context, storageMonitor, phone);
740d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        handler.start();
750d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        return handler;
760d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
770d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
780d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
790d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Return true if this handler is for 3GPP2 messages; false for 3GPP format.
800d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @return false (3GPP)
810d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
820d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    @Override
830d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    protected boolean is3gpp2() {
840d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        return false;
850d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
860d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
870d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
880d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Handle type zero, SMS-PP data download, and 3GPP/CPHS MWI type SMS. Normal SMS messages
890d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * are handled by {@link #dispatchNormalMessage} in parent class.
900d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     *
910d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @param smsb the SmsMessageBase object from the RIL
920d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @return a result code from {@link android.provider.Telephony.Sms.Intents},
930d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     *  or {@link Activity#RESULT_OK} for delayed acknowledgment to SMSC
940d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
950d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    @Override
960d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    protected int dispatchMessageRadioSpecific(SmsMessageBase smsb) {
970d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        SmsMessage sms = (SmsMessage) smsb;
980d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
990d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        if (sms.isTypeZero()) {
1000aa683b47dfd8590f71d88e0814dade4503f0b5dTa-wei Yen            // Some carriers will send visual voicemail SMS as type zero.
1010aa683b47dfd8590f71d88e0814dade4503f0b5dTa-wei Yen            int destPort = -1;
1020aa683b47dfd8590f71d88e0814dade4503f0b5dTa-wei Yen            SmsHeader smsHeader = sms.getUserDataHeader();
1030aa683b47dfd8590f71d88e0814dade4503f0b5dTa-wei Yen            if (smsHeader != null && smsHeader.portAddrs != null) {
1040aa683b47dfd8590f71d88e0814dade4503f0b5dTa-wei Yen                // The message was sent to a port.
1050aa683b47dfd8590f71d88e0814dade4503f0b5dTa-wei Yen                destPort = smsHeader.portAddrs.destPort;
1060aa683b47dfd8590f71d88e0814dade4503f0b5dTa-wei Yen            }
1070aa683b47dfd8590f71d88e0814dade4503f0b5dTa-wei Yen            VisualVoicemailSmsFilter
1080aa683b47dfd8590f71d88e0814dade4503f0b5dTa-wei Yen                    .filter(mContext, new byte[][]{sms.getPdu()}, SmsConstants.FORMAT_3GPP,
1090aa683b47dfd8590f71d88e0814dade4503f0b5dTa-wei Yen                            destPort, mPhone.getSubId());
1100d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            // As per 3GPP TS 23.040 9.2.3.9, Type Zero messages should not be
1110d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            // Displayed/Stored/Notified. They should only be acknowledged.
1120d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            log("Received short message type 0, Don't display or store it. Send Ack");
1130d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return Intents.RESULT_SMS_HANDLED;
1140d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
1150d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1160d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        // Send SMS-PP data download messages to UICC. See 3GPP TS 31.111 section 7.1.1.
1170d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        if (sms.isUsimDataDownload()) {
1180d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            UsimServiceTable ust = mPhone.getUsimServiceTable();
1190d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return mDataDownloadHandler.handleUsimDataDownload(ust, sms);
1200d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
1210d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1220d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        boolean handled = false;
1230d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        if (sms.isMWISetMessage()) {
12426a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa            updateMessageWaitingIndicator(sms.getNumOfVoicemails());
1250d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            handled = sms.isMwiDontStore();
1260d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            if (DBG) log("Received voice mail indicator set SMS shouldStore=" + !handled);
1270d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        } else if (sms.isMWIClearMessage()) {
12826a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa            updateMessageWaitingIndicator(0);
1290d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            handled = sms.isMwiDontStore();
1300d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            if (DBG) log("Received voice mail indicator clear SMS shouldStore=" + !handled);
1310d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
1320d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        if (handled) {
1330d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return Intents.RESULT_SMS_HANDLED;
1340d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
1350d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1360d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        if (!mStorageMonitor.isStorageAvailable() &&
1370d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                sms.getMessageClass() != SmsConstants.MessageClass.CLASS_0) {
1380d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            // It's a storable message and there's no storage available.  Bail.
1390d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            // (See TS 23.038 for a description of class 0 messages.)
1400d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return Intents.RESULT_SMS_OUT_OF_MEMORY;
1410d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
1420d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1430d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        return dispatchNormalMessage(smsb);
1440d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
1450d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
146ecac744a4e585e3c7af95ffa06fa3e711131200cAmit Mahajan    private void updateMessageWaitingIndicator(int voicemailCount) {
14726a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        // range check
14826a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        if (voicemailCount < 0) {
14926a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa            voicemailCount = -1;
15026a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        } else if (voicemailCount > 0xff) {
15126a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa            // TS 23.040 9.2.3.24.2
15226a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa            // "The value 255 shall be taken to mean 255 or greater"
15326a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa            voicemailCount = 0xff;
15426a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        }
1551a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        // update voice mail count in Phone
15626a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        mPhone.setVoiceMessageCount(voicemailCount);
15726a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        // store voice mail count in SIM & shared preferences
15826a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        IccRecords records = UiccController.getInstance().getIccRecords(
15926a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa                mPhone.getPhoneId(), UiccController.APP_FAM_3GPP);
16026a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        if (records != null) {
16126a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa            log("updateMessageWaitingIndicator: updating SIM Records");
16226a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa            records.setVoiceMessageWaiting(1, voicemailCount);
16326a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        } else {
16426a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa            log("updateMessageWaitingIndicator: SIM Records not found");
16526a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa        }
16626a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa    }
16726a4150cfb8cd317eb64994b9d9fd6109bd87ba7Sukanya Rajkhowa
1680d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
1690d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Send an acknowledge message.
1700d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @param success indicates that last message was successfully received.
1710d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @param result result code indicating any error
1720d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @param response callback message sent when operation completes.
1730d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
1740d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    @Override
1750d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    protected void acknowledgeLastIncomingSms(boolean success, int result, Message response) {
1760d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        mPhone.mCi.acknowledgeLastIncomingGsmSms(success, resultToCause(result), response);
1770d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
1780d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1790d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
180d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville     * Called when the phone changes the default method updates mPhone
181d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville     * mStorageMonitor and mCellBroadcastHandler.updatePhoneObject.
182d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville     * Override if different or other behavior is desired.
183d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville     *
184d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville     * @param phone
185d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville     */
186d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville    @Override
1871a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu    protected void onUpdatePhoneObject(Phone phone) {
188d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville        super.onUpdatePhoneObject(phone);
189d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville        log("onUpdatePhoneObject: dispose of old CellBroadcastHandler and make a new one");
190d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville        mCellBroadcastHandler.dispose();
191d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville        mCellBroadcastHandler = GsmCellBroadcastHandler
192d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville                .makeGsmCellBroadcastHandler(mContext, phone);
193d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville    }
194d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville
195d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville    /**
1960d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Convert Android result code to 3GPP SMS failure cause.
1970d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @param rc the Android SMS intent result value
1980d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @return 0 for success, or a 3GPP SMS failure cause value
1990d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
2000d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    private static int resultToCause(int rc) {
2010d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        switch (rc) {
2020d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            case Activity.RESULT_OK:
2030d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            case Intents.RESULT_SMS_HANDLED:
2040d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                // Cause code is ignored on success.
2050d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                return 0;
2060d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            case Intents.RESULT_SMS_OUT_OF_MEMORY:
2070d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                return CommandsInterface.GSM_SMS_FAIL_CAUSE_MEMORY_CAPACITY_EXCEEDED;
2080d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            case Intents.RESULT_SMS_GENERIC_ERROR:
2090d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            default:
2100d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                return CommandsInterface.GSM_SMS_FAIL_CAUSE_UNSPECIFIED_ERROR;
2110d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
2120d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
2130d4bcdf379842af4b6304809156971e926f374f0Jake Hamby}
214