RilMessageDecoder.java revision eca4a2ab310bf8d96cf98b5e880e2f8eef7ffeb6
1/*
2 * Copyright (C) 2007 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
17package com.android.internal.telephony.cat;
18
19import com.android.internal.telephony.uicc.IccFileHandler;
20import com.android.internal.telephony.uicc.IccUtils;
21import com.android.internal.telephony.PhoneConstants;
22
23import android.os.Handler;
24import com.android.internal.util.State;
25import com.android.internal.util.StateMachine;
26import android.os.Message;
27import android.telephony.TelephonyManager;
28
29/**
30 * Class used for queuing raw ril messages, decoding them into CommanParams
31 * objects and sending the result back to the CAT Service.
32 */
33class RilMessageDecoder extends StateMachine {
34
35    // constants
36    private static final int CMD_START = 1;
37    private static final int CMD_PARAMS_READY = 2;
38
39    // members
40    private CommandParamsFactory mCmdParamsFactory = null;
41    private RilMessage mCurrentRilMessage = null;
42    private Handler mCaller = null;
43    private static int mSimCount = 0;
44    private static RilMessageDecoder[] mInstance = null;
45
46    // States
47    private StateStart mStateStart = new StateStart();
48    private StateCmdParamsReady mStateCmdParamsReady = new StateCmdParamsReady();
49
50    /**
51     * Get the singleton instance, constructing if necessary.
52     *
53     * @param caller
54     * @param fh
55     * @return RilMesssageDecoder
56     */
57    public static synchronized RilMessageDecoder getInstance(Handler caller, IccFileHandler fh,
58            int slotId) {
59        if (null == mInstance) {
60            mSimCount = TelephonyManager.getDefault().getSimCount();
61            mInstance = new RilMessageDecoder[mSimCount];
62            for (int i = 0; i < mSimCount; i++) {
63                mInstance[i] = null;
64            }
65        }
66
67        if (slotId < mSimCount) {
68            if (null == mInstance[slotId]) {
69                mInstance[slotId] = new RilMessageDecoder(caller, fh);
70            }
71        } else {
72            CatLog.d("RilMessageDecoder", "invaild slot id: " + slotId);
73            return null;
74        }
75
76        return mInstance[slotId];
77    }
78
79    /**
80     * Start decoding the message parameters,
81     * when complete MSG_ID_RIL_MSG_DECODED will be returned to caller.
82     *
83     * @param rilMsg
84     */
85    public void sendStartDecodingMessageParams(RilMessage rilMsg) {
86        Message msg = obtainMessage(CMD_START);
87        msg.obj = rilMsg;
88        sendMessage(msg);
89    }
90
91    /**
92     * The command parameters have been decoded.
93     *
94     * @param resCode
95     * @param cmdParams
96     */
97    public void sendMsgParamsDecoded(ResultCode resCode, CommandParams cmdParams) {
98        Message msg = obtainMessage(RilMessageDecoder.CMD_PARAMS_READY);
99        msg.arg1 = resCode.value();
100        msg.obj = cmdParams;
101        sendMessage(msg);
102    }
103
104    private void sendCmdForExecution(RilMessage rilMsg) {
105        Message msg = mCaller.obtainMessage(CatService.MSG_ID_RIL_MSG_DECODED,
106                new RilMessage(rilMsg));
107        msg.sendToTarget();
108    }
109
110    private RilMessageDecoder(Handler caller, IccFileHandler fh) {
111        super("RilMessageDecoder");
112
113        addState(mStateStart);
114        addState(mStateCmdParamsReady);
115        setInitialState(mStateStart);
116
117        mCaller = caller;
118        mCmdParamsFactory = CommandParamsFactory.getInstance(this, fh);
119    }
120
121    private RilMessageDecoder() {
122        super("RilMessageDecoder");
123    }
124
125    private class StateStart extends State {
126        @Override
127        public boolean processMessage(Message msg) {
128            if (msg.what == CMD_START) {
129                if (decodeMessageParams((RilMessage)msg.obj)) {
130                    transitionTo(mStateCmdParamsReady);
131                }
132            } else {
133                CatLog.d(this, "StateStart unexpected expecting START=" +
134                         CMD_START + " got " + msg.what);
135            }
136            return true;
137        }
138    }
139
140    private class StateCmdParamsReady extends State {
141        @Override
142        public boolean processMessage(Message msg) {
143            if (msg.what == CMD_PARAMS_READY) {
144                mCurrentRilMessage.mResCode = ResultCode.fromInt(msg.arg1);
145                mCurrentRilMessage.mData = msg.obj;
146                sendCmdForExecution(mCurrentRilMessage);
147                transitionTo(mStateStart);
148            } else {
149                CatLog.d(this, "StateCmdParamsReady expecting CMD_PARAMS_READY="
150                         + CMD_PARAMS_READY + " got " + msg.what);
151                deferMessage(msg);
152            }
153            return true;
154        }
155    }
156
157    private boolean decodeMessageParams(RilMessage rilMsg) {
158        boolean decodingStarted;
159
160        mCurrentRilMessage = rilMsg;
161        switch(rilMsg.mId) {
162        case CatService.MSG_ID_SESSION_END:
163        case CatService.MSG_ID_CALL_SETUP:
164            mCurrentRilMessage.mResCode = ResultCode.OK;
165            sendCmdForExecution(mCurrentRilMessage);
166            decodingStarted = false;
167            break;
168        case CatService.MSG_ID_PROACTIVE_COMMAND:
169        case CatService.MSG_ID_EVENT_NOTIFY:
170        case CatService.MSG_ID_REFRESH:
171            byte[] rawData = null;
172            try {
173                rawData = IccUtils.hexStringToBytes((String) rilMsg.mData);
174            } catch (Exception e) {
175                // zombie messages are dropped
176                CatLog.d(this, "decodeMessageParams dropping zombie messages");
177                decodingStarted = false;
178                break;
179            }
180            try {
181                // Start asynch parsing of the command parameters.
182                mCmdParamsFactory.make(BerTlv.decode(rawData));
183                decodingStarted = true;
184            } catch (ResultException e) {
185                // send to Service for proper RIL communication.
186                CatLog.d(this, "decodeMessageParams: caught ResultException e=" + e);
187                mCurrentRilMessage.mResCode = e.result();
188                sendCmdForExecution(mCurrentRilMessage);
189                decodingStarted = false;
190            }
191            break;
192        default:
193            decodingStarted = false;
194            break;
195        }
196        return decodingStarted;
197    }
198
199    public void dispose() {
200        mStateStart = null;
201        mStateCmdParamsReady = null;
202        mCmdParamsFactory.dispose();
203        mCmdParamsFactory = null;
204        mCurrentRilMessage = null;
205        mCaller = null;
206        mInstance = null;
207    }
208}
209