GlobalActions.java revision 7304c343821309dd15f769b18f1de2fa43751573
1/* 2 * Copyright (C) 2008 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.policy.impl; 18 19import com.android.internal.telephony.TelephonyIntents; 20import com.android.internal.telephony.TelephonyProperties; 21import com.android.internal.R; 22 23import android.app.ActivityManagerNative; 24import android.app.AlertDialog; 25import android.content.BroadcastReceiver; 26import android.content.Context; 27import android.content.DialogInterface; 28import android.content.Intent; 29import android.content.IntentFilter; 30import android.content.pm.UserInfo; 31import android.media.AudioManager; 32import android.os.Handler; 33import android.os.IBinder; 34import android.os.Message; 35import android.os.RemoteException; 36import android.os.ServiceManager; 37import android.os.SystemProperties; 38import android.os.Vibrator; 39import android.provider.Settings; 40import android.telephony.PhoneStateListener; 41import android.telephony.ServiceState; 42import android.telephony.TelephonyManager; 43import android.util.Log; 44import android.view.IWindowManager; 45import android.view.LayoutInflater; 46import android.view.View; 47import android.view.ViewGroup; 48import android.view.WindowManager; 49import android.view.WindowManagerPolicy.WindowManagerFuncs; 50import android.widget.AdapterView; 51import android.widget.BaseAdapter; 52import android.widget.ImageView; 53import android.widget.TextView; 54 55import java.util.ArrayList; 56import java.util.List; 57 58/** 59 * Helper to show the global actions dialog. Each item is an {@link Action} that 60 * may show depending on whether the keyguard is showing, and whether the device 61 * is provisioned. 62 */ 63class GlobalActions implements DialogInterface.OnDismissListener, DialogInterface.OnClickListener { 64 65 private static final String TAG = "GlobalActions"; 66 67 private static final boolean SHOW_SILENT_TOGGLE = true; 68 69 private final Context mContext; 70 private final WindowManagerFuncs mWindowManagerFuncs; 71 private final AudioManager mAudioManager; 72 73 private ArrayList<Action> mItems; 74 private AlertDialog mDialog; 75 76 private SilentModeAction mSilentModeAction; 77 private ToggleAction mAirplaneModeOn; 78 79 private MyAdapter mAdapter; 80 81 private boolean mKeyguardShowing = false; 82 private boolean mDeviceProvisioned = false; 83 private ToggleAction.State mAirplaneState = ToggleAction.State.Off; 84 private boolean mIsWaitingForEcmExit = false; 85 86 private IWindowManager mIWindowManager; 87 88 /** 89 * @param context everything needs a context :( 90 */ 91 public GlobalActions(Context context, WindowManagerFuncs windowManagerFuncs) { 92 mContext = context; 93 mWindowManagerFuncs = windowManagerFuncs; 94 mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); 95 96 // receive broadcasts 97 IntentFilter filter = new IntentFilter(); 98 filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); 99 filter.addAction(Intent.ACTION_SCREEN_OFF); 100 filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); 101 context.registerReceiver(mBroadcastReceiver, filter); 102 103 // get notified of phone state changes 104 TelephonyManager telephonyManager = 105 (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 106 telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE); 107 } 108 109 /** 110 * Show the global actions dialog (creating if necessary) 111 * @param keyguardShowing True if keyguard is showing 112 */ 113 public void showDialog(boolean keyguardShowing, boolean isDeviceProvisioned) { 114 mKeyguardShowing = keyguardShowing; 115 mDeviceProvisioned = isDeviceProvisioned; 116 if (mDialog != null) { 117 mDialog.dismiss(); 118 mDialog = null; 119 // Show delayed, so that the dismiss of the previous dialog completes 120 mHandler.sendEmptyMessage(MESSAGE_SHOW); 121 } else { 122 handleShow(); 123 } 124 } 125 126 private void handleShow() { 127 mDialog = createDialog(); 128 prepareDialog(); 129 130 mDialog.show(); 131 mDialog.getWindow().getDecorView().setSystemUiVisibility(View.STATUS_BAR_DISABLE_EXPAND); 132 } 133 /** 134 * Create the global actions dialog. 135 * @return A new dialog. 136 */ 137 private AlertDialog createDialog() { 138 mSilentModeAction = new SilentModeAction(mContext, mAudioManager, mHandler); 139 140 mAirplaneModeOn = new ToggleAction( 141 R.drawable.ic_lock_airplane_mode, 142 R.drawable.ic_lock_airplane_mode_off, 143 R.string.global_actions_toggle_airplane_mode, 144 R.string.global_actions_airplane_mode_on_status, 145 R.string.global_actions_airplane_mode_off_status) { 146 147 void onToggle(boolean on) { 148 if (Boolean.parseBoolean( 149 SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))) { 150 mIsWaitingForEcmExit = true; 151 // Launch ECM exit dialog 152 Intent ecmDialogIntent = 153 new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null); 154 ecmDialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 155 mContext.startActivity(ecmDialogIntent); 156 } else { 157 changeAirplaneModeSystemSetting(on); 158 } 159 } 160 161 @Override 162 protected void changeStateFromPress(boolean buttonOn) { 163 // In ECM mode airplane state cannot be changed 164 if (!(Boolean.parseBoolean( 165 SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE)))) { 166 mState = buttonOn ? State.TurningOn : State.TurningOff; 167 mAirplaneState = mState; 168 } 169 } 170 171 public boolean showDuringKeyguard() { 172 return true; 173 } 174 175 public boolean showBeforeProvisioning() { 176 return false; 177 } 178 }; 179 180 mItems = new ArrayList<Action>(); 181 182 // first: power off 183 mItems.add( 184 new SinglePressAction( 185 com.android.internal.R.drawable.ic_lock_power_off, 186 R.string.global_action_power_off) { 187 188 public void onPress() { 189 // shutdown by making sure radio and power are handled accordingly. 190 mWindowManagerFuncs.shutdown(); 191 } 192 193 public boolean onLongPress() { 194 mWindowManagerFuncs.rebootSafeMode(); 195 return true; 196 } 197 198 public boolean showDuringKeyguard() { 199 return true; 200 } 201 202 public boolean showBeforeProvisioning() { 203 return true; 204 } 205 }); 206 207 // next: airplane mode 208 mItems.add(mAirplaneModeOn); 209 210 // last: silent mode 211 if (SHOW_SILENT_TOGGLE) { 212 mItems.add(mSilentModeAction); 213 } 214 215 List<UserInfo> users = mContext.getPackageManager().getUsers(); 216 if (users.size() > 1) { 217 UserInfo currentUser; 218 try { 219 currentUser = ActivityManagerNative.getDefault().getCurrentUser(); 220 } catch (RemoteException re) { 221 currentUser = null; 222 } 223 for (final UserInfo user : users) { 224 boolean isCurrentUser = currentUser == null 225 ? user.id == 0 : (currentUser.id == user.id); 226 SinglePressAction switchToUser = new SinglePressAction( 227 com.android.internal.R.drawable.ic_menu_cc, 228 (user.name != null ? user.name : "Primary") 229 + (isCurrentUser ? " \u2714" : "")) { 230 public void onPress() { 231 try { 232 ActivityManagerNative.getDefault().switchUser(user.id); 233 getWindowManager().lockNow(); 234 } catch (RemoteException re) { 235 Log.e(TAG, "Couldn't switch user " + re); 236 } 237 } 238 239 public boolean showDuringKeyguard() { 240 return true; 241 } 242 243 public boolean showBeforeProvisioning() { 244 return false; 245 } 246 }; 247 mItems.add(switchToUser); 248 } 249 } 250 mAdapter = new MyAdapter(); 251 252 final AlertDialog.Builder ab = new AlertDialog.Builder(mContext); 253 254 ab.setAdapter(mAdapter, this) 255 .setInverseBackgroundForced(true); 256 257 final AlertDialog dialog = ab.create(); 258 dialog.getListView().setItemsCanFocus(true); 259 dialog.getListView().setLongClickable(true); 260 dialog.getListView().setOnItemLongClickListener( 261 new AdapterView.OnItemLongClickListener() { 262 @Override 263 public boolean onItemLongClick(AdapterView<?> parent, View view, int position, 264 long id) { 265 return mAdapter.getItem(position).onLongPress(); 266 } 267 }); 268 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); 269 270 dialog.setOnDismissListener(this); 271 272 return dialog; 273 } 274 275 private void prepareDialog() { 276 final boolean silentModeOn = 277 mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL; 278 mAirplaneModeOn.updateState(mAirplaneState); 279 mAdapter.notifyDataSetChanged(); 280 if (mKeyguardShowing) { 281 mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); 282 } else { 283 mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); 284 } 285 if (SHOW_SILENT_TOGGLE) { 286 IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION); 287 mContext.registerReceiver(mRingerModeReceiver, filter); 288 } 289 } 290 291 /** {@inheritDoc} */ 292 public void onDismiss(DialogInterface dialog) { 293 if (SHOW_SILENT_TOGGLE) { 294 mContext.unregisterReceiver(mRingerModeReceiver); 295 } 296 } 297 298 /** {@inheritDoc} */ 299 public void onClick(DialogInterface dialog, int which) { 300 if (!(mAdapter.getItem(which) instanceof SilentModeAction)) { 301 dialog.dismiss(); 302 } 303 mAdapter.getItem(which).onPress(); 304 } 305 306 /** 307 * The adapter used for the list within the global actions dialog, taking 308 * into account whether the keyguard is showing via 309 * {@link GlobalActions#mKeyguardShowing} and whether the device is provisioned 310 * via {@link GlobalActions#mDeviceProvisioned}. 311 */ 312 private class MyAdapter extends BaseAdapter { 313 314 public int getCount() { 315 int count = 0; 316 317 for (int i = 0; i < mItems.size(); i++) { 318 final Action action = mItems.get(i); 319 320 if (mKeyguardShowing && !action.showDuringKeyguard()) { 321 continue; 322 } 323 if (!mDeviceProvisioned && !action.showBeforeProvisioning()) { 324 continue; 325 } 326 count++; 327 } 328 return count; 329 } 330 331 @Override 332 public boolean isEnabled(int position) { 333 return getItem(position).isEnabled(); 334 } 335 336 @Override 337 public boolean areAllItemsEnabled() { 338 return false; 339 } 340 341 public Action getItem(int position) { 342 343 int filteredPos = 0; 344 for (int i = 0; i < mItems.size(); i++) { 345 final Action action = mItems.get(i); 346 if (mKeyguardShowing && !action.showDuringKeyguard()) { 347 continue; 348 } 349 if (!mDeviceProvisioned && !action.showBeforeProvisioning()) { 350 continue; 351 } 352 if (filteredPos == position) { 353 return action; 354 } 355 filteredPos++; 356 } 357 358 throw new IllegalArgumentException("position " + position 359 + " out of range of showable actions" 360 + ", filtered count=" + getCount() 361 + ", keyguardshowing=" + mKeyguardShowing 362 + ", provisioned=" + mDeviceProvisioned); 363 } 364 365 366 public long getItemId(int position) { 367 return position; 368 } 369 370 public View getView(int position, View convertView, ViewGroup parent) { 371 Action action = getItem(position); 372 return action.create(mContext, convertView, parent, LayoutInflater.from(mContext)); 373 } 374 } 375 376 // note: the scheme below made more sense when we were planning on having 377 // 8 different things in the global actions dialog. seems overkill with 378 // only 3 items now, but may as well keep this flexible approach so it will 379 // be easy should someone decide at the last minute to include something 380 // else, such as 'enable wifi', or 'enable bluetooth' 381 382 /** 383 * What each item in the global actions dialog must be able to support. 384 */ 385 private interface Action { 386 View create(Context context, View convertView, ViewGroup parent, LayoutInflater inflater); 387 388 void onPress(); 389 390 public boolean onLongPress(); 391 392 /** 393 * @return whether this action should appear in the dialog when the keygaurd 394 * is showing. 395 */ 396 boolean showDuringKeyguard(); 397 398 /** 399 * @return whether this action should appear in the dialog before the 400 * device is provisioned. 401 */ 402 boolean showBeforeProvisioning(); 403 404 boolean isEnabled(); 405 } 406 407 /** 408 * A single press action maintains no state, just responds to a press 409 * and takes an action. 410 */ 411 private static abstract class SinglePressAction implements Action { 412 private final int mIconResId; 413 private final int mMessageResId; 414 private final CharSequence mMessage; 415 416 protected SinglePressAction(int iconResId, int messageResId) { 417 mIconResId = iconResId; 418 mMessageResId = messageResId; 419 mMessage = null; 420 } 421 422 protected SinglePressAction(int iconResId, CharSequence message) { 423 mIconResId = iconResId; 424 mMessageResId = 0; 425 mMessage = message; 426 } 427 public boolean isEnabled() { 428 return true; 429 } 430 431 abstract public void onPress(); 432 433 public boolean onLongPress() { 434 return false; 435 } 436 437 public View create( 438 Context context, View convertView, ViewGroup parent, LayoutInflater inflater) { 439 View v = inflater.inflate(R.layout.global_actions_item, parent, false); 440 441 ImageView icon = (ImageView) v.findViewById(R.id.icon); 442 TextView messageView = (TextView) v.findViewById(R.id.message); 443 444 v.findViewById(R.id.status).setVisibility(View.GONE); 445 446 icon.setImageDrawable(context.getResources().getDrawable(mIconResId)); 447 if (mMessage != null) { 448 messageView.setText(mMessage); 449 } else { 450 messageView.setText(mMessageResId); 451 } 452 453 return v; 454 } 455 } 456 457 /** 458 * A toggle action knows whether it is on or off, and displays an icon 459 * and status message accordingly. 460 */ 461 private static abstract class ToggleAction implements Action { 462 463 enum State { 464 Off(false), 465 TurningOn(true), 466 TurningOff(true), 467 On(false); 468 469 private final boolean inTransition; 470 471 State(boolean intermediate) { 472 inTransition = intermediate; 473 } 474 475 public boolean inTransition() { 476 return inTransition; 477 } 478 } 479 480 protected State mState = State.Off; 481 482 // prefs 483 protected int mEnabledIconResId; 484 protected int mDisabledIconResid; 485 protected int mMessageResId; 486 protected int mEnabledStatusMessageResId; 487 protected int mDisabledStatusMessageResId; 488 489 /** 490 * @param enabledIconResId The icon for when this action is on. 491 * @param disabledIconResid The icon for when this action is off. 492 * @param essage The general information message, e.g 'Silent Mode' 493 * @param enabledStatusMessageResId The on status message, e.g 'sound disabled' 494 * @param disabledStatusMessageResId The off status message, e.g. 'sound enabled' 495 */ 496 public ToggleAction(int enabledIconResId, 497 int disabledIconResid, 498 int essage, 499 int enabledStatusMessageResId, 500 int disabledStatusMessageResId) { 501 mEnabledIconResId = enabledIconResId; 502 mDisabledIconResid = disabledIconResid; 503 mMessageResId = essage; 504 mEnabledStatusMessageResId = enabledStatusMessageResId; 505 mDisabledStatusMessageResId = disabledStatusMessageResId; 506 } 507 508 /** 509 * Override to make changes to resource IDs just before creating the 510 * View. 511 */ 512 void willCreate() { 513 514 } 515 516 public View create(Context context, View convertView, ViewGroup parent, 517 LayoutInflater inflater) { 518 willCreate(); 519 520 View v = inflater.inflate(R 521 .layout.global_actions_item, parent, false); 522 523 ImageView icon = (ImageView) v.findViewById(R.id.icon); 524 TextView messageView = (TextView) v.findViewById(R.id.message); 525 TextView statusView = (TextView) v.findViewById(R.id.status); 526 final boolean enabled = isEnabled(); 527 528 if (messageView != null) { 529 messageView.setText(mMessageResId); 530 messageView.setEnabled(enabled); 531 } 532 533 boolean on = ((mState == State.On) || (mState == State.TurningOn)); 534 if (icon != null) { 535 icon.setImageDrawable(context.getResources().getDrawable( 536 (on ? mEnabledIconResId : mDisabledIconResid))); 537 icon.setEnabled(enabled); 538 } 539 540 if (statusView != null) { 541 statusView.setText(on ? mEnabledStatusMessageResId : mDisabledStatusMessageResId); 542 statusView.setVisibility(View.VISIBLE); 543 statusView.setEnabled(enabled); 544 } 545 v.setEnabled(enabled); 546 547 return v; 548 } 549 550 public final void onPress() { 551 if (mState.inTransition()) { 552 Log.w(TAG, "shouldn't be able to toggle when in transition"); 553 return; 554 } 555 556 final boolean nowOn = !(mState == State.On); 557 onToggle(nowOn); 558 changeStateFromPress(nowOn); 559 } 560 561 public boolean onLongPress() { 562 return false; 563 } 564 565 public boolean isEnabled() { 566 return !mState.inTransition(); 567 } 568 569 /** 570 * Implementations may override this if their state can be in on of the intermediate 571 * states until some notification is received (e.g airplane mode is 'turning off' until 572 * we know the wireless connections are back online 573 * @param buttonOn Whether the button was turned on or off 574 */ 575 protected void changeStateFromPress(boolean buttonOn) { 576 mState = buttonOn ? State.On : State.Off; 577 } 578 579 abstract void onToggle(boolean on); 580 581 public void updateState(State state) { 582 mState = state; 583 } 584 } 585 586 private static class SilentModeAction implements Action, View.OnClickListener { 587 588 private final int[] ITEM_IDS = { R.id.option1, R.id.option2, R.id.option3 }; 589 590 private final AudioManager mAudioManager; 591 private final Handler mHandler; 592 private final boolean mHasVibrator; 593 private final Context mContext; 594 595 SilentModeAction(Context context, AudioManager audioManager, Handler handler) { 596 mAudioManager = audioManager; 597 mHandler = handler; 598 mContext = context; 599 Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE); 600 mHasVibrator = vibrator != null && vibrator.hasVibrator(); 601 } 602 603 private int ringerModeToIndex(int ringerMode) { 604 // They just happen to coincide 605 return ringerMode; 606 } 607 608 private int indexToRingerMode(int index) { 609 // They just happen to coincide 610 return index; 611 } 612 613 public View create(Context context, View convertView, ViewGroup parent, 614 LayoutInflater inflater) { 615 View v = inflater.inflate(R.layout.global_actions_silent_mode, parent, false); 616 617 int selectedIndex = ringerModeToIndex(mAudioManager.getRingerMode()); 618 for (int i = 0; i < 3; i++) { 619 View itemView = v.findViewById(ITEM_IDS[i]); 620 itemView.setSelected(selectedIndex == i); 621 // Set up click handler 622 itemView.setTag(i); 623 itemView.setOnClickListener(this); 624 if (itemView.getId() == R.id.option2 && !mHasVibrator) { 625 itemView.setVisibility(View.GONE); 626 } 627 } 628 return v; 629 } 630 631 public void onPress() { 632 } 633 634 public boolean onLongPress() { 635 return false; 636 } 637 638 public boolean showDuringKeyguard() { 639 return true; 640 } 641 642 public boolean showBeforeProvisioning() { 643 return false; 644 } 645 646 public boolean isEnabled() { 647 return true; 648 } 649 650 void willCreate() { 651 } 652 653 public void onClick(View v) { 654 if (!(v.getTag() instanceof Integer)) return; 655 656 int index = (Integer) v.getTag(); 657 mAudioManager.setRingerMode(indexToRingerMode(index)); 658 mHandler.sendEmptyMessageDelayed(MESSAGE_DISMISS, DIALOG_DISMISS_DELAY); 659 } 660 } 661 662 private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 663 public void onReceive(Context context, Intent intent) { 664 String action = intent.getAction(); 665 if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action) 666 || Intent.ACTION_SCREEN_OFF.equals(action)) { 667 String reason = intent.getStringExtra(PhoneWindowManager.SYSTEM_DIALOG_REASON_KEY); 668 if (!PhoneWindowManager.SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS.equals(reason)) { 669 mHandler.sendEmptyMessage(MESSAGE_DISMISS); 670 } 671 } else if (TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED.equals(action)) { 672 // Airplane mode can be changed after ECM exits if airplane toggle button 673 // is pressed during ECM mode 674 if (!(intent.getBooleanExtra("PHONE_IN_ECM_STATE", false)) && 675 mIsWaitingForEcmExit) { 676 mIsWaitingForEcmExit = false; 677 changeAirplaneModeSystemSetting(true); 678 } 679 } 680 } 681 }; 682 683 PhoneStateListener mPhoneStateListener = new PhoneStateListener() { 684 @Override 685 public void onServiceStateChanged(ServiceState serviceState) { 686 final boolean inAirplaneMode = serviceState.getState() == ServiceState.STATE_POWER_OFF; 687 mAirplaneState = inAirplaneMode ? ToggleAction.State.On : ToggleAction.State.Off; 688 mAirplaneModeOn.updateState(mAirplaneState); 689 mAdapter.notifyDataSetChanged(); 690 } 691 }; 692 693 private BroadcastReceiver mRingerModeReceiver = new BroadcastReceiver() { 694 @Override 695 public void onReceive(Context context, Intent intent) { 696 if (intent.getAction().equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { 697 mHandler.sendEmptyMessage(MESSAGE_REFRESH); 698 } 699 } 700 }; 701 702 private static final int MESSAGE_DISMISS = 0; 703 private static final int MESSAGE_REFRESH = 1; 704 private static final int MESSAGE_SHOW = 2; 705 private static final int DIALOG_DISMISS_DELAY = 300; // ms 706 707 private Handler mHandler = new Handler() { 708 public void handleMessage(Message msg) { 709 switch (msg.what) { 710 case MESSAGE_DISMISS: 711 if (mDialog != null) { 712 mDialog.dismiss(); 713 } 714 break; 715 case MESSAGE_REFRESH: 716 mAdapter.notifyDataSetChanged(); 717 break; 718 case MESSAGE_SHOW: 719 handleShow(); 720 break; 721 } 722 } 723 }; 724 725 /** 726 * Change the airplane mode system setting 727 */ 728 private void changeAirplaneModeSystemSetting(boolean on) { 729 Settings.System.putInt( 730 mContext.getContentResolver(), 731 Settings.System.AIRPLANE_MODE_ON, 732 on ? 1 : 0); 733 Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); 734 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 735 intent.putExtra("state", on); 736 mContext.sendBroadcast(intent); 737 } 738 739 private IWindowManager getWindowManager() { 740 if (mIWindowManager == null) { 741 IBinder b = ServiceManager.getService(Context.WINDOW_SERVICE); 742 mIWindowManager = IWindowManager.Stub.asInterface(b); 743 } 744 return mIWindowManager; 745 } 746} 747