blob: 222c692a9778ccc3e1d3511530361821697d439e [file] [log] [blame]
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.policy;
import static android.view.KeyEvent.ACTION_DOWN;
import static android.view.KeyEvent.ACTION_UP;
import static android.view.KeyEvent.KEYCODE_POWER;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.android.server.policy.SingleKeyGestureDetector.KEY_LONGPRESS;
import static com.android.server.policy.SingleKeyGestureDetector.KEY_VERYLONGPRESS;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.app.Instrumentation;
import android.content.Context;
import android.os.SystemClock;
import android.view.KeyEvent;
import android.view.ViewConfiguration;
import org.junit.Before;
import org.junit.Test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* Test class for {@link SingleKeyGestureDetector}.
*
* Build/Install/Run:
* atest WmTests:SingleKeyGestureTests
*/
public class SingleKeyGestureTests {
private SingleKeyGestureDetector mDetector;
private int mMaxMultiPressPowerCount = 2;
private CountDownLatch mShortPressed = new CountDownLatch(1);
private CountDownLatch mLongPressed = new CountDownLatch(1);
private CountDownLatch mVeryLongPressed = new CountDownLatch(1);
private CountDownLatch mMultiPressed = new CountDownLatch(1);
private final Instrumentation mInstrumentation = getInstrumentation();
private final Context mContext = mInstrumentation.getTargetContext();
private long mWaitTimeout;
private long mLongPressTime;
private long mVeryLongPressTime;
// Allow press from non interactive mode.
private boolean mAllowNonInteractiveForPress = true;
private boolean mAllowNonInteractiveForLongPress = true;
@Before
public void setUp() {
mDetector = new SingleKeyGestureDetector(mContext);
initSingleKeyGestureRules();
mWaitTimeout = ViewConfiguration.getMultiPressTimeout() + 50;
mLongPressTime = ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout() + 50;
mVeryLongPressTime = mContext.getResources().getInteger(
com.android.internal.R.integer.config_veryLongPressTimeout) + 50;
}
private void initSingleKeyGestureRules() {
mDetector.addRule(new SingleKeyGestureDetector.SingleKeyRule(KEYCODE_POWER,
KEY_LONGPRESS | KEY_VERYLONGPRESS) {
@Override
int getMaxMultiPressCount() {
return mMaxMultiPressPowerCount;
}
@Override
public void onPress(long downTime) {
if (mDetector.beganFromNonInteractive() && !mAllowNonInteractiveForPress) {
return;
}
mShortPressed.countDown();
}
@Override
void onLongPress(long downTime) {
if (mDetector.beganFromNonInteractive() && !mAllowNonInteractiveForLongPress) {
return;
}
mLongPressed.countDown();
}
@Override
void onVeryLongPress(long downTime) {
mVeryLongPressed.countDown();
}
@Override
void onMultiPress(long downTime, int count) {
if (mDetector.beganFromNonInteractive() && !mAllowNonInteractiveForPress) {
return;
}
mMultiPressed.countDown();
assertEquals(mMaxMultiPressPowerCount, count);
}
});
}
private void pressKey(long eventTime, int keyCode, long pressTime) {
pressKey(eventTime, keyCode, pressTime, true /* interactive */);
}
private void pressKey(long eventTime, int keyCode, long pressTime, boolean interactive) {
final KeyEvent keyDown = new KeyEvent(eventTime, eventTime, ACTION_DOWN,
keyCode, 0 /* repeat */, 0 /* metaState */);
mDetector.interceptKey(keyDown, interactive);
// keep press down.
try {
Thread.sleep(pressTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
eventTime += pressTime;
final KeyEvent keyUp = new KeyEvent(eventTime, eventTime, ACTION_UP,
keyCode, 0 /* repeat */, 0 /* metaState */);
mDetector.interceptKey(keyUp, interactive);
}
@Test
public void testShortPress() throws InterruptedException {
final long eventTime = SystemClock.uptimeMillis();
pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
assertTrue(mShortPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
}
@Test
public void testLongPress() throws InterruptedException {
final long eventTime = SystemClock.uptimeMillis();
pressKey(eventTime, KEYCODE_POWER, mLongPressTime);
assertTrue(mLongPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
}
@Test
public void testVeryLongPress() throws InterruptedException {
final long eventTime = SystemClock.uptimeMillis();
pressKey(eventTime, KEYCODE_POWER, mVeryLongPressTime);
assertTrue(mVeryLongPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
}
@Test
public void testMultiPress() throws InterruptedException {
final long eventTime = SystemClock.uptimeMillis();
pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
assertTrue(mMultiPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
}
@Test
public void testNonInteractive() throws InterruptedException {
long eventTime = SystemClock.uptimeMillis();
// Disallow short press behavior from non interactive.
mAllowNonInteractiveForPress = false;
pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */, false /* interactive */);
assertFalse(mShortPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
// Allow long press behavior from non interactive.
eventTime = SystemClock.uptimeMillis();
pressKey(eventTime, KEYCODE_POWER, mLongPressTime, false /* interactive */);
assertTrue(mLongPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
}
}