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.stk;
18
19import android.app.ListActivity;
20import android.content.Context;
21import android.content.Intent;
22import android.os.Bundle;
23import android.os.Handler;
24import android.os.Message;
25import android.view.KeyEvent;
26import android.view.MenuItem;
27import android.view.View;
28import android.view.Window;
29import android.widget.ImageView;
30import android.widget.ListView;
31import android.widget.ProgressBar;
32import android.widget.TextView;
33
34import com.android.internal.telephony.cat.Item;
35import com.android.internal.telephony.cat.Menu;
36import com.android.internal.telephony.cat.CatLog;
37
38/**
39 * ListActivity used for displaying STK menus. These can be SET UP MENU and
40 * SELECT ITEM menus. This activity is started multiple times with different
41 * menu content.
42 *
43 */
44public class StkMenuActivity extends ListActivity {
45    private Context mContext;
46    private Menu mStkMenu = null;
47    private int mState = STATE_MAIN;
48    private boolean mAcceptUsersInput = true;
49
50    private TextView mTitleTextView = null;
51    private ImageView mTitleIconView = null;
52    private ProgressBar mProgressView = null;
53
54    StkAppService appService = StkAppService.getInstance();
55
56    // Internal state values
57    static final int STATE_MAIN = 1;
58    static final int STATE_SECONDARY = 2;
59
60    // message id for time out
61    private static final int MSG_ID_TIMEOUT = 1;
62
63    Handler mTimeoutHandler = new Handler() {
64        @Override
65        public void handleMessage(Message msg) {
66            switch(msg.what) {
67            case MSG_ID_TIMEOUT:
68                mAcceptUsersInput = false;
69                sendResponse(StkAppService.RES_ID_TIMEOUT);
70                break;
71            }
72        }
73    };
74
75    @Override
76    public void onCreate(Bundle icicle) {
77        super.onCreate(icicle);
78
79        CatLog.d(this, "onCreate");
80        // Remove the default title, customized one is used.
81        requestWindowFeature(Window.FEATURE_NO_TITLE);
82        // Set the layout for this activity.
83        setContentView(R.layout.stk_menu_list);
84
85        mTitleTextView = (TextView) findViewById(R.id.title_text);
86        mTitleIconView = (ImageView) findViewById(R.id.title_icon);
87        mProgressView = (ProgressBar) findViewById(R.id.progress_bar);
88        mContext = getBaseContext();
89
90        initFromIntent(getIntent());
91        mAcceptUsersInput = true;
92    }
93
94    @Override
95    protected void onNewIntent(Intent intent) {
96        super.onNewIntent(intent);
97
98        CatLog.d(this, "onNewIntent");
99        initFromIntent(intent);
100        mAcceptUsersInput = true;
101    }
102
103    @Override
104    protected void onListItemClick(ListView l, View v, int position, long id) {
105        super.onListItemClick(l, v, position, id);
106
107        if (!mAcceptUsersInput) {
108            return;
109        }
110
111        Item item = getSelectedItem(position);
112        if (item == null) {
113            return;
114        }
115        sendResponse(StkAppService.RES_ID_MENU_SELECTION, item.id, false);
116        mAcceptUsersInput = false;
117        mProgressView.setVisibility(View.VISIBLE);
118        mProgressView.setIndeterminate(true);
119    }
120
121    @Override
122    public boolean onKeyDown(int keyCode, KeyEvent event) {
123
124        if (!mAcceptUsersInput) {
125            return true;
126        }
127
128        switch (keyCode) {
129        case KeyEvent.KEYCODE_BACK:
130            switch (mState) {
131            case STATE_SECONDARY:
132                cancelTimeOut();
133                mAcceptUsersInput = false;
134                sendResponse(StkAppService.RES_ID_BACKWARD);
135                return true;
136            case STATE_MAIN:
137                break;
138            }
139            break;
140        }
141        return super.onKeyDown(keyCode, event);
142    }
143
144    @Override
145    public void onResume() {
146        super.onResume();
147
148        appService.indicateMenuVisibility(true);
149        mStkMenu = appService.getMenu();
150        if (mStkMenu == null) {
151            finish();
152            return;
153        }
154        displayMenu();
155        startTimeOut();
156        // whenever this activity is resumed after a sub activity was invoked
157        // (Browser, In call screen) switch back to main state and enable
158        // user's input;
159        if (!mAcceptUsersInput) {
160            mState = STATE_MAIN;
161            mAcceptUsersInput = true;
162        }
163        // make sure the progress bar is not shown.
164        mProgressView.setIndeterminate(false);
165        mProgressView.setVisibility(View.GONE);
166    }
167
168    @Override
169    public void onPause() {
170        super.onPause();
171
172        appService.indicateMenuVisibility(false);
173        cancelTimeOut();
174    }
175
176    @Override
177    public void onDestroy() {
178        super.onDestroy();
179
180        CatLog.d(this, "onDestroy");
181    }
182
183    @Override
184    public boolean onCreateOptionsMenu(android.view.Menu menu) {
185        super.onCreateOptionsMenu(menu);
186        menu.add(0, StkApp.MENU_ID_END_SESSION, 1, R.string.menu_end_session);
187        menu.add(0, StkApp.MENU_ID_HELP, 2, R.string.help);
188        return true;
189    }
190
191    @Override
192    public boolean onPrepareOptionsMenu(android.view.Menu menu) {
193        super.onPrepareOptionsMenu(menu);
194        boolean helpVisible = false;
195        boolean mainVisible = false;
196
197        if (mState == STATE_SECONDARY) {
198            mainVisible = true;
199        }
200        if (mStkMenu != null) {
201            helpVisible = mStkMenu.helpAvailable;
202        }
203
204        menu.findItem(StkApp.MENU_ID_END_SESSION).setVisible(mainVisible);
205        menu.findItem(StkApp.MENU_ID_HELP).setVisible(helpVisible);
206
207        return true;
208    }
209
210    @Override
211    public boolean onOptionsItemSelected(MenuItem item) {
212        if (!mAcceptUsersInput) {
213            return true;
214        }
215        switch (item.getItemId()) {
216        case StkApp.MENU_ID_END_SESSION:
217            cancelTimeOut();
218            mAcceptUsersInput = false;
219            // send session end response.
220            sendResponse(StkAppService.RES_ID_END_SESSION);
221            return true;
222        case StkApp.MENU_ID_HELP:
223            cancelTimeOut();
224            mAcceptUsersInput = false;
225            int position = getSelectedItemPosition();
226            Item stkItem = getSelectedItem(position);
227            if (stkItem == null) {
228                break;
229            }
230            // send help needed response.
231            sendResponse(StkAppService.RES_ID_MENU_SELECTION, stkItem.id, true);
232            return true;
233        }
234        return super.onOptionsItemSelected(item);
235    }
236
237    @Override
238    protected void onSaveInstanceState(Bundle outState) {
239        outState.putInt("STATE", mState);
240        outState.putParcelable("MENU", mStkMenu);
241    }
242
243    @Override
244    protected void onRestoreInstanceState(Bundle savedInstanceState) {
245        mState = savedInstanceState.getInt("STATE");
246        mStkMenu = savedInstanceState.getParcelable("MENU");
247    }
248
249    private void cancelTimeOut() {
250        mTimeoutHandler.removeMessages(MSG_ID_TIMEOUT);
251    }
252
253    private void startTimeOut() {
254        if (mState == STATE_SECONDARY) {
255            // Reset timeout.
256            cancelTimeOut();
257            mTimeoutHandler.sendMessageDelayed(mTimeoutHandler
258                    .obtainMessage(MSG_ID_TIMEOUT), StkApp.UI_TIMEOUT);
259        }
260    }
261
262    // Bind list adapter to the items list.
263    private void displayMenu() {
264
265        if (mStkMenu != null) {
266            // Display title & title icon
267            if (mStkMenu.titleIcon != null) {
268                mTitleIconView.setImageBitmap(mStkMenu.titleIcon);
269                mTitleIconView.setVisibility(View.VISIBLE);
270            } else {
271                mTitleIconView.setVisibility(View.GONE);
272            }
273            if (!mStkMenu.titleIconSelfExplanatory) {
274                mTitleTextView.setVisibility(View.VISIBLE);
275                if (mStkMenu.title == null) {
276                    mTitleTextView.setText(R.string.app_name);
277                } else {
278                    mTitleTextView.setText(mStkMenu.title);
279                }
280            } else {
281                mTitleTextView.setVisibility(View.INVISIBLE);
282            }
283            // create an array adapter for the menu list
284            StkMenuAdapter adapter = new StkMenuAdapter(this,
285                    mStkMenu.items, mStkMenu.itemsIconSelfExplanatory);
286            // Bind menu list to the new adapter.
287            setListAdapter(adapter);
288            // Set default item
289            setSelection(mStkMenu.defaultItem);
290        }
291    }
292
293    private void initFromIntent(Intent intent) {
294
295        if (intent != null) {
296            mState = intent.getIntExtra("STATE", STATE_MAIN);
297        } else {
298            finish();
299        }
300    }
301
302    private Item getSelectedItem(int position) {
303        Item item = null;
304        if (mStkMenu != null) {
305            try {
306                item = mStkMenu.items.get(position);
307            } catch (IndexOutOfBoundsException e) {
308                if (StkApp.DBG) {
309                    CatLog.d(this, "Invalid menu");
310                }
311            } catch (NullPointerException e) {
312                if (StkApp.DBG) {
313                    CatLog.d(this, "Invalid menu");
314                }
315            }
316        }
317        return item;
318    }
319
320    private void sendResponse(int resId) {
321        sendResponse(resId, 0, false);
322    }
323
324    private void sendResponse(int resId, int itemId, boolean help) {
325        Bundle args = new Bundle();
326        args.putInt(StkAppService.OPCODE, StkAppService.OP_RESPONSE);
327        args.putInt(StkAppService.RES_ID, resId);
328        args.putInt(StkAppService.MENU_SELECTION, itemId);
329        args.putBoolean(StkAppService.HELP, help);
330        mContext.startService(new Intent(mContext, StkAppService.class)
331                .putExtras(args));
332    }
333}
334