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.nene.utils.Poll; 32 import com.android.bedstead.nene.utils.ShellCommand; 33 import com.android.bedstead.permissions.PermissionContext; 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 * Turn the screen off. 90 */ sleep()91 public void sleep() { 92 String unused1 = ShellCommand.builder("input keyevent") 93 .addOperand("KEYCODE_SLEEP") 94 .allowEmptyOutput(true) 95 .validate(String::isEmpty) 96 .executeOrThrowNeneException("Error sleeping device"); 97 98 Boolean unused2 = Poll.forValue("isScreenOn", this::isScreenOn) 99 .toBeEqualTo(false) 100 .errorOnFail() 101 .await(); 102 } 103 104 /** 105 * Dismiss the keyguard. 106 */ unlock()107 public void unlock() { 108 String unused = ShellCommand.builder("wm dismiss-keyguard") 109 .allowEmptyOutput(true) 110 .validate(String::isEmpty) 111 .executeOrThrowNeneException("Error dismissing keyguard"); 112 } 113 114 /** 115 * Set the screen on setting. 116 * 117 * <p>When enabled, the device will never sleep. 118 */ 119 @Experimental keepScreenOn(boolean stayOn)120 public void keepScreenOn(boolean stayOn) { 121 // one day vs default 122 TestApis.settings().system().putInt("screen_off_timeout", stayOn ? 86400000 : 121000); 123 String unused = ShellCommand.builder("svc power stayon") 124 .addOperand(stayOn ? "true" : "false") 125 .allowEmptyOutput(true) 126 .validate(String::isEmpty) 127 .executeOrThrowNeneException("Error setting stayOn"); 128 unlock(); 129 } 130 131 @Experimental setKeyguardEnabled(boolean keyguardEnabled)132 public void setKeyguardEnabled(boolean keyguardEnabled) { 133 try (PermissionContext p = TestApis.permissions().withPermission(DISABLE_KEYGUARD)) { 134 if (keyguardEnabled) { 135 keyGuardLock().reenableKeyguard(); 136 } else { 137 keyGuardLock().disableKeyguard(); 138 } 139 } 140 } 141 142 /** 143 * True if the screen is on. 144 */ isScreenOn()145 public boolean isScreenOn() { 146 try { 147 return sDevice.isScreenOn(); 148 } catch (RemoteException e) { 149 throw new NeneException("Error getting isScreenOn", e); 150 } 151 } 152 153 /** 154 * Returns True if this device is a handheld device. 155 */ 156 @Experimental isHandheld()157 public boolean isHandheld() { 158 // handheld nature is not exposed to package manager, for now 159 // we check for touchscreen and NOT watch, NOT tv, NOT car and NOT PC. 160 return sPackageManager.hasSystemFeature(sPackageManager.FEATURE_TOUCHSCREEN) 161 && !sPackageManager.hasSystemFeature(sPackageManager.FEATURE_WATCH) 162 && !sPackageManager.hasSystemFeature(sPackageManager.FEATURE_TELEVISION) 163 && !sPackageManager.hasSystemFeature(sPackageManager.FEATURE_AUTOMOTIVE) 164 && !sPackageManager.hasSystemFeature(sPackageManager.FEATURE_PC); 165 } 166 } 167