Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions docs/evidence/android-keep-awake-2026-11-08.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Android keep-awake end-to-end run and the svc-true no-op, 2026-11-08

Evidence for #4290 (keep-awake on and off across Android and HarmonyOS): the
first backend draft lowered `on` to `svc power stayon true`, and a live run
proved that a no-op on real hardware — the command answers and the stored
value never moves when the mask already covers the plugged-in sources. The
shipped backend writes the setting itself and reports the read-back state.

## Device

- Xiaomi Redmi K60 (`2312DRAABC` model code), Android 14 (SDK 34), adb serial
`5p4hqglvpzxshiuw`, USB connected.

## The svc-true no-op (discovered live)

With the user's stored mask at `15`, the draft command changed nothing while
the CLI still acked the write:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The transcript does not substantiate the claimed CLI acknowledgement; it only runs raw ADB commands. Include the draft CLI invocation and its acknowledgement output alongside the device read-back.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At docs/evidence/android-keep-awake-2026-11-08.md, line 17:

<comment>The transcript does not substantiate the claimed CLI acknowledgement; it only runs raw ADB commands. Include the draft CLI invocation and its acknowledgement output alongside the device read-back.</comment>

<file context>
@@ -0,0 +1,57 @@
+## The svc-true no-op (discovered live)
+
+With the user's stored mask at `15`, the draft command changed nothing while
+the CLI still acked the write:
+
+```sh
</file context>


```sh
$ adb -s 5p4hqglvpzxshiuw shell "settings get global stay_on_while_plugged_in"
15
$ adb -s 5p4hqglvpzxshiuw shell "svc power stayon true; settings get global stay_on_while_plugged_in"
15
$ adb -s 5p4hqglvpzxshiuw shell "svc power stayon usb; settings get global stay_on_while_plugged_in"
2
```

`stayon true` does not rewrite a mask that already covers the plugged-in
sources; `stayon usb` rewrites to `2`. A write that skips no-op spellings is
the only reliable form.

## The shipped backend, end to end through the public CLI

Branch build of #4290, one command per state, device state read back with raw

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This live run is not pinned to the source revision it exercised. Record the tested commit SHA so these device results remain attributable to this implementation.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At docs/evidence/android-keep-awake-2026-11-08.md, line 34:

<comment>This live run is not pinned to the source revision it exercised. Record the tested commit SHA so these device results remain attributable to this implementation.</comment>

<file context>
@@ -0,0 +1,57 @@
+
+## The shipped backend, end to end through the public CLI
+
+Branch build of #4290, one command per state, device state read back with raw
+`settings get` between the calls:
+
</file context>

`settings get` between the calls:

```sh
$ node bin/agent-device.mjs settings keep-awake on --platform android --serial 5p4hqglvpzxshiuw
Updated setting: keep-awake
$ adb -s 5p4hqglvpzxshiuw shell "settings get global stay_on_while_plugged_in"
7
$ node bin/agent-device.mjs settings keep-awake off --platform android --serial 5p4hqglvpzxshiuw
Updated setting: keep-awake
$ adb -s 5p4hqglvpzxshiuw shell "settings get global stay_on_while_plugged_in"
0
```

`15 → 7 → 0`. The user's stored mask was restored to `15` after the run. The

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The transcript ends at 0 but only asserts that the user’s mask was later restored to 15. Include the restoration command and its settings get output so reviewers can verify the device was left unchanged.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At docs/evidence/android-keep-awake-2026-11-08.md, line 48:

<comment>The transcript ends at `0` but only asserts that the user’s mask was later restored to `15`. Include the restoration command and its `settings get` output so reviewers can verify the device was left unchanged.</comment>

<file context>
@@ -0,0 +1,57 @@
+0
+```
+
+`15 → 7 → 0`. The user's stored mask was restored to `15` after the run. The
+CLI result carries the read-back state (`stayOnWhilePluggedIn`), so an ack can
+never claim a write the device did not store.
</file context>

CLI result carries the read-back state (`stayOnWhilePluggedIn`), so an ack can
never claim a write the device did not store.

## HarmonyOS note

`power-shell` on JDY-AL50 (7.0.0.111) has no query form: `setmode` spells only

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The HarmonyOS section does not provide a live-run transcript for the JDY-AL50 claim. Add the exact command output and resulting state (including off restoration), or limit this evidence file’s claim to Android.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At docs/evidence/android-keep-awake-2026-11-08.md, line 54:

