appium-adb 14.1.2 → 14.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/build/lib/tools/aab-utils.d.ts +5 -4
- package/build/lib/tools/aab-utils.d.ts.map +1 -1
- package/build/lib/tools/aab-utils.js +13 -11
- package/build/lib/tools/aab-utils.js.map +1 -1
- package/build/lib/tools/android-manifest.d.ts +26 -30
- package/build/lib/tools/android-manifest.d.ts.map +1 -1
- package/build/lib/tools/android-manifest.js +33 -47
- package/build/lib/tools/android-manifest.js.map +1 -1
- package/build/lib/tools/apks-utils.d.ts +25 -29
- package/build/lib/tools/apks-utils.d.ts.map +1 -1
- package/build/lib/tools/apks-utils.js +41 -52
- package/build/lib/tools/apks-utils.js.map +1 -1
- package/build/lib/tools/emulator-commands.d.ts.map +1 -1
- package/build/lib/tools/emulator-commands.js +2 -1
- package/build/lib/tools/emulator-commands.js.map +1 -1
- package/build/lib/tools/fs-commands.d.ts +25 -30
- package/build/lib/tools/fs-commands.d.ts.map +1 -1
- package/build/lib/tools/fs-commands.js +19 -26
- package/build/lib/tools/fs-commands.js.map +1 -1
- package/build/lib/tools/general-commands.d.ts +36 -58
- package/build/lib/tools/general-commands.d.ts.map +1 -1
- package/build/lib/tools/general-commands.js +41 -47
- package/build/lib/tools/general-commands.js.map +1 -1
- package/build/lib/tools/keyboard-commands.d.ts +27 -36
- package/build/lib/tools/keyboard-commands.d.ts.map +1 -1
- package/build/lib/tools/keyboard-commands.js +24 -34
- package/build/lib/tools/keyboard-commands.js.map +1 -1
- package/build/lib/tools/lockmgmt.d.ts +25 -36
- package/build/lib/tools/lockmgmt.d.ts.map +1 -1
- package/build/lib/tools/lockmgmt.js +34 -38
- package/build/lib/tools/lockmgmt.js.map +1 -1
- package/build/lib/tools/logcat-commands.d.ts +11 -30
- package/build/lib/tools/logcat-commands.d.ts.map +1 -1
- package/build/lib/tools/logcat-commands.js +16 -17
- package/build/lib/tools/logcat-commands.js.map +1 -1
- package/build/lib/tools/network-commands.d.ts +24 -31
- package/build/lib/tools/network-commands.d.ts.map +1 -1
- package/build/lib/tools/network-commands.js +14 -24
- package/build/lib/tools/network-commands.js.map +1 -1
- package/lib/tools/{aab-utils.js → aab-utils.ts} +24 -15
- package/lib/tools/{android-manifest.js → android-manifest.ts} +66 -59
- package/lib/tools/{apks-utils.js → apks-utils.ts} +76 -68
- package/lib/tools/emulator-commands.ts +3 -2
- package/lib/tools/{fs-commands.js → fs-commands.ts} +41 -35
- package/lib/tools/{general-commands.js → general-commands.ts} +71 -68
- package/lib/tools/{keyboard-commands.js → keyboard-commands.ts} +42 -49
- package/lib/tools/{lockmgmt.js → lockmgmt.ts} +71 -56
- package/lib/tools/{logcat-commands.js → logcat-commands.ts} +24 -22
- package/lib/tools/{network-commands.js → network-commands.ts} +42 -34
- package/package.json +2 -2
|
@@ -2,6 +2,8 @@ import {log} from '../logger.js';
|
|
|
2
2
|
import _ from 'lodash';
|
|
3
3
|
import {waitForCondition} from 'asyncbox';
|
|
4
4
|
import B from 'bluebird';
|
|
5
|
+
import type {ADB} from '../adb.js';
|
|
6
|
+
import type {KeyboardState} from './types.js';
|
|
5
7
|
|
|
6
8
|
const KEYCODE_ESC = 111;
|
|
7
9
|
const KEYCODE_BACK = 4;
|
|
@@ -10,14 +12,15 @@ const KEYCODE_BACK = 4;
|
|
|
10
12
|
* Hides software keyboard if it is visible.
|
|
11
13
|
* Noop if the keyboard is already hidden.
|
|
12
14
|
*
|
|
13
|
-
* @
|
|
14
|
-
* @param {number} [timeoutMs=1000] For how long to wait (in milliseconds)
|
|
15
|
+
* @param timeoutMs - For how long to wait (in milliseconds)
|
|
15
16
|
* until the keyboard is actually hidden.
|
|
16
|
-
* @returns
|
|
17
|
+
* @returns `false` if the keyboard was already hidden
|
|
17
18
|
* @throws {Error} If the keyboard cannot be hidden.
|
|
18
19
|
*/
|
|
19
|
-
export async function hideKeyboard(timeoutMs = 1000) {
|
|
20
|
-
|
|
20
|
+
export async function hideKeyboard(this: ADB, timeoutMs: number = 1000): Promise<boolean> {
|
|
21
|
+
const keyboardState = await this.isSoftKeyboardPresent();
|
|
22
|
+
let {isKeyboardShown} = keyboardState;
|
|
23
|
+
const {canCloseKeyboard} = keyboardState;
|
|
21
24
|
if (!isKeyboardShown) {
|
|
22
25
|
log.info('Keyboard has no UI; no closing necessary');
|
|
23
26
|
return false;
|
|
@@ -43,10 +46,9 @@ export async function hideKeyboard(timeoutMs = 1000) {
|
|
|
43
46
|
/**
|
|
44
47
|
* Retrieve the state of the software keyboard on the device under test.
|
|
45
48
|
*
|
|
46
|
-
* @
|
|
47
|
-
* @return {Promise<import('./types').KeyboardState>} The keyboard state.
|
|
49
|
+
* @return The keyboard state.
|
|
48
50
|
*/
|
|
49
|
-
export async function isSoftKeyboardPresent() {
|
|
51
|
+
export async function isSoftKeyboardPresent(this: ADB): Promise<KeyboardState> {
|
|
50
52
|
try {
|
|
51
53
|
const stdout = await this.shell(['dumpsys', 'input_method']);
|
|
52
54
|
const inputShownMatch = /mInputShown=(\w+)/.exec(stdout);
|
|
@@ -56,17 +58,16 @@ export async function isSoftKeyboardPresent() {
|
|
|
56
58
|
canCloseKeyboard: !!(inputViewShownMatch && inputViewShownMatch[1] === 'true'),
|
|
57
59
|
};
|
|
58
60
|
} catch (e) {
|
|
59
|
-
throw new Error(`Error finding softkeyboard. Original error: ${e.message}`);
|
|
61
|
+
throw new Error(`Error finding softkeyboard. Original error: ${(e as Error).message}`);
|
|
60
62
|
}
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
/**
|
|
64
66
|
* Send the particular keycode to the device under test.
|
|
65
67
|
*
|
|
66
|
-
* @
|
|
67
|
-
* @param {string|number} keycode - The actual key code to be sent.
|
|
68
|
+
* @param keycode - The actual key code to be sent.
|
|
68
69
|
*/
|
|
69
|
-
export async function keyevent(keycode) {
|
|
70
|
+
export async function keyevent(this: ADB, keycode: string | number): Promise<void> {
|
|
70
71
|
// keycode must be an int.
|
|
71
72
|
const code = parseInt(`${keycode}`, 10);
|
|
72
73
|
await this.shell(['input', 'keyevent', `${code}`]);
|
|
@@ -75,14 +76,13 @@ export async function keyevent(keycode) {
|
|
|
75
76
|
/**
|
|
76
77
|
* Retrieve the list of available input methods (IMEs) for the device under test.
|
|
77
78
|
*
|
|
78
|
-
* @
|
|
79
|
-
* @return {Promise<string[]>} The list of IME names or an empty list.
|
|
79
|
+
* @return The list of IME names or an empty list.
|
|
80
80
|
*/
|
|
81
|
-
export async function availableIMEs() {
|
|
81
|
+
export async function availableIMEs(this: ADB): Promise<string[]> {
|
|
82
82
|
try {
|
|
83
83
|
return getIMEListFromOutput(await this.shell(['ime', 'list', '-a']));
|
|
84
84
|
} catch (e) {
|
|
85
|
-
const err =
|
|
85
|
+
const err = e as Error;
|
|
86
86
|
throw new Error(`Error getting available IME's. Original error: ${err.message}`);
|
|
87
87
|
}
|
|
88
88
|
}
|
|
@@ -90,14 +90,13 @@ export async function availableIMEs() {
|
|
|
90
90
|
/**
|
|
91
91
|
* Retrieve the list of enabled input methods (IMEs) for the device under test.
|
|
92
92
|
*
|
|
93
|
-
* @
|
|
94
|
-
* @return {Promise<string[]>} The list of enabled IME names or an empty list.
|
|
93
|
+
* @return The list of enabled IME names or an empty list.
|
|
95
94
|
*/
|
|
96
|
-
export async function enabledIMEs() {
|
|
95
|
+
export async function enabledIMEs(this: ADB): Promise<string[]> {
|
|
97
96
|
try {
|
|
98
97
|
return getIMEListFromOutput(await this.shell(['ime', 'list']));
|
|
99
98
|
} catch (e) {
|
|
100
|
-
const err =
|
|
99
|
+
const err = e as Error;
|
|
101
100
|
throw new Error(`Error getting enabled IME's. Original error: ${err.message}`);
|
|
102
101
|
}
|
|
103
102
|
}
|
|
@@ -105,48 +104,44 @@ export async function enabledIMEs() {
|
|
|
105
104
|
/**
|
|
106
105
|
* Enable the particular input method on the device under test.
|
|
107
106
|
*
|
|
108
|
-
* @
|
|
109
|
-
* @param {string} imeId - One of existing IME ids.
|
|
107
|
+
* @param imeId - One of existing IME ids.
|
|
110
108
|
*/
|
|
111
|
-
export async function enableIME(imeId) {
|
|
109
|
+
export async function enableIME(this: ADB, imeId: string): Promise<void> {
|
|
112
110
|
await this.shell(['ime', 'enable', imeId]);
|
|
113
111
|
}
|
|
114
112
|
|
|
115
113
|
/**
|
|
116
114
|
* Disable the particular input method on the device under test.
|
|
117
115
|
*
|
|
118
|
-
* @
|
|
119
|
-
* @param {string} imeId - One of existing IME ids.
|
|
116
|
+
* @param imeId - One of existing IME ids.
|
|
120
117
|
*/
|
|
121
|
-
export async function disableIME(imeId) {
|
|
118
|
+
export async function disableIME(this: ADB, imeId: string): Promise<void> {
|
|
122
119
|
await this.shell(['ime', 'disable', imeId]);
|
|
123
120
|
}
|
|
124
121
|
|
|
125
122
|
/**
|
|
126
123
|
* Set the particular input method on the device under test.
|
|
127
124
|
*
|
|
128
|
-
* @
|
|
129
|
-
* @param {string} imeId - One of existing IME ids.
|
|
125
|
+
* @param imeId - One of existing IME ids.
|
|
130
126
|
*/
|
|
131
|
-
export async function setIME(imeId) {
|
|
127
|
+
export async function setIME(this: ADB, imeId: string): Promise<void> {
|
|
132
128
|
await this.shell(['ime', 'set', imeId]);
|
|
133
129
|
}
|
|
134
130
|
|
|
135
131
|
/**
|
|
136
132
|
* Get the default input method on the device under test.
|
|
137
133
|
*
|
|
138
|
-
* @
|
|
139
|
-
* @return {Promise<string|null>} The name of the default input method
|
|
134
|
+
* @return The name of the default input method
|
|
140
135
|
*/
|
|
141
|
-
export async function defaultIME() {
|
|
136
|
+
export async function defaultIME(this: ADB): Promise<string | null> {
|
|
142
137
|
try {
|
|
143
|
-
|
|
138
|
+
const engine = await this.getSetting('secure', 'default_input_method');
|
|
144
139
|
if (engine === 'null') {
|
|
145
140
|
return null;
|
|
146
141
|
}
|
|
147
142
|
return engine.trim();
|
|
148
143
|
} catch (e) {
|
|
149
|
-
const err =
|
|
144
|
+
const err = e as Error;
|
|
150
145
|
throw new Error(`Error getting default IME. Original error: ${err.message}`);
|
|
151
146
|
}
|
|
152
147
|
}
|
|
@@ -156,18 +151,17 @@ export async function defaultIME() {
|
|
|
156
151
|
* The text gets properly escaped before being passed to ADB.
|
|
157
152
|
* Noop if the text is empty.
|
|
158
153
|
*
|
|
159
|
-
* @
|
|
160
|
-
* @param {string|number} text - The actual text to be sent.
|
|
154
|
+
* @param text - The actual text to be sent.
|
|
161
155
|
* @throws {Error} If it is impossible to escape the given string
|
|
162
156
|
*/
|
|
163
|
-
export async function inputText(text) {
|
|
157
|
+
export async function inputText(this: ADB, text: string | number): Promise<void> {
|
|
164
158
|
if (text === '') {
|
|
165
159
|
return;
|
|
166
160
|
}
|
|
167
161
|
|
|
168
162
|
const originalStr = `${text}`;
|
|
169
163
|
const escapedText = originalStr.replace(/\$/g, '\\$').replace(/ /g, '%s');
|
|
170
|
-
let args = ['input', 'text', originalStr];
|
|
164
|
+
let args: string[] = ['input', 'text', originalStr];
|
|
171
165
|
// https://stackoverflow.com/questions/25791423/adb-shell-input-text-does-not-take-ampersand-character/25791498
|
|
172
166
|
const adbInputEscapePattern = /[()<>|;&*\\~^"']/g;
|
|
173
167
|
if (escapedText !== originalStr || adbInputEscapePattern.test(originalStr)) {
|
|
@@ -186,14 +180,13 @@ export async function inputText(text) {
|
|
|
186
180
|
* Executes the given function with the given input method context
|
|
187
181
|
* and then restores the IME to the original value
|
|
188
182
|
*
|
|
189
|
-
* @
|
|
190
|
-
* @param
|
|
191
|
-
* @
|
|
192
|
-
* @returns {Promise<any>} The result of the given function
|
|
183
|
+
* @param ime - Valid IME identifier
|
|
184
|
+
* @param fn - Function to execute
|
|
185
|
+
* @returns The result of the given function
|
|
193
186
|
*/
|
|
194
|
-
export async function runInImeContext(ime, fn) {
|
|
187
|
+
export async function runInImeContext<T>(this: ADB, ime: string, fn: () => Promise<T>): Promise<T> {
|
|
195
188
|
// This is needed to properly apply new IME on some devices
|
|
196
|
-
const cycleImeState = async (
|
|
189
|
+
const cycleImeState = async (name: string) => {
|
|
197
190
|
try {
|
|
198
191
|
await this.disableIME(name);
|
|
199
192
|
await this.enableIME(name);
|
|
@@ -225,12 +218,11 @@ export async function runInImeContext(ime, fn) {
|
|
|
225
218
|
// #region Private function
|
|
226
219
|
|
|
227
220
|
/**
|
|
228
|
-
* @param
|
|
229
|
-
* @returns
|
|
221
|
+
* @param stdout
|
|
222
|
+
* @returns
|
|
230
223
|
*/
|
|
231
|
-
function getIMEListFromOutput(stdout) {
|
|
232
|
-
|
|
233
|
-
const engines = [];
|
|
224
|
+
function getIMEListFromOutput(stdout: string): string[] {
|
|
225
|
+
const engines: string[] = [];
|
|
234
226
|
for (const line of stdout.split('\n')) {
|
|
235
227
|
if (line.length > 0 && line[0] !== ' ') {
|
|
236
228
|
// remove newline and trailing colon, and add to the list
|
|
@@ -241,3 +233,4 @@ function getIMEListFromOutput(stdout) {
|
|
|
241
233
|
}
|
|
242
234
|
|
|
243
235
|
// #endregion
|
|
236
|
+
|
|
@@ -2,6 +2,7 @@ import {log} from '../logger.js';
|
|
|
2
2
|
import _ from 'lodash';
|
|
3
3
|
import B from 'bluebird';
|
|
4
4
|
import {waitForCondition} from 'asyncbox';
|
|
5
|
+
import type {ADB} from '../adb.js';
|
|
5
6
|
|
|
6
7
|
const CREDENTIAL_CANNOT_BE_NULL_OR_EMPTY_ERROR = `Credential can't be null or empty`;
|
|
7
8
|
const CREDENTIAL_DID_NOT_MATCH_ERROR = `didn't match`;
|
|
@@ -11,14 +12,14 @@ const KEYCODE_WAKEUP = 224; // works over API Level 20
|
|
|
11
12
|
const HIDE_KEYBOARD_WAIT_TIME = 100;
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
|
-
* @param
|
|
15
|
-
* @param
|
|
16
|
-
* @param
|
|
15
|
+
* @param verb
|
|
16
|
+
* @param oldCredential
|
|
17
|
+
* @param args
|
|
17
18
|
*/
|
|
18
|
-
function buildCommand(verb, oldCredential = null, ...args) {
|
|
19
|
+
function buildCommand(verb: string, oldCredential: string | null = null, ...args: string[]): string[] {
|
|
19
20
|
const cmd = ['locksettings', verb];
|
|
20
|
-
if (!_.isEmpty(oldCredential)) {
|
|
21
|
-
cmd.push('--old',
|
|
21
|
+
if (oldCredential && !_.isEmpty(oldCredential)) {
|
|
22
|
+
cmd.push('--old', oldCredential);
|
|
22
23
|
}
|
|
23
24
|
if (!_.isEmpty(args)) {
|
|
24
25
|
cmd.push(...args);
|
|
@@ -29,11 +30,10 @@ function buildCommand(verb, oldCredential = null, ...args) {
|
|
|
29
30
|
/**
|
|
30
31
|
* Performs swipe up gesture on the screen
|
|
31
32
|
*
|
|
32
|
-
* @
|
|
33
|
-
* @param {string} windowDumpsys The output of `adb shell dumpsys window` command
|
|
33
|
+
* @param windowDumpsys The output of `adb shell dumpsys window` command
|
|
34
34
|
* @throws {Error} If the display size cannot be retrieved
|
|
35
35
|
*/
|
|
36
|
-
async function swipeUp(windowDumpsys) {
|
|
36
|
+
async function swipeUp(this: ADB, windowDumpsys: string): Promise<void> {
|
|
37
37
|
const dimensionsMatch = /init=(\d+)x(\d+)/.exec(windowDumpsys);
|
|
38
38
|
if (!dimensionsMatch) {
|
|
39
39
|
throw new Error('Cannot retrieve the display size');
|
|
@@ -56,10 +56,9 @@ async function swipeUp(windowDumpsys) {
|
|
|
56
56
|
* Check whether the device supports lock settings management with `locksettings`
|
|
57
57
|
* command line tool. This tool has been added to Android toolset since API 27 Oreo
|
|
58
58
|
*
|
|
59
|
-
* @
|
|
60
|
-
* @return {Promise<boolean>} True if the management is supported. The result is cached per ADB instance
|
|
59
|
+
* @return True if the management is supported. The result is cached per ADB instance
|
|
61
60
|
*/
|
|
62
|
-
export async function isLockManagementSupported() {
|
|
61
|
+
export async function isLockManagementSupported(this: ADB): Promise<boolean> {
|
|
63
62
|
if (!_.isBoolean(this._isLockManagementSupported)) {
|
|
64
63
|
const passFlag = '__PASS__';
|
|
65
64
|
let output = '';
|
|
@@ -72,23 +71,25 @@ export async function isLockManagementSupported() {
|
|
|
72
71
|
`${this._isLockManagementSupported ? '' : 'not '}supported`,
|
|
73
72
|
);
|
|
74
73
|
}
|
|
75
|
-
return this._isLockManagementSupported;
|
|
74
|
+
return this._isLockManagementSupported as boolean;
|
|
76
75
|
}
|
|
77
76
|
|
|
78
77
|
/**
|
|
79
78
|
* Check whether the given credential is matches to the currently set one.
|
|
80
79
|
*
|
|
81
|
-
* @
|
|
82
|
-
* @param {string?} [credential=null] The credential value. It could be either
|
|
80
|
+
* @param credential - The credential value. It could be either
|
|
83
81
|
* pin, password or a pattern. A pattern is specified by a non-separated list
|
|
84
82
|
* of numbers that index the cell on the pattern in a 1-based manner in left
|
|
85
83
|
* to right and top to bottom order, i.e. the top-left cell is indexed with 1,
|
|
86
84
|
* whereas the bottom-right cell is indexed with 9. Example: 1234.
|
|
87
85
|
* null/empty value assumes the device has no lock currently set.
|
|
88
|
-
* @return
|
|
86
|
+
* @return True if the given credential matches to the device's one
|
|
89
87
|
* @throws {Error} If the verification faces an unexpected error
|
|
90
88
|
*/
|
|
91
|
-
export async function verifyLockCredential(
|
|
89
|
+
export async function verifyLockCredential(
|
|
90
|
+
this: ADB,
|
|
91
|
+
credential: string | null = null,
|
|
92
|
+
): Promise<boolean> {
|
|
92
93
|
try {
|
|
93
94
|
const {stdout, stderr} = await this.shell(buildCommand('verify', credential), {
|
|
94
95
|
outputFormat: this.EXEC_OUTPUT_FORMAT.FULL,
|
|
@@ -107,7 +108,11 @@ export async function verifyLockCredential(credential = null) {
|
|
|
107
108
|
} catch (e) {
|
|
108
109
|
throw new Error(
|
|
109
110
|
`Device lock credential verification failed. ` +
|
|
110
|
-
`Original error: ${
|
|
111
|
+
`Original error: ${
|
|
112
|
+
(e as Error & {stderr?: string; stdout?: string}).stderr
|
|
113
|
+
|| (e as Error & {stderr?: string; stdout?: string}).stdout
|
|
114
|
+
|| (e as Error).message
|
|
115
|
+
}`,
|
|
111
116
|
);
|
|
112
117
|
}
|
|
113
118
|
}
|
|
@@ -116,8 +121,7 @@ export async function verifyLockCredential(credential = null) {
|
|
|
116
121
|
* Clears current lock credentials. Usually it takes several seconds for a device to
|
|
117
122
|
* sync the credential state after this method returns.
|
|
118
123
|
*
|
|
119
|
-
* @
|
|
120
|
-
* @param {string?} [credential=null] The credential value. It could be either
|
|
124
|
+
* @param credential - The credential value. It could be either
|
|
121
125
|
* pin, password or a pattern. A pattern is specified by a non-separated list
|
|
122
126
|
* of numbers that index the cell on the pattern in a 1-based manner in left
|
|
123
127
|
* to right and top to bottom order, i.e. the top-left cell is indexed with 1,
|
|
@@ -125,7 +129,10 @@ export async function verifyLockCredential(credential = null) {
|
|
|
125
129
|
* null/empty value assumes the device has no lock currently set.
|
|
126
130
|
* @throws {Error} If operation faces an unexpected error
|
|
127
131
|
*/
|
|
128
|
-
export async function clearLockCredential(
|
|
132
|
+
export async function clearLockCredential(
|
|
133
|
+
this: ADB,
|
|
134
|
+
credential: string | null = null,
|
|
135
|
+
): Promise<void> {
|
|
129
136
|
try {
|
|
130
137
|
const {stdout, stderr} = await this.shell(buildCommand('clear', credential), {
|
|
131
138
|
outputFormat: this.EXEC_OUTPUT_FORMAT.FULL,
|
|
@@ -140,7 +147,11 @@ export async function clearLockCredential(credential = null) {
|
|
|
140
147
|
} catch (e) {
|
|
141
148
|
throw new Error(
|
|
142
149
|
`Cannot clear device lock credential. ` +
|
|
143
|
-
`Original error: ${
|
|
150
|
+
`Original error: ${
|
|
151
|
+
(e as Error & {stderr?: string; stdout?: string}).stderr
|
|
152
|
+
|| (e as Error & {stderr?: string; stdout?: string}).stdout
|
|
153
|
+
|| (e as Error).message
|
|
154
|
+
}`,
|
|
144
155
|
);
|
|
145
156
|
}
|
|
146
157
|
}
|
|
@@ -149,11 +160,10 @@ export async function clearLockCredential(credential = null) {
|
|
|
149
160
|
* Checks whether the device is locked with a credential (either pin or a password
|
|
150
161
|
* or a pattern).
|
|
151
162
|
*
|
|
152
|
-
* @
|
|
153
|
-
* @returns {Promise<boolean>} `true` if the device is locked
|
|
163
|
+
* @returns `true` if the device is locked
|
|
154
164
|
* @throws {Error} If operation faces an unexpected error
|
|
155
165
|
*/
|
|
156
|
-
export async function isLockEnabled() {
|
|
166
|
+
export async function isLockEnabled(this: ADB): Promise<boolean> {
|
|
157
167
|
try {
|
|
158
168
|
const {stdout, stderr} = await this.shell(buildCommand('get-disabled'), {
|
|
159
169
|
outputFormat: this.EXEC_OUTPUT_FORMAT.FULL,
|
|
@@ -171,29 +181,33 @@ export async function isLockEnabled() {
|
|
|
171
181
|
}
|
|
172
182
|
throw new Error(stderr || stdout);
|
|
173
183
|
} catch (e) {
|
|
174
|
-
throw new Error(`Cannot check if device lock is enabled. Original error: ${e.message}`);
|
|
184
|
+
throw new Error(`Cannot check if device lock is enabled. Original error: ${(e as Error).message}`);
|
|
175
185
|
}
|
|
176
186
|
}
|
|
177
187
|
|
|
178
188
|
/**
|
|
179
189
|
* Sets the device lock.
|
|
180
190
|
*
|
|
181
|
-
* @
|
|
182
|
-
* @param
|
|
183
|
-
* @param {string} credential A non-empty credential value to be set.
|
|
191
|
+
* @param credentialType - One of: password, pin, pattern.
|
|
192
|
+
* @param credential - A non-empty credential value to be set.
|
|
184
193
|
* Make sure your new credential matches to the actual system security requirements,
|
|
185
194
|
* e.g. a minimum password length. A pattern is specified by a non-separated list
|
|
186
195
|
* of numbers that index the cell on the pattern in a 1-based manner in left
|
|
187
196
|
* to right and top to bottom order, i.e. the top-left cell is indexed with 1,
|
|
188
197
|
* whereas the bottom-right cell is indexed with 9. Example: 1234.
|
|
189
|
-
* @param
|
|
198
|
+
* @param oldCredential - An old credential string.
|
|
190
199
|
* It is only required to be set in case you need to change the current
|
|
191
200
|
* credential rather than to set a new one. Setting it to a wrong value will
|
|
192
201
|
* make this method to fail and throw an exception.
|
|
193
202
|
* @throws {Error} If there was a failure while verifying input arguments or setting
|
|
194
203
|
* the credential
|
|
195
204
|
*/
|
|
196
|
-
export async function setLockCredential(
|
|
205
|
+
export async function setLockCredential(
|
|
206
|
+
this: ADB,
|
|
207
|
+
credentialType: string,
|
|
208
|
+
credential: string,
|
|
209
|
+
oldCredential: string | null = null,
|
|
210
|
+
): Promise<void> {
|
|
197
211
|
if (!SUPPORTED_LOCK_CREDENTIAL_TYPES.includes(credentialType)) {
|
|
198
212
|
throw new Error(
|
|
199
213
|
`Device lock credential type '${credentialType}' is unknown. ` +
|
|
@@ -214,7 +228,11 @@ export async function setLockCredential(credentialType, credential, oldCredentia
|
|
|
214
228
|
} catch (e) {
|
|
215
229
|
throw new Error(
|
|
216
230
|
`Setting of device lock ${credentialType} credential failed. ` +
|
|
217
|
-
`Original error: ${
|
|
231
|
+
`Original error: ${
|
|
232
|
+
(e as Error & {stderr?: string; stdout?: string}).stderr
|
|
233
|
+
|| (e as Error & {stderr?: string; stdout?: string}).stdout
|
|
234
|
+
|| (e as Error).message
|
|
235
|
+
}`,
|
|
218
236
|
);
|
|
219
237
|
}
|
|
220
238
|
}
|
|
@@ -222,10 +240,9 @@ export async function setLockCredential(credentialType, credential, oldCredentia
|
|
|
222
240
|
/**
|
|
223
241
|
* Retrieve the screen lock state of the device under test.
|
|
224
242
|
*
|
|
225
|
-
* @
|
|
226
|
-
* @return {Promise<boolean>} True if the device is locked.
|
|
243
|
+
* @return True if the device is locked.
|
|
227
244
|
*/
|
|
228
|
-
export async function isScreenLocked() {
|
|
245
|
+
export async function isScreenLocked(this: ADB): Promise<boolean> {
|
|
229
246
|
const [windowOutput, powerOutput] = await B.all([
|
|
230
247
|
this.shell(['dumpsys', 'window']),
|
|
231
248
|
this.shell(['dumpsys', 'power']),
|
|
@@ -241,9 +258,8 @@ export async function isScreenLocked() {
|
|
|
241
258
|
|
|
242
259
|
/**
|
|
243
260
|
* Dismisses keyguard overlay.
|
|
244
|
-
* @this {import('../adb.js').ADB}
|
|
245
261
|
*/
|
|
246
|
-
export async function dismissKeyguard() {
|
|
262
|
+
export async function dismissKeyguard(this: ADB): Promise<void> {
|
|
247
263
|
log.info('Waking up the device to dismiss the keyguard');
|
|
248
264
|
// Screen off once to force pre-inputted text field clean after wake-up
|
|
249
265
|
// Just screen on if the screen defaults off
|
|
@@ -273,18 +289,16 @@ export async function dismissKeyguard() {
|
|
|
273
289
|
/**
|
|
274
290
|
* Presses the corresponding key combination to make sure the device's screen
|
|
275
291
|
* is not turned off and is locked if the latter is enabled.
|
|
276
|
-
* @this {import('../adb.js').ADB}
|
|
277
292
|
*/
|
|
278
|
-
export async function cycleWakeUp() {
|
|
293
|
+
export async function cycleWakeUp(this: ADB): Promise<void> {
|
|
279
294
|
await this.keyevent(KEYCODE_POWER);
|
|
280
295
|
await this.keyevent(KEYCODE_WAKEUP);
|
|
281
296
|
}
|
|
282
297
|
|
|
283
298
|
/**
|
|
284
299
|
* Send the special keycode to the device under test in order to lock it.
|
|
285
|
-
* @this {import('../adb.js').ADB}
|
|
286
300
|
*/
|
|
287
|
-
export async function lock() {
|
|
301
|
+
export async function lock(this: ADB): Promise<void> {
|
|
288
302
|
if (await this.isScreenLocked()) {
|
|
289
303
|
log.debug('Screen is already locked. Doing nothing.');
|
|
290
304
|
return;
|
|
@@ -310,10 +324,10 @@ export async function lock() {
|
|
|
310
324
|
* Default is true.
|
|
311
325
|
* Note: this key
|
|
312
326
|
*
|
|
313
|
-
* @param
|
|
314
|
-
* @returns
|
|
327
|
+
* @param dumpsys
|
|
328
|
+
* @returns
|
|
315
329
|
*/
|
|
316
|
-
function isScreenOnFully(dumpsys) {
|
|
330
|
+
function isScreenOnFully(dumpsys: string): boolean {
|
|
317
331
|
const m = /mScreenOnFully=\w+/gi.exec(dumpsys);
|
|
318
332
|
return (
|
|
319
333
|
!m || // if information is missing we assume screen is fully on
|
|
@@ -325,10 +339,10 @@ function isScreenOnFully(dumpsys) {
|
|
|
325
339
|
/**
|
|
326
340
|
* Checks mCurrentFocus in dumpsys output to determine if Keyguard is activated
|
|
327
341
|
*
|
|
328
|
-
* @param
|
|
329
|
-
* @returns
|
|
342
|
+
* @param dumpsys
|
|
343
|
+
* @returns
|
|
330
344
|
*/
|
|
331
|
-
function isCurrentFocusOnKeyguard(dumpsys) {
|
|
345
|
+
function isCurrentFocusOnKeyguard(dumpsys: string): boolean {
|
|
332
346
|
const m = /mCurrentFocus.+Keyguard/gi.exec(dumpsys);
|
|
333
347
|
return Boolean(m?.length && m[0]);
|
|
334
348
|
}
|
|
@@ -336,10 +350,10 @@ function isCurrentFocusOnKeyguard(dumpsys) {
|
|
|
336
350
|
/**
|
|
337
351
|
* Check the current device power state to determine if it is locked
|
|
338
352
|
*
|
|
339
|
-
* @param
|
|
340
|
-
* @returns
|
|
353
|
+
* @param dumpsys The `adb shell dumpsys power` output
|
|
354
|
+
* @returns True if lock screen is shown
|
|
341
355
|
*/
|
|
342
|
-
function isInDozingMode(dumpsys) {
|
|
356
|
+
function isInDozingMode(dumpsys: string): boolean {
|
|
343
357
|
// On some phones/tablets we were observing mWakefulness=Dozing
|
|
344
358
|
// while on others it was getWakefulnessLocked()=Dozing
|
|
345
359
|
return /^[\s\w]+wakefulness[^=]*=Dozing$/im.test(dumpsys);
|
|
@@ -358,10 +372,10 @@ function isInDozingMode(dumpsys) {
|
|
|
358
372
|
* Some devices such as Android TV do not have keyguard, so we should keep
|
|
359
373
|
* screen condition as this primary method.
|
|
360
374
|
*
|
|
361
|
-
* @param
|
|
362
|
-
* @return
|
|
375
|
+
* @param dumpsys - The output of dumpsys window command.
|
|
376
|
+
* @return True if lock screen is showing.
|
|
363
377
|
*/
|
|
364
|
-
export function isShowingLockscreen(dumpsys) {
|
|
378
|
+
export function isShowingLockscreen(dumpsys: string): boolean {
|
|
365
379
|
return (
|
|
366
380
|
_.some(['mShowingLockscreen=true', 'mDreamingLockscreen=true'], (x) => dumpsys.includes(x)) ||
|
|
367
381
|
// `mIsShowing` and `mInputRestricted` are `true` in lock condition. `false` is unlock condition.
|
|
@@ -375,11 +389,12 @@ export function isShowingLockscreen(dumpsys) {
|
|
|
375
389
|
* Checks screenState has SCREEN_STATE_OFF in dumpsys output to determine
|
|
376
390
|
* possible lock screen.
|
|
377
391
|
*
|
|
378
|
-
* @param
|
|
379
|
-
* @return
|
|
392
|
+
* @param dumpsys - The output of dumpsys window command.
|
|
393
|
+
* @return True if lock screen is showing.
|
|
380
394
|
*/
|
|
381
|
-
export function isScreenStateOff(dumpsys) {
|
|
395
|
+
export function isScreenStateOff(dumpsys: string): boolean {
|
|
382
396
|
return /\s+screenState=SCREEN_STATE_OFF/i.test(dumpsys);
|
|
383
397
|
}
|
|
384
398
|
|
|
385
399
|
// #endregion
|
|
400
|
+
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
2
|
import {Logcat} from '../logcat';
|
|
3
|
+
import type {ADB} from '../adb.js';
|
|
4
|
+
import type {LogcatOpts, LogEntry, LogcatListener} from './types.js';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Start the logcat process to gather logs.
|
|
6
8
|
*
|
|
7
|
-
* @
|
|
8
|
-
* @param {import('./types').LogcatOpts} [opts={}]
|
|
9
|
+
* @param opts - Logcat options
|
|
9
10
|
* @throws {Error} If restart fails.
|
|
10
11
|
*/
|
|
11
|
-
export async function startLogcat(opts = {}) {
|
|
12
|
+
export async function startLogcat(this: ADB, opts: LogcatOpts = {}): Promise<void> {
|
|
12
13
|
if (!_.isEmpty(this.logcat)) {
|
|
13
14
|
throw new Error("Trying to start logcat capture but it's already started!");
|
|
14
15
|
}
|
|
@@ -26,14 +27,14 @@ export async function startLogcat(opts = {}) {
|
|
|
26
27
|
/**
|
|
27
28
|
* Stop the active logcat process which gathers logs.
|
|
28
29
|
* The call will be ignored if no logcat process is running.
|
|
29
|
-
* @this {import('../adb.js').ADB}
|
|
30
30
|
*/
|
|
31
|
-
export async function stopLogcat() {
|
|
32
|
-
|
|
31
|
+
export async function stopLogcat(this: ADB): Promise<void> {
|
|
32
|
+
const logcat = this.logcat;
|
|
33
|
+
if (!logcat || _.isEmpty(this.logcat)) {
|
|
33
34
|
return;
|
|
34
35
|
}
|
|
35
36
|
try {
|
|
36
|
-
await
|
|
37
|
+
await logcat.stopCapture();
|
|
37
38
|
} finally {
|
|
38
39
|
this.logcat = undefined;
|
|
39
40
|
}
|
|
@@ -43,43 +44,44 @@ export async function stopLogcat() {
|
|
|
43
44
|
* Retrieve the output from the currently running logcat process.
|
|
44
45
|
* The logcat process should be executed by {2link #startLogcat} method.
|
|
45
46
|
*
|
|
46
|
-
* @
|
|
47
|
-
* @return {import('./types').LogEntry[]} The collected logcat output.
|
|
47
|
+
* @return The collected logcat output.
|
|
48
48
|
* @throws {Error} If logcat process is not running.
|
|
49
49
|
*/
|
|
50
|
-
export function getLogcatLogs() {
|
|
51
|
-
|
|
50
|
+
export function getLogcatLogs(this: ADB): LogEntry[] {
|
|
51
|
+
const logcat = this.logcat;
|
|
52
|
+
if (!logcat || _.isEmpty(this.logcat)) {
|
|
52
53
|
throw new Error(`Can't get logcat logs since logcat hasn't started`);
|
|
53
54
|
}
|
|
54
|
-
return
|
|
55
|
+
return logcat.getLogs();
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
/**
|
|
58
59
|
* Set the callback for the logcat output event.
|
|
59
60
|
*
|
|
60
|
-
* @
|
|
61
|
-
* @param {import('./types').LogcatListener} listener - Listener function
|
|
61
|
+
* @param listener - Listener function
|
|
62
62
|
* @throws {Error} If logcat process is not running.
|
|
63
63
|
*/
|
|
64
|
-
export function setLogcatListener(listener) {
|
|
65
|
-
|
|
64
|
+
export function setLogcatListener(this: ADB, listener: LogcatListener): void {
|
|
65
|
+
const logcat = this.logcat;
|
|
66
|
+
if (!logcat || _.isEmpty(this.logcat)) {
|
|
66
67
|
throw new Error("Logcat process hasn't been started");
|
|
67
68
|
}
|
|
68
|
-
|
|
69
|
+
logcat.on('output', listener);
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
/**
|
|
72
73
|
* Removes the previously set callback for the logcat output event.
|
|
73
74
|
*
|
|
74
|
-
* @
|
|
75
|
-
* @param {import('./types').LogcatListener} listener
|
|
75
|
+
* @param listener
|
|
76
76
|
* The listener function, which has been previously
|
|
77
77
|
* passed to `setLogcatListener`
|
|
78
78
|
* @throws {Error} If logcat process is not running.
|
|
79
79
|
*/
|
|
80
|
-
export function removeLogcatListener(listener) {
|
|
81
|
-
|
|
80
|
+
export function removeLogcatListener(this: ADB, listener: LogcatListener): void {
|
|
81
|
+
const logcat = this.logcat;
|
|
82
|
+
if (!logcat || _.isEmpty(this.logcat)) {
|
|
82
83
|
throw new Error("Logcat process hasn't been started");
|
|
83
84
|
}
|
|
84
|
-
|
|
85
|
+
logcat.removeListener('output', listener);
|
|
85
86
|
}
|
|
87
|
+
|