1c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/*
2c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Copyright (C) 2006-2007 Google Inc.
3c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
4c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * use this file except in compliance with the License. You may obtain a copy of
6c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * the License at
7c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
8c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * http://www.apache.org/licenses/LICENSE-2.0
9c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
10c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Unless required by applicable law or agreed to in writing, software
11c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * License for the specific language governing permissions and limitations under
14c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * the License.
15c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */
16c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
17c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savillepackage com.android.internal.telephony.cat;
18c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
19c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.EncodeException;
20c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.GsmAlphabet;
21c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport java.util.Calendar;
22c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport java.util.TimeZone;
23c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.SystemProperties;
24c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.text.TextUtils;
25c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
26c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.cat.AppInterface.CommandType;
27c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
28c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport java.io.ByteArrayOutputStream;
29c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport java.io.UnsupportedEncodingException;
30c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
31c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleabstract class ResponseData {
32c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
33c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Format the data appropriate for TERMINAL RESPONSE and write it into
34c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * the ByteArrayOutputStream object.
35c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
36c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public abstract void format(ByteArrayOutputStream buf);
37c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
38c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public static void writeLength(ByteArrayOutputStream buf, int length) {
39c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // As per ETSI 102.220 Sec7.1.2, if the total length is greater
40c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // than 0x7F, it should be coded in two bytes and the first byte
41c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // should be 0x81.
42c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (length > 0x7F) {
43c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            buf.write(0x81);
44c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
45c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        buf.write(length);
46c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
47c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville}
48c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
49c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleclass SelectItemResponseData extends ResponseData {
50c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // members
51c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private int id;
52c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
53c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public SelectItemResponseData(int id) {
54c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        super();
55c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        this.id = id;
56c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
57c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
58c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
59c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void format(ByteArrayOutputStream buf) {
60c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Item identifier object
61c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        int tag = 0x80 | ComprehensionTlvTag.ITEM_ID.value();
62c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        buf.write(tag); // tag
63c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        buf.write(1); // length
64c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        buf.write(id); // identifier of item chosen
65c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
66c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville}
67c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
68c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleclass GetInkeyInputResponseData extends ResponseData {
69c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // members
70c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private boolean mIsUcs2;
71c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private boolean mIsPacked;
72c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private boolean mIsYesNo;
73c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private boolean mYesNoResponse;
74c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public String mInData;
75c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
76c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // GetInKey Yes/No response characters constants.
77c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected static final byte GET_INKEY_YES = 0x01;
78c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    protected static final byte GET_INKEY_NO = 0x00;
79c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
80c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public GetInkeyInputResponseData(String inData, boolean ucs2, boolean packed) {
81c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        super();
82c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        this.mIsUcs2 = ucs2;
83c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        this.mIsPacked = packed;
84c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        this.mInData = inData;
85c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        this.mIsYesNo = false;
86c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
87c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
88c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public GetInkeyInputResponseData(boolean yesNoResponse) {
89c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        super();
90c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        this.mIsUcs2 = false;
91c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        this.mIsPacked = false;
92c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        this.mInData = "";
93c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        this.mIsYesNo = true;
94c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        this.mYesNoResponse = yesNoResponse;
95c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
96c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
97c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
98c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void format(ByteArrayOutputStream buf) {
99c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (buf == null) {
100c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return;
101c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
102c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
103c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Text string object
104c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        int tag = 0x80 | ComprehensionTlvTag.TEXT_STRING.value();
105c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        buf.write(tag); // tag
106c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
107c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        byte[] data;
108c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
109c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (mIsYesNo) {
110c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            data = new byte[1];
111c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            data[0] = mYesNoResponse ? GET_INKEY_YES : GET_INKEY_NO;
112c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (mInData != null && mInData.length() > 0) {
113c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            try {
1149f1860d5596f79d74fa4ecf78c0dd1d8253fc5f9Pierre Fröjd                // ETSI TS 102 223 8.15, should use the same format as in SMS messages
1159f1860d5596f79d74fa4ecf78c0dd1d8253fc5f9Pierre Fröjd                // on the network.
116c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (mIsUcs2) {
1179f1860d5596f79d74fa4ecf78c0dd1d8253fc5f9Pierre Fröjd                    // ucs2 is by definition big endian.
1189f1860d5596f79d74fa4ecf78c0dd1d8253fc5f9Pierre Fröjd                    data = mInData.getBytes("UTF-16BE");
119c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else if (mIsPacked) {
120c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    int size = mInData.length();
121c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
122c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    byte[] tempData = GsmAlphabet
123c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            .stringToGsm7BitPacked(mInData, 0, 0);
124c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    data = new byte[size];
125c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // Since stringToGsm7BitPacked() set byte 0 in the
126c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // returned byte array to the count of septets used...
127c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    // copy to a new array without byte 0.
128c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    System.arraycopy(tempData, 1, data, 0, size);
129c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                } else {
130c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    data = GsmAlphabet.stringToGsm8BitPacked(mInData);
131c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
132c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } catch (UnsupportedEncodingException e) {
133c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                data = new byte[0];
134c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } catch (EncodeException e) {
135c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                data = new byte[0];
136c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
137c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
138c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            data = new byte[0];
139c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
140c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
141c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // length - one more for data coding scheme.
142c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        writeLength(buf, data.length + 1);
143c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
144c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // data coding scheme
145c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (mIsUcs2) {
146c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            buf.write(0x08); // UCS2
147c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else if (mIsPacked) {
148c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            buf.write(0x00); // 7 bit packed
149c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
150c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            buf.write(0x04); // 8 bit unpacked
151c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
152c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
153c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        for (byte b : data) {
154c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            buf.write(b);
155c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
156c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
157c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville}
158c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
159c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville// For "PROVIDE LOCAL INFORMATION" command.
160c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville// See TS 31.111 section 6.4.15/ETSI TS 102 223
161c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville// TS 31.124 section 27.22.4.15 for test spec
162c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleclass LanguageResponseData extends ResponseData {
163c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private String lang;
164c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
165c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public LanguageResponseData(String lang) {
166c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        super();
167c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        this.lang = lang;
168c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
169c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
170c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
171c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void format(ByteArrayOutputStream buf) {
172c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (buf == null) {
173c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return;
174c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
175c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
176c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Text string object
177c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        int tag = 0x80 | ComprehensionTlvTag.LANGUAGE.value();
178c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        buf.write(tag); // tag
179c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
180c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        byte[] data;
181c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
182c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (lang != null && lang.length() > 0) {
183c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            data = GsmAlphabet.stringToGsm8BitPacked(lang);
184c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
185c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        else {
186c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            data = new byte[0];
187c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
188c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
189c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        buf.write(data.length);
190c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
191c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        for (byte b : data) {
192c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            buf.write(b);
193c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
194c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
195c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville}
196c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
197c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville// For "PROVIDE LOCAL INFORMATION" command.
198c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville// See TS 31.111 section 6.4.15/ETSI TS 102 223
199c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville// TS 31.124 section 27.22.4.15 for test spec
200c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleclass DTTZResponseData extends ResponseData {
201c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private Calendar calendar;
202c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
203c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public DTTZResponseData(Calendar cal) {
204c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        super();
205c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        calendar = cal;
206c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
207c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
208c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    @Override
209c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void format(ByteArrayOutputStream buf) {
210c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (buf == null) {
211c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return;
212c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
213c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
214c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // DTTZ object
215c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        int tag = 0x80 | CommandType.PROVIDE_LOCAL_INFORMATION.value();
216c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        buf.write(tag); // tag
217c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
218c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        byte[] data = new byte[8];
219c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
220c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        data[0] = 0x07; // Write length of DTTZ data
221c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
222c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (calendar == null) {
223c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            calendar = Calendar.getInstance();
224c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
225c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Fill year byte
226c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        data[1] = byteToBCD(calendar.get(java.util.Calendar.YEAR) % 100);
227c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
228c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Fill month byte
229c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        data[2] = byteToBCD(calendar.get(java.util.Calendar.MONTH) + 1);
230c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
231c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Fill day byte
232c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        data[3] = byteToBCD(calendar.get(java.util.Calendar.DATE));
233c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
234c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Fill hour byte
235c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        data[4] = byteToBCD(calendar.get(java.util.Calendar.HOUR_OF_DAY));
236c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
237c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Fill minute byte
238c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        data[5] = byteToBCD(calendar.get(java.util.Calendar.MINUTE));
239c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
240c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        // Fill second byte
241c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        data[6] = byteToBCD(calendar.get(java.util.Calendar.SECOND));
242c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
243c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        String tz = SystemProperties.get("persist.sys.timezone", "");
244c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (TextUtils.isEmpty(tz)) {
245c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            data[7] = (byte) 0xFF;    // set FF in terminal response
246c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
247c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            TimeZone zone = TimeZone.getTimeZone(tz);
248c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            int zoneOffset = zone.getRawOffset() + zone.getDSTSavings();
249c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            data[7] = getTZOffSetByte(zoneOffset);
250c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
251c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
252c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        for (byte b : data) {
253c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            buf.write(b);
254c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
255c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
256c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
257c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private byte byteToBCD(int value) {
258c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (value < 0 && value > 99) {
259c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            CatLog.d(this, "Err: byteToBCD conversion Value is " + value +
260c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                           " Value has to be between 0 and 99");
261c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            return 0;
262c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
263c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
264c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return (byte) ((value / 10) | ((value % 10) << 4));
265c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
266c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
267c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private byte getTZOffSetByte(long offSetVal) {
268c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        boolean isNegative = (offSetVal < 0);
269c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
270c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        /*
271c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         * The 'offSetVal' is in milliseconds. Convert it to hours and compute
272c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         * offset While sending T.R to UICC, offset is expressed is 'quarters of
273c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         * hours'
274c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         */
275c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
276c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         long tzOffset = offSetVal / (15 * 60 * 1000);
277c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         tzOffset = (isNegative ? -1 : 1) * tzOffset;
278c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         byte bcdVal = byteToBCD((int) tzOffset);
279c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         // For negative offsets, put '1' in the msb
280c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville         return isNegative ?  (bcdVal |= 0x08) : bcdVal;
281c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
282c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
283c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville}
284c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
285