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