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