1/* 2 * Copyright (C) 2015 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; 18 19import android.test.ActivityInstrumentationTestCase2; 20import android.test.UiThreadTest; 21import android.view.ActionMode; 22import android.view.ActionMode.Callback; 23import android.view.KeyEvent; 24import android.view.Menu; 25import android.view.MenuInflater; 26import android.view.MenuItem; 27import android.view.MotionEvent; 28import android.view.SearchEvent; 29import android.view.View; 30import android.view.Window; 31import android.view.WindowManager.LayoutParams; 32import android.view.accessibility.AccessibilityEvent; 33 34/** 35 * Tests {@link PhoneWindow}'s {@link ActionMode} related methods. 36 */ 37public final class PhoneWindowActionModeTest 38 extends ActivityInstrumentationTestCase2<PhoneWindowActionModeTestActivity> { 39 40 private PhoneWindow mPhoneWindow; 41 private MockWindowCallback mWindowCallback; 42 private MockActionModeCallback mActionModeCallback; 43 44 public PhoneWindowActionModeTest() { 45 super(PhoneWindowActionModeTestActivity.class); 46 } 47 48 @Override 49 protected void setUp() throws Exception { 50 super.setUp(); 51 mPhoneWindow = (PhoneWindow) getActivity().getWindow(); 52 mWindowCallback = new MockWindowCallback(); 53 mPhoneWindow.setCallback(mWindowCallback); 54 mActionModeCallback = new MockActionModeCallback(); 55 } 56 57 public void testStartActionModeWithCallback() { 58 mWindowCallback.mShouldReturnOwnActionMode = true; 59 60 ActionMode mode = mPhoneWindow.getDecorView().startActionMode( 61 mActionModeCallback, ActionMode.TYPE_FLOATING); 62 63 assertEquals(mWindowCallback.mLastCreatedActionMode, mode); 64 } 65 66 public void testStartActionModePrimaryFinishesPreviousMode() { 67 // Use custom callback to control the provided ActionMode. 68 mWindowCallback.mShouldReturnOwnActionMode = true; 69 70 ActionMode mode1 = mPhoneWindow.getDecorView().startActionMode( 71 mActionModeCallback, ActionMode.TYPE_PRIMARY); 72 ActionMode mode2 = mPhoneWindow.getDecorView().startActionMode( 73 mActionModeCallback, ActionMode.TYPE_PRIMARY); 74 75 assertTrue(mode1 instanceof MockActionMode); 76 assertTrue(((MockActionMode) mode1).mIsFinished); 77 assertNotNull(mode2); 78 } 79 80 public void testStartActionModeFloatingFinishesPreviousMode() { 81 // Use custom callback to control the provided ActionMode. 82 mWindowCallback.mShouldReturnOwnActionMode = true; 83 84 ActionMode mode1 = mPhoneWindow.getDecorView().startActionMode( 85 mActionModeCallback, ActionMode.TYPE_FLOATING); 86 ActionMode mode2 = mPhoneWindow.getDecorView().startActionMode( 87 mActionModeCallback, ActionMode.TYPE_FLOATING); 88 89 assertTrue(mode1 instanceof MockActionMode); 90 assertTrue(((MockActionMode) mode1).mIsFinished); 91 assertNotNull(mode2); 92 } 93 94 public void testStartActionModePreservesPreviousModeOfDifferentType1() { 95 // Use custom callback to control the provided ActionMode. 96 mWindowCallback.mShouldReturnOwnActionMode = true; 97 98 ActionMode mode1 = mPhoneWindow.getDecorView().startActionMode( 99 mActionModeCallback, ActionMode.TYPE_FLOATING); 100 ActionMode mode2 = mPhoneWindow.getDecorView().startActionMode( 101 mActionModeCallback, ActionMode.TYPE_PRIMARY); 102 103 assertTrue(mode1 instanceof MockActionMode); 104 assertFalse(((MockActionMode) mode1).mIsFinished); 105 assertNotNull(mode2); 106 } 107 108 public void testStartActionModePreservesPreviousModeOfDifferentType2() { 109 // Use custom callback to control the provided ActionMode. 110 mWindowCallback.mShouldReturnOwnActionMode = true; 111 112 ActionMode mode1 = mPhoneWindow.getDecorView().startActionMode( 113 mActionModeCallback, ActionMode.TYPE_PRIMARY); 114 ActionMode mode2 = mPhoneWindow.getDecorView().startActionMode( 115 mActionModeCallback, ActionMode.TYPE_FLOATING); 116 117 assertTrue(mode1 instanceof MockActionMode); 118 assertFalse(((MockActionMode) mode1).mIsFinished); 119 assertNotNull(mode2); 120 } 121 122 public void testWindowCallbackModesLifecycleIsNotHandled() { 123 mWindowCallback.mShouldReturnOwnActionMode = true; 124 125 ActionMode mode = mPhoneWindow.getDecorView().startActionMode( 126 mActionModeCallback, ActionMode.TYPE_PRIMARY); 127 128 assertNotNull(mode); 129 assertEquals(mWindowCallback.mLastCreatedActionMode, mode); 130 assertFalse(mActionModeCallback.mIsCreateActionModeCalled); 131 assertTrue(mWindowCallback.mIsActionModeStarted); 132 } 133 134 @UiThreadTest 135 public void testCreatedPrimaryModeLifecycleIsHandled() { 136 mWindowCallback.mShouldReturnOwnActionMode = false; 137 138 ActionMode mode = mPhoneWindow.getDecorView().startActionMode( 139 mActionModeCallback, ActionMode.TYPE_PRIMARY); 140 141 assertNotNull(mode); 142 assertEquals(ActionMode.TYPE_PRIMARY, mode.getType()); 143 assertTrue(mActionModeCallback.mIsCreateActionModeCalled); 144 assertTrue(mWindowCallback.mIsActionModeStarted); 145 } 146 147 @UiThreadTest 148 public void testCreatedFloatingModeLifecycleIsHandled() { 149 mWindowCallback.mShouldReturnOwnActionMode = false; 150 151 ActionMode mode = mPhoneWindow.getDecorView().startActionMode( 152 mActionModeCallback, ActionMode.TYPE_FLOATING); 153 154 assertNotNull(mode); 155 assertEquals(ActionMode.TYPE_FLOATING, mode.getType()); 156 assertTrue(mActionModeCallback.mIsCreateActionModeCalled); 157 assertTrue(mWindowCallback.mIsActionModeStarted); 158 } 159 160 @UiThreadTest 161 public void testCreatedModeIsNotStartedIfCreateReturnsFalse() { 162 mWindowCallback.mShouldReturnOwnActionMode = false; 163 mActionModeCallback.mShouldCreateActionMode = false; 164 165 ActionMode mode = mPhoneWindow.getDecorView().startActionMode( 166 mActionModeCallback, ActionMode.TYPE_FLOATING); 167 168 assertTrue(mActionModeCallback.mIsCreateActionModeCalled); 169 assertFalse(mWindowCallback.mIsActionModeStarted); 170 assertNull(mode); 171 } 172 173 private static final class MockWindowCallback implements Window.Callback { 174 private boolean mShouldReturnOwnActionMode = false; 175 private MockActionMode mLastCreatedActionMode; 176 private boolean mIsActionModeStarted = false; 177 178 @Override 179 public boolean dispatchKeyEvent(KeyEvent event) { 180 return false; 181 } 182 183 @Override 184 public boolean dispatchKeyShortcutEvent(KeyEvent event) { 185 return false; 186 } 187 188 @Override 189 public boolean dispatchTouchEvent(MotionEvent event) { 190 return false; 191 } 192 193 @Override 194 public boolean dispatchTrackballEvent(MotionEvent event) { 195 return false; 196 } 197 198 @Override 199 public boolean dispatchGenericMotionEvent(MotionEvent event) { 200 return false; 201 } 202 203 @Override 204 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 205 return false; 206 } 207 208 @Override 209 public View onCreatePanelView(int featureId) { 210 return null; 211 } 212 213 @Override 214 public boolean onCreatePanelMenu(int featureId, Menu menu) { 215 return false; 216 } 217 218 @Override 219 public boolean onPreparePanel(int featureId, View view, Menu menu) { 220 return false; 221 } 222 223 @Override 224 public boolean onMenuOpened(int featureId, Menu menu) { 225 return false; 226 } 227 228 @Override 229 public boolean onMenuItemSelected(int featureId, MenuItem item) { 230 return false; 231 } 232 233 @Override 234 public void onWindowAttributesChanged(LayoutParams attrs) {} 235 236 @Override 237 public void onContentChanged() {} 238 239 @Override 240 public void onWindowFocusChanged(boolean hasFocus) {} 241 242 @Override 243 public void onAttachedToWindow() {} 244 245 @Override 246 public void onDetachedFromWindow() {} 247 248 @Override 249 public void onPanelClosed(int featureId, Menu menu) {} 250 251 @Override 252 public boolean onSearchRequested() { 253 return false; 254 } 255 256 @Override 257 public boolean onSearchRequested(SearchEvent searchEvent) { 258 return false; 259 } 260 261 @Override 262 public ActionMode onWindowStartingActionMode(Callback callback) { 263 if (mShouldReturnOwnActionMode) { 264 MockActionMode mode = new MockActionMode(); 265 mLastCreatedActionMode = mode; 266 return mode; 267 } 268 return null; 269 } 270 271 @Override 272 public ActionMode onWindowStartingActionMode(Callback callback, int type) { 273 if (mShouldReturnOwnActionMode) { 274 MockActionMode mode = new MockActionMode(); 275 mode.mActionModeType = type; 276 mLastCreatedActionMode = mode; 277 return mode; 278 } 279 return null; 280 } 281 282 @Override 283 public void onActionModeStarted(ActionMode mode) { 284 mIsActionModeStarted = true; 285 } 286 287 @Override 288 public void onActionModeFinished(ActionMode mode) {} 289 } 290 291 private static final class MockActionModeCallback implements ActionMode.Callback { 292 private boolean mShouldCreateActionMode = true; 293 private boolean mIsCreateActionModeCalled = false; 294 295 @Override 296 public boolean onPrepareActionMode(ActionMode mode, Menu menu) { 297 return true; 298 } 299 300 @Override 301 public void onDestroyActionMode(ActionMode mode) {} 302 303 @Override 304 public boolean onCreateActionMode(ActionMode mode, Menu menu) { 305 mIsCreateActionModeCalled = true; 306 return mShouldCreateActionMode; 307 } 308 309 @Override 310 public boolean onActionItemClicked(ActionMode mode, MenuItem item) { 311 return false; 312 } 313 } 314 315 private static final class MockActionMode extends ActionMode { 316 private int mActionModeType = ActionMode.TYPE_PRIMARY; 317 private boolean mIsFinished = false; 318 319 @Override 320 public int getType() { 321 return mActionModeType; 322 } 323 324 @Override 325 public void setTitle(CharSequence title) {} 326 327 @Override 328 public void setTitle(int resId) {} 329 330 @Override 331 public void setSubtitle(CharSequence subtitle) {} 332 333 @Override 334 public void setSubtitle(int resId) {} 335 336 @Override 337 public void setCustomView(View view) {} 338 339 @Override 340 public void invalidate() {} 341 342 @Override 343 public void finish() { 344 mIsFinished = true; 345 } 346 347 @Override 348 public Menu getMenu() { 349 return null; 350 } 351 352 @Override 353 public CharSequence getTitle() { 354 return null; 355 } 356 357 @Override 358 public CharSequence getSubtitle() { 359 return null; 360 } 361 362 @Override 363 public View getCustomView() { 364 return null; 365 } 366 367 @Override 368 public MenuInflater getMenuInflater() { 369 return null; 370 } 371 } 372} 373