1 /* 2 * Copyright (C) 2021 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 17 package com.android.bedstead.nene.device; 18 19 import static com.android.bedstead.permissions.CommonPermissions.DISABLE_KEYGUARD; 20 21 import android.app.KeyguardManager; 22 import android.content.pm.PackageManager; 23 import android.os.RemoteException; 24 import android.support.test.uiautomator.UiDevice; 25 26 import androidx.test.platform.app.InstrumentationRegistry; 27 28 import com.android.bedstead.nene.TestApis; 29 import com.android.bedstead.nene.annotations.Experimental; 30 import com.android.bedstead.nene.exceptions.NeneException; 31 import com.android.bedstead.permissions.PermissionContext; 32 import com.android.bedstead.nene.utils.Poll; 33 import com.android.bedstead.nene.utils.ShellCommand; 34 35 /** Helper methods related to the device. */ 36 public final class Device { 37 public static final Device sInstance = new Device(); 38 private static final UiDevice sDevice = 39 UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); 40 private static final KeyguardManager sKeyguardManager = 41 TestApis.context().instrumentedContext() 42 .getSystemService(KeyguardManager.class); 43 private static KeyguardManager.KeyguardLock sKeyguardLock; 44 45 private static PackageManager sPackageManager = 46 TestApis.context().instrumentedContext().getPackageManager(); 47 Device()48 private Device() { 49 50 } 51 keyGuardLock()52 private KeyguardManager.KeyguardLock keyGuardLock() { 53 if (sKeyguardManager == null) { 54 if (TestApis.packages().instrumented().isInstantApp()) { 55 throw new NeneException("Cannot manage keyguard with instant app"); 56 } 57 58 throw new NeneException("KeyguardManager cannot be found."); 59 } 60 61 if (sKeyguardLock == null) { 62 synchronized (Device.class) { 63 if (sKeyguardLock == null) { 64 sKeyguardLock = sKeyguardManager.newKeyguardLock("Nene"); 65 } 66 } 67 } 68 69 return sKeyguardLock; 70 } 71 72 /** 73 * Turn the screen on. 74 */ wakeUp()75 public void wakeUp() { 76 String unused1 = ShellCommand.builder("input keyevent") 77 .addOperand("KEYCODE_WAKEUP") 78 .allowEmptyOutput(true) 79 .validate(String::isEmpty) 80 .executeOrThrowNeneException("Error waking up device"); 81 82 Boolean unused2 = Poll.forValue("isScreenOn", this::isScreenOn) 83 .toBeEqualTo(true) 84 .errorOnFail() 85 .await(); 86 } 87 88 /** 89 * Dismiss the keyguard. 90 */ unlock()91 public void unlock() { 92 String unused = ShellCommand.builder("wm dismiss-keyguard") 93 .allowEmptyOutput(true) 94 .validate(String::isEmpty) 95 .executeOrThrowNeneException("Error dismissing keyguard"); 96 } 97 98 /** 99 * Set the screen on setting. 100 * 101 * <p>When enabled, the device will never sleep. 102 */ 103 @Experimental keepScreenOn(boolean stayOn)104 public void keepScreenOn(boolean stayOn) { 105 // one day vs default 106 TestApis.settings().system().putInt("screen_off_timeout", stayOn ? 86400000 : 121000); 107 String unused = ShellCommand.builder("svc power stayon") 108 .addOperand(stayOn ? "true" : "false") 109 .allowEmptyOutput(true) 110 .validate(String::isEmpty) 111 .executeOrThrowNeneException("Error setting stayOn"); 112 unlock(); 113 } 114 115 @Experimental setKeyguardEnabled(boolean keyguardEnabled)116 public void setKeyguardEnabled(boolean keyguardEnabled) { 117 try (PermissionContext p = TestApis.permissions().withPermission(DISABLE_KEYGUARD)) { 118 if (keyguardEnabled) { 119 keyGuardLock().reenableKeyguard(); 120 } else { 121 keyGuardLock().disableKeyguard(); 122 } 123 } 124 } 125 126 /** 127 * True if the screen is on. 128 */ isScreenOn()129 public boolean isScreenOn() { 130 try { 131 return sDevice.isScreenOn(); 132 } catch (RemoteException e) { 133 throw new NeneException("Error getting isScreenOn", e); 134 } 135 } 136 137 /** 138 * Returns True if this device is a handheld device. 139 */ 140 @Experimental isHandheld()141 public boolean isHandheld() { 142 // handheld nature is not exposed to package manager, for now 143 // we check for touchscreen and NOT watch, NOT tv, NOT car and NOT PC. 144 return sPackageManager.hasSystemFeature(sPackageManager.FEATURE_TOUCHSCREEN) 145 && !sPackageManager.hasSystemFeature(sPackageManager.FEATURE_WATCH) 146 && !sPackageManager.hasSystemFeature(sPackageManager.FEATURE_TELEVISION) 147 && !sPackageManager.hasSystemFeature(sPackageManager.FEATURE_AUTOMOTIVE) 148 && !sPackageManager.hasSystemFeature(sPackageManager.FEATURE_PC); 149 } 150 } 151