InCallActivity.java revision 7ac6cb331919db2a3a8985e4cb3299b309d9012a
1/* 2 * Copyright (C) 2006 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.incallui; 18 19import android.app.Activity; 20import android.app.Fragment; 21import android.content.Intent; 22import android.os.Bundle; 23import android.util.Log; 24import android.view.KeyEvent; 25import android.view.View; 26import android.view.Window; 27import android.view.WindowManager; 28import android.widget.Toast; 29 30/** 31 * Phone app "in call" screen. 32 */ 33public class InCallActivity extends Activity { 34 private static final String TAG = InCallActivity.class.getSimpleName(); 35 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 36 private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE); 37 38 private CallButtonFragment mCallButtonFragment; 39 private CallCardFragment mCallCardFragment; 40 private AnswerFragment mAnswerFragment; 41 42 @Override 43 protected void onCreate(Bundle icicle) { 44 logD("onCreate()... this = " + this); 45 46 super.onCreate(icicle); 47 48 // set this flag so this activity will stay in front of the keyguard 49 // Have the WindowManager filter out touch events that are "too fat". 50 getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED 51 | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON 52 | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD 53 | WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES); 54 55 requestWindowFeature(Window.FEATURE_NO_TITLE); 56 57 // Inflate everything in incall_screen.xml and add it to the screen. 58 setContentView(R.layout.incall_screen); 59 60 initializeInCall(); 61 62 logD("onCreate(): exit"); 63 } 64 65 @Override 66 protected void onResume() { 67 logD("onResume()..."); 68 super.onResume(); 69 } 70 71 // onPause is guaranteed to be called when the InCallActivity goes 72 // in the background. 73 @Override 74 protected void onPause() { 75 logD("onPause()..."); 76 super.onPause(); 77 } 78 79 @Override 80 protected void onStop() { 81 logD("onStop()..."); 82 super.onStop(); 83 } 84 85 @Override 86 protected void onDestroy() { 87 logD("onDestroy()... this = " + this); 88 super.onDestroy(); 89 } 90 91 /** 92 * Dismisses the in-call screen. 93 * 94 * We never *really* finish() the InCallActivity, since we don't want to get destroyed and then 95 * have to be re-created from scratch for the next call. Instead, we just move ourselves to the 96 * back of the activity stack. 97 * 98 * This also means that we'll no longer be reachable via the BACK button (since moveTaskToBack() 99 * puts us behind the Home app, but the home app doesn't allow the BACK key to move you any 100 * farther down in the history stack.) 101 * 102 * (Since the Phone app itself is never killed, this basically means that we'll keep a single 103 * InCallActivity instance around for the entire uptime of the device. This noticeably improves 104 * the UI responsiveness for incoming calls.) 105 */ 106 @Override 107 public void finish() { 108 logD("finish()..."); 109 super.finish(); 110 111 // TODO(klp): Actually finish the activity for now. Revisit performance implications of 112 // this before launch. 113 // moveTaskToBack(true); 114 } 115 116 @Override 117 protected void onNewIntent(Intent intent) { 118 logD("onNewIntent: intent = " + intent); 119 120 // We're being re-launched with a new Intent. Since it's possible for a 121 // single InCallActivity instance to persist indefinitely (even if we 122 // finish() ourselves), this sequence can potentially happen any time 123 // the InCallActivity needs to be displayed. 124 125 // Stash away the new intent so that we can get it in the future 126 // by calling getIntent(). (Otherwise getIntent() will return the 127 // original Intent from when we first got created!) 128 setIntent(intent); 129 130 // Activities are always paused before receiving a new intent, so 131 // we can count on our onResume() method being called next. 132 133 // Just like in onCreate(), handle the intent. 134 //TODO(klp): handle intent 135 } 136 137 @Override 138 public void onBackPressed() { 139 // TODO(klp): implement 140 141 // Nothing special to do. Fall back to the default behavior. 142 super.onBackPressed(); 143 } 144 145 @Override 146 public boolean onKeyDown(int keyCode, KeyEvent event) { 147 switch (keyCode) { 148 case KeyEvent.KEYCODE_CALL: 149 // TODO(klp): handle call key 150 // Always consume CALL to be sure the PhoneWindow won't do anything with it 151 return true; 152 153 // Note there's no KeyEvent.KEYCODE_ENDCALL case here. 154 // The standard system-wide handling of the ENDCALL key 155 // (see PhoneWindowManager's handling of KEYCODE_ENDCALL) 156 // already implements exactly what the UI spec wants, 157 // namely (1) "hang up" if there's a current active call, 158 // or (2) "don't answer" if there's a current ringing call. 159 160 case KeyEvent.KEYCODE_CAMERA: 161 // Disable the CAMERA button while in-call since it's too 162 // easy to press accidentally. 163 return true; 164 165 case KeyEvent.KEYCODE_VOLUME_UP: 166 case KeyEvent.KEYCODE_VOLUME_DOWN: 167 case KeyEvent.KEYCODE_VOLUME_MUTE: 168 // Not sure if needed. If so, silence ringer. 169 break; 170 171 case KeyEvent.KEYCODE_MUTE: 172 toast("mute"); 173 return true; 174 175 // Various testing/debugging features, enabled ONLY when VERBOSE == true. 176 case KeyEvent.KEYCODE_SLASH: 177 if (VERBOSE) { 178 Log.v(TAG, "----------- InCallActivity View dump --------------"); 179 // Dump starting from the top-level view of the entire activity: 180 Window w = this.getWindow(); 181 View decorView = w.getDecorView(); 182 decorView.debug(); 183 return true; 184 } 185 break; 186 case KeyEvent.KEYCODE_EQUALS: 187 // TODO(klp): Dump phone state? 188 break; 189 } 190 191 // TODO(klp): handle dialer key down 192 193 return super.onKeyDown(keyCode, event); 194 } 195 196 private void initializeInCall() { 197 // TODO(klp): Make sure that this doesn't need to move back to onResume() since they are 198 // statically added fragments. 199 if (mCallButtonFragment == null) { 200 mCallButtonFragment = (CallButtonFragment) getFragmentManager() 201 .findFragmentById(R.id.callButtonFragment); 202 } 203 204 if (mCallCardFragment == null) { 205 mCallCardFragment = (CallCardFragment) getFragmentManager() 206 .findFragmentById(R.id.callCardFragment); 207 } 208 209 if (mAnswerFragment == null) { 210 mAnswerFragment = (AnswerFragment) getFragmentManager() 211 .findFragmentById(R.id.answerFragment); 212 } 213 214 setUpPresenters(); 215 } 216 217 private void setUpPresenters() { 218 InCallPresenter mainPresenter = InCallPresenter.getInstance(); 219 220 mainPresenter.addListener(mCallButtonFragment.getPresenter()); 221 mainPresenter.addListener(mCallCardFragment.getPresenter()); 222 mainPresenter.addListener(mAnswerFragment.getPresenter()); 223 224 // setting activity should be last thing in setup process 225 mainPresenter.setActivity(this); 226 } 227 228 private void toast(String text) { 229 final Toast toast = Toast.makeText(this, text, Toast.LENGTH_SHORT); 230 231 toast.show(); 232 } 233 234 private void logD(String msg) { 235 if (DEBUG) { 236 Log.d(TAG, msg); 237 } 238 } 239} 240