<comment>The HarmonyOS section does not provide a live-run transcript for the JDY-AL50 claim. Add the exact command output and resulting state (including `off` restoration), or limit this evidence file’s claim to Android.</comment>

<file context>
@@ -0,0 +1,57 @@
+
+## HarmonyOS note
+
+`power-shell` on JDY-AL50 (7.0.0.111) has no query form: `setmode` spells only
+the 600-series modes, `timeout -o <ms>` acks with `Override screen off time to
+2147483647`, and `timeout -r` restores. The harmony backend uses the timeout
</file context>

the 600-series modes, `timeout -o <ms>` acks with `Override screen off time to
2147483647`, and `timeout -r` restores. The harmony backend uses the timeout
override for exactly this reason.
2 changes: 1 addition & 1 deletion packages/command-surface/src/capture/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const settingsCommandMetadata = defineFieldCommandMetadata(
// A readable setting answers with no state; the parse decides per setting.
state: stringField(),
app: stringField(
'App the change targets, by bundle id, package name, or app name: the app `clear-app-state` clears, or the app a `permission` change (or an iOS-simulator `location on|off` privacy change) lands on. A name resolves to the installed app as `open` resolves it: an iOS simulator, local or Limrun, matches display names and accepts only an installed bundle id, and Android accepts only an installed package and refuses a name that resolves to an intent with `setting_app_not_package`. One that resolves to nothing is refused with `app_not_installed` before anything changes. The app need not be running. Without it the session app is used; a device-wide change (`location set` on any target, the Android `location on|off` toggle, `mobile-data`, macOS permissions) refuses one with `setting_app_not_consumed`. The CLI reads it only from this invocation, never from `AGENT_DEVICE_TARGET_APP` or config `targetApp`.',
'App the change targets, by bundle id, package name, or app name: the app `clear-app-state` clears, or the app a `permission` change (or an iOS-simulator `location on|off` privacy change) lands on. A name resolves to the installed app as `open` resolves it: an iOS simulator, local or Limrun, matches display names and accepts only an installed bundle id, and Android accepts only an installed package and refuses a name that resolves to an intent with `setting_app_not_package`. One that resolves to nothing is refused with `app_not_installed` before anything changes. The app need not be running. Without it the session app is used; a device-wide change (`location set` on any target, the Android `location on|off` toggle, `mobile-data`, `keep-awake`, macOS permissions) refuses one with `setting_app_not_consumed`. The CLI reads it only from this invocation, never from `AGENT_DEVICE_TARGET_APP` or config `targetApp`.',
),
latitude: numberField(),
longitude: numberField(),
Expand Down
6 changes: 6 additions & 0 deletions packages/contracts/src/settings-catalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ export const SETTINGS = {
appScope: { mobile: 'device-level' },
help: 'Android only. Runs svc data and reports the stored mobileData state, or fails with mobile-data-not-applied or mobile-data-unreadable. Multi-SIM read-back is not covered yet, and --app is refused.',
},
'keep-awake': {
forms: [{ kind: 'on-off' }],
app: 'input',
appScope: { mobile: 'device-level' },
help: 'Android holds its screen on while the device charges (svc power stayon), so a device on battery can still sleep; the write survives a reboot. HarmonyOS raises its screen-off timeout to the largest value the power tool accepts; a reboot clears that override. off restores the timeout the system setting holds. --app is refused.',
},
location: {
forms: [
{ kind: 'on-off', appScope: { apple: 'app-scoped', mobile: 'device-level' } },
Expand Down
6 changes: 3 additions & 3 deletions packages/contracts/src/settings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ function expectInvalidArgs(run: () => unknown, message: string): void {
describe('settings usage', () => {
test('folds settings that share a form into one line', () => {
expect(SETTINGS_USAGE_OVERRIDE.split(' | ')).toEqual([
'settings <wifi|bluetooth|airplane|mobile-data|location|animations> <on|off>',
'settings <wifi|bluetooth|airplane|mobile-data|keep-awake|location|animations> <on|off>',
'settings location set <lat> <lon>',
'settings appearance <light|dark|toggle>',
`settings text-size [${TEXT_SIZE_CATEGORIES.join('|')}]`,
Expand All @@ -56,7 +56,7 @@ describe('settings usage', () => {

test('the invalid-args message lists the same forms, with the last one as an alternative', () => {
expect(SETTINGS_INVALID_ARGS_MESSAGE).toMatch(
/^settings requires <wifi\|bluetooth\|airplane\|mobile-data\|location\|animations> <on\|off>, .*, or permission <grant\|reset> <accessibility\|screen-recording\|input-monitoring>$/,
/^settings requires <wifi\|bluetooth\|airplane\|mobile-data\|keep-awake\|location\|animations> <on\|off>, .*, or permission <grant\|reset> <accessibility\|screen-recording\|input-monitoring>$/,
);
});

Expand Down Expand Up @@ -240,7 +240,7 @@ describe('settingsAppScope', () => {
});

describe('settingsAppScope device-wide radios', () => {
test.each(['mobile-data', 'bluetooth'])(
test.each(['mobile-data', 'keep-awake', 'bluetooth'])(
'%s switches the whole device wherever it is served',
(setting) => {
expect(settingsAppScope('mobile', setting, 'on')).toBe('device-level');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ function settingsFacts(device: DeviceInfo) {
bluetooth: available,
airplane: available,
'mobile-data': available,
'keep-awake': available,
location: available,
animations: available,
appearance: available,
Expand All @@ -199,7 +200,7 @@ function settingsFacts(device: DeviceInfo) {
return settingsRuntimeOperationFacts({
target: available,
unsupported,
write: { 'clear-app-state': available },
write: { 'clear-app-state': available, 'keep-awake': available },
});
case 'apple':
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,7 @@ test('settings mobile-data reaches the Android owner as an on/off mutation', asy
expect(fixtureSettingsMutations.at(-1)).toMatchObject({ setting: 'mobile-data', state: 'off' });
});

test.each(['mobile-data', 'bluetooth'])(
test.each(['mobile-data', 'keep-awake', 'bluetooth'])(
'settings Android %s refuses a named app before reaching the owner',
async (setting) => {
const sessionStore = makeSessionStore();
Expand Down
39 changes: 39 additions & 0 deletions packages/platform-android/src/__tests__/settings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -652,3 +652,42 @@ test('setAndroidSetting mobile-data stops sampling when the request is cancelled
},
);
});

// --- settings keep-awake: explicit stay-on mask write ---

test('setAndroidSetting keep-awake writes the mask and reports the read-back state', async () => {
for (const { state, value, keepAwake } of [
{ state: 'on', value: '7', keepAwake: 'enabled' },
{ state: 'off', value: '0', keepAwake: 'disabled' },
] as const) {
await withFakeAdb(
(args) => {
const joined = args.join(' ');
if (joined === `shell settings put global stay_on_while_plugged_in ${value}`) return '';
if (joined === 'shell settings get global stay_on_while_plugged_in') return value;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This fixture always reports the requested mask from settings get, so it cannot catch a silently ignored write or a device that retains a different mask. Make the fake stateful and add a refused/mismatched-write case that verifies the returned read-back value or the required failure behavior.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/platform-android/src/__tests__/settings.test.ts, line 667:

<comment>This fixture always reports the requested mask from `settings get`, so it cannot catch a silently ignored write or a device that retains a different mask. Make the fake stateful and add a refused/mismatched-write case that verifies the returned read-back value or the required failure behavior.</comment>

<file context>
@@ -653,18 +653,27 @@ test('setAndroidSetting mobile-data stops sampling when the request is cancelled
+      (args) => {
+        const joined = args.join(' ');
+        if (joined === `shell settings put global stay_on_while_plugged_in ${value}`) return '';
+        if (joined === 'shell settings get global stay_on_while_plugged_in') return value;
+        return undefined;
+      },
</file context>

return undefined;
},
async ({ calls, device }) => {
const result = await setAndroidSetting(device, 'keep-awake', state);
assert.deepEqual(flatCalls(calls), [
`shell settings put global stay_on_while_plugged_in ${value}`,
'shell settings get global stay_on_while_plugged_in',
]);
assert.deepEqual(result, { keepAwake, stayOnWhilePluggedIn: value });
},
);
}
});

test('setAndroidSetting keep-awake runs nothing for a state svc cannot spell', async () => {
await withFakeAdb(
(args) => ({ stderr: `unexpected args: ${args.join(' ')}`, exitCode: 1 }),
async ({ calls, device }) => {
await assertRejectsAppError(() => setAndroidSetting(device, 'keep-awake', 'forever'), {
code: 'INVALID_ARGS',
message: /Invalid setting state: forever/,
});
assert.deepEqual(calls, []);
},
);
});
1 change: 1 addition & 0 deletions packages/platform-android/src/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ export function createAndroidPlatformRuntime(host: PlatformRuntimeHost): Platfor
bluetooth: available,
airplane: available,
'mobile-data': available,
'keep-awake': available,
location: available,
animations: available,
appearance: available,
Expand Down
25 changes: 25 additions & 0 deletions packages/platform-android/src/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export const ANDROID_SETTINGS = [
'bluetooth',
'airplane',
'mobile-data',
'keep-awake',
'location',
'animations',
'appearance',
Expand Down Expand Up @@ -114,6 +115,30 @@ export async function setAndroidSetting(
signal,
);
}
case 'keep-awake': {
// `svc power stayon true` is a no-op when the stored mask already covers the plugged-in
// sources (a device holding 15 answers "Updated" with the value unchanged — verified on
// a Redmi K60, Android 14). The write goes to the setting itself with the explicit
// BATTERY_PLUGGED_ANY mask, and the result carries the read-back state.
const enabled = parseSettingState(state);
await runAndroidShell(device, [
'settings',
'put',
'global',
'stay_on_while_plugged_in',
enabled ? '7' : '0',
]);
const applied = await runAndroidShell(device, [
'settings',
'get',
'global',
'stay_on_while_plugged_in',
]);
return {
keepAwake: enabled ? 'enabled' : 'disabled',
stayOnWhilePluggedIn: applied.stdout.trim(),
};
Comment on lines +137 to +140

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The Android result can report keepAwake: 'enabled' even when the read-back value shows that the device did not apply the write. Compare the read-back with 7/0 and return a typed COMMAND_FAILED for a mismatch, preferably using the same settling behavior as the other Android global toggles.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/platform-android/src/settings.ts, line 137:

<comment>The Android result can report `keepAwake: 'enabled'` even when the read-back value shows that the device did not apply the write. Compare the read-back with `7`/`0` and return a typed `COMMAND_FAILED` for a mismatch, preferably using the same settling behavior as the other Android global toggles.</comment>

<file context>
@@ -116,12 +116,28 @@ export async function setAndroidSetting(
+        'global',
+        'stay_on_while_plugged_in',
+      ]);
+      return {
+        keepAwake: enabled ? 'enabled' : 'disabled',
+        stayOnWhilePluggedIn: applied.stdout.trim(),
</file context>
Suggested change
return {
keepAwake: enabled ? 'enabled' : 'disabled',
stayOnWhilePluggedIn: applied.stdout.trim(),
};
const stayOnWhilePluggedIn = applied.stdout.trim();
const expected = enabled ? '7' : '0';
if (stayOnWhilePluggedIn !== expected) {
throw new AppError(
'COMMAND_FAILED',
`Android keep-awake reads ${stayOnWhilePluggedIn || '(empty)'} after requesting ${expected}.`,
{
deviceId: device.id,
reason: 'keep-awake-not-applied',
requested: expected,
stayOnWhilePluggedIn,
},
);
}
return {
keepAwake: enabled ? 'enabled' : 'disabled',
stayOnWhilePluggedIn,
};

}
case 'location': {
if (state.toLowerCase() === 'set') {
if (device.kind !== 'emulator') {
Expand Down
22 changes: 22 additions & 0 deletions packages/platform-harmonyos/src/__tests__/settings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,28 @@ test('HarmonyOS clear-app-state force stops then clears bundle data and cache',
);
});

test('HarmonyOS keep-awake raises the screen-off timeout and off restores the system value', async () => {
assert.deepEqual(await setHarmonySetting(device, 'keep-awake', 'on'), { keepAwake: 'enabled' });
assert.deepEqual(await setHarmonySetting(device, 'keep-awake', 'OFF'), {
keepAwake: 'disabled',
});
assert.deepEqual(
mockRunHarmonyShell.mock.calls.map((call) => call[1]),
[
['power-shell', 'timeout', '-o', '2147483647'],
['power-shell', 'timeout', '-r'],
],
);
});

test('HarmonyOS keep-awake runs nothing for a state the tool cannot spell', async () => {
await assert.rejects(
async () => await setHarmonySetting(device, 'keep-awake', 'always'),
/Invalid setting state: always/,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Assert the typed error code here, not only its message, so this test proves invalid states are rejected through the INVALID_ARGS contract.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/platform-harmonyos/src/__tests__/settings.test.ts, line 63:

<comment>Assert the typed error code here, not only its message, so this test proves invalid states are rejected through the `INVALID_ARGS` contract.</comment>

<file context>
@@ -43,6 +43,28 @@ test('HarmonyOS clear-app-state force stops then clears bundle data and cache',
+test('HarmonyOS keep-awake runs nothing for a state the tool cannot spell', async () => {
+  await assert.rejects(
+    async () => await setHarmonySetting(device, 'keep-awake', 'always'),
+    /Invalid setting state: always/,
+  );
+  assert.deepEqual(mockRunHarmonyShell.mock.calls, []);
</file context>
Suggested change
/Invalid setting state: always/,
(error: unknown) =>
error instanceof AppError &&
error.code === 'INVALID_ARGS' &&
error.message === 'Invalid setting state: always',

);
assert.deepEqual(mockRunHarmonyShell.mock.calls, []);
});

test('HarmonyOS settings rejects unsupported setting and missing app bundle', async () => {
await assert.rejects(async () => await setHarmonySetting(device, 'wifi', 'on'), /not supported/);
await assert.rejects(
Expand Down
1 change: 1 addition & 0 deletions packages/platform-harmonyos/src/runtime.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ test.each([
expect(binding.operations[operation]).toBeUndefined();
}
expect(runtimeSubjectFact(facts.operations.setSetting, 'clear-app-state').available).toBe(true);
expect(runtimeSubjectFact(facts.operations.setSetting, 'keep-awake').available).toBe(true);
expect(runtimeSubjectFact(facts.operations.setSetting, 'wifi').available).toBe(false);
expect(binding.operations.setSetting).toBeTypeOf('function');
await expect(binding.operations.ensureReady?.({})).resolves.toMatchObject({ booted: true });
Expand Down
4 changes: 2 additions & 2 deletions packages/platform-harmonyos/src/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ function harmonyFocusFact(device: DeviceInfo): RuntimeOperationFact {
const harmonyPlatformLeafUnavailable = unavailableFact('unsupported-platform-leaf');
const harmonySettingUnavailable = unavailableFact(
'unsupported-platform-leaf',
'HarmonyOS supports settings clear-app-state only.',
'HarmonyOS supports settings clear-app-state and keep-awake only.',
);

/** Android's live IME status read has no HarmonyOS counterpart (parity with the retired leaf,
Expand Down Expand Up @@ -258,7 +258,7 @@ export function createHarmonyPlatformRuntime(host: PlatformRuntimeHost): Platfor
...settingsRuntimeOperationFacts({
target: harmonyFocusFact(device),
unsupported: harmonySettingUnavailable,
write: { 'clear-app-state': available },
write: { 'clear-app-state': available, 'keep-awake': available },
}),
// HarmonyOS exposes no alert automation operation.
...alertRuntimeOperationFacts({
Expand Down
22 changes: 21 additions & 1 deletion packages/platform-harmonyos/src/settings.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,36 @@
import type { DeviceInfo } from '@agent-device/kernel/device';
import { AppError, sessionAppRequiredDetails } from '@agent-device/kernel/errors';
import { parseSettingState } from '@agent-device/contracts/settings';
import { runHarmonyShell } from './hdc.ts';

/**
* The screen-off timeout `power-shell timeout -o` accepts at its largest: the 32-bit maximum, in
* milliseconds. `off` restores the timeout the system setting holds (`power-shell timeout -r`).
* `power-shell setmode` spells only the 600-series power modes, so `timeout -o` is the route that
* takes this raw millisecond value.
*/
const HARMONY_KEEP_AWAKE_TIMEOUT_MS = '2147483647';

export async function setHarmonySetting(
device: DeviceInfo,
setting: string,
state: string,
appBundleId?: string,
): Promise<Record<string, unknown>> {
if (setting === 'keep-awake') {
const enabled = parseSettingState(state);
await runHarmonyShell(
device,
enabled
? ['power-shell', 'timeout', '-o', HARMONY_KEEP_AWAKE_TIMEOUT_MS]
: ['power-shell', 'timeout', '-r'],
{ timeoutMs: 15_000 },
);
return { keepAwake: enabled ? 'enabled' : 'disabled' };
}
if (setting !== 'clear-app-state') {
throw new AppError('UNSUPPORTED_OPERATION', `HarmonyOS setting "${setting}" is not supported`, {
hint: 'HarmonyOS currently supports settings clear-app-state for an app bundle only.',
hint: 'HarmonyOS currently supports settings clear-app-state and keep-awake only.',
});
}
if (state !== 'clear') {
Expand Down
1 change: 1 addition & 0 deletions packages/provider-limrun/src/interaction-operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ export function limrunAndroidSettingsFacts(
bluetooth: available,
airplane: available,
'mobile-data': available,
'keep-awake': available,
location: available,
animations: available,
appearance: available,
Expand Down
Loading