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