feat(launcher,lock): 锁屏补充三定案—面板一次性解锁恢复口 / 设置页 PIN 管理 / 电源菜单主动锁强化
- 面板一次性解锁恢复口:/tmp/meow_pin_unlock_once 存在即被锁屏页消费删除并放行一次 (不校验 PIN、不清 system.pin、不重置失败计数;重启标志自然消失;lck_unlock_once_consume, launcher 侧只做检查/消费,panel 端点由主会话另实现)。 - 系统设置「安全 → 锁屏 PIN」页(lock_settings.c,subpage.c 脚手架):状态(未设置/已设置/ 锁定中+剩余)/ 设置(4 位双输确认)/ 修改(需旧 PIN 一次)/ 清除(**免旧 PIN**,仅二次确认弹窗) / system.pin_lock_on_wake 开关;数字输入用 SDK 按钮键盘(lck_input_pin_modal)。 - 电源菜单「锁定」主动锁强化:立即熄屏 + 写 /tmp/meow_pin_locked(主动锁标志,重启消失, 唤醒时无论 pin_lock_on_wake 是否开都必锁屏)+ rm /tmp/meow_pin_unlock_once 作废挂起绕过; lck_wake_should_lock() 作为唤醒门取代 lck_lock_required(1)(主菜单 2 处 + App 会话 2 处)。 - 测试:test_lock_screen 扩 51 ok——bypass 存在即消费/不存在不影响/消费后删除;清除免旧 PIN; 主动锁标志唤醒必锁/清除后回退;全回归 settings_brightness/notif_panel/notif_tf/vol_ramp_jack 无碍; 交叉 -Wall -Wextra 0 warning。meow_launcherd md5 bdf884756ef8a8353aa8e5dfb6e10a0a。 - SYSTEM_SETTINGS.md 同步锁屏行为段。
This commit is contained in:
1 parent
e948a0a44e
commit
c3abc3fee4
13 files changed
+409
-10
No files matched your search
@@ -1957,7 +1957,7 @@ static int launch_app_chain(struct app *a, const char *chain)
|
||||
meow_auto_slept = 0;
|
||||
fb_pan_buf0_force();
|
||||
/* M2.x 锁屏:App 前台唤醒后若需锁屏 → SIGSTOP 叠加锁屏页;解锁/SIGCONT 回应用 */
|
||||
if (lck_lock_required(1)) run_app_lock_overlay(a, pid);
|
||||
if (lck_wake_should_lock()) run_app_lock_overlay(a, pid);
|
||||
}
|
||||
}
|
||||
if (screen_off_timeout > 0 && meow_screen_on && !meow_auto_slept && !fg_keep_awake()) {
|
||||
@@ -1981,7 +1981,7 @@ static int launch_app_chain(struct app *a, const char *chain)
|
||||
meow_auto_slept = 0;
|
||||
fb_pan_buf0_force();
|
||||
/* M2.x 锁屏:App 前台唤醒后若需锁屏 → SIGSTOP 叠加锁屏页;解锁/SIGCONT 回应用 */
|
||||
if (lck_lock_required(1)) run_app_lock_overlay(a, pid);
|
||||
if (lck_wake_should_lock()) run_app_lock_overlay(a, pid);
|
||||
}
|
||||
}
|
||||
if (vold && !app_prev_vold) {
|
||||
|
||||
@@ -28,7 +28,7 @@ SYSROOT="$ROOT/.tools/mipsel-linux-muslsf-cross/mipsel-linux-muslsf"
|
||||
subpage.c wifi_page.c bt_page.c netmgr_ipc.c now_playing.c \
|
||||
font_theme.c keys.c util.c meow_dep.c \
|
||||
meow_touch.c meow_settings.c meow_notif.c meow_media.c meow_bgplay.c \
|
||||
meow_ams_start.c lock_screen.c lock_screen_ui.c \
|
||||
meow_ams_start.c lock_screen.c lock_screen_ui.c lock_settings.c \
|
||||
"../sdk/meow_ui.a" "$SYSROOT/lib/libz.a" -lpthread -o meow_launcherd
|
||||
echo "== meow_launcherd =="
|
||||
ls -la meow_launcherd
|
||||
|
||||
@@ -351,3 +351,39 @@ time_t lck_lock_remaining(void)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---- 面板一次性解锁恢复口(tmpfs 标志)---- */
|
||||
int lck_unlock_once_consume(void)
|
||||
{
|
||||
if (access(LCK_UNLOCK_ONCE_FILE, F_OK) != 0) return 0; /* 不存在:不影响 */
|
||||
unlink(LCK_UNLOCK_ONCE_FILE);
|
||||
LCK_LOG("unlock-once: bypass file present -> consume + release once\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lck_manual_lock_set(void)
|
||||
{
|
||||
int fd = open(LCK_MANUAL_LOCK_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (fd < 0) { LCK_LOG("manual-lock: open %s fail\n", LCK_MANUAL_LOCK_FILE); return MEOW_ERR_IO; }
|
||||
write(fd, "1", 1); close(fd);
|
||||
LCK_LOG("manual-lock: set %s\n", LCK_MANUAL_LOCK_FILE);
|
||||
return MEOW_OK;
|
||||
}
|
||||
|
||||
void lck_manual_lock_clear(void)
|
||||
{
|
||||
if (access(LCK_MANUAL_LOCK_FILE, F_OK) == 0) {
|
||||
unlink(LCK_MANUAL_LOCK_FILE);
|
||||
LCK_LOG("manual-lock: cleared\n");
|
||||
}
|
||||
}
|
||||
|
||||
int lck_wake_should_lock(void)
|
||||
{
|
||||
if (!lck_pin_configured()) return 0;
|
||||
int wake = 1;
|
||||
if (meow_settings_get_int(LCK_KEY_WAKE, &wake) != 0) wake = 1;
|
||||
if (wake) return 1;
|
||||
/* 唤醒锁已关,但存在「主动锁」标志(电源菜单「锁定」)→ 仍必锁屏 */
|
||||
return access(LCK_MANUAL_LOCK_FILE, F_OK) == 0;
|
||||
}
|
||||
@@ -38,6 +38,10 @@ extern "C" {
|
||||
#define LCK_KEY_FAILS "system.pin_fails"
|
||||
#define LCK_KEY_PANEL_PIN "panel.pin" /* 面板 PIN(read-only 兼容源) */
|
||||
|
||||
/* ---- 文件标志(tmpfs,重启自然消失)---- */
|
||||
#define LCK_UNLOCK_ONCE_FILE "/tmp/meow_pin_unlock_once" /* 面板一次性解锁恢复口:存在即消费放行 */
|
||||
#define LCK_MANUAL_LOCK_FILE "/tmp/meow_pin_locked" /* 电源菜单「锁定」主动锁标志:唤醒必锁屏 */
|
||||
|
||||
/* PIN 合法:恰好 4 位数字(0-9)。NULL/长度不符/含非数字 → 0。 */
|
||||
int lck_pin_valid(const char *pin);
|
||||
|
||||
@@ -70,6 +74,20 @@ int lck_pin_fail(void);
|
||||
/* 剩余锁定秒(0=未锁定)。若截止已过,自动清锁定戳+计数并落盘(进程内已解禁)。 */
|
||||
time_t lck_lock_remaining(void);
|
||||
|
||||
/* ---- 面板一次性解锁恢复口(tmpfs 标志文件)----
|
||||
* 锁屏页进入时 / 每次重试前调用:LCK_UNLOCK_ONCE_FILE 存在 → **删除并返回 1(放行进入系统一次)**;
|
||||
* 不存在 → 0。不校验 PIN、不清除 system.pin 本身、不重置失败计数(重启标志自然消失)。 */
|
||||
int lck_unlock_once_consume(void);
|
||||
|
||||
/* ---- 电源菜单「锁定」主动锁标志(tmpfs,重启消失)----
|
||||
* 主动锁屏:写 LCK_MANUAL_LOCK_FILE → 之后唤醒 `lck_wake_should_lock()` 无论 system.pin_lock_on_wake
|
||||
* 是否开都必走锁屏;解锁(PIN 或面板绕过)时清除。 */
|
||||
int lck_manual_lock_set(void); /* 写标志;返回 MEOW_OK */
|
||||
void lck_manual_lock_clear(void); /* 删标志(幂等) */
|
||||
/* 唤醒是否应锁屏:已配凭据 且 (system.pin_lock_on_wake=1 或 主动锁标志存在)。
|
||||
* 取代 lck_lock_required(1) 作为唤醒门——主动锁强制锁屏,覆盖「关闭唤醒锁」的手动锁场景。 */
|
||||
int lck_wake_should_lock(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -134,6 +134,13 @@ int run_lock_screen(void)
|
||||
}
|
||||
time_t last_countdown = 0;
|
||||
|
||||
/* 面板一次性解锁恢复口:进入时消费(存在即删除+放行一次,不校验 PIN/不清 PIN/不重置失败计数) */
|
||||
if (lck_unlock_once_consume()) {
|
||||
lck_manual_lock_clear(); /* 进入系统即视为解除主动锁 */
|
||||
logmsg("lock: unlock-once bypass consumed at entry -> release");
|
||||
return 1;
|
||||
}
|
||||
|
||||
lk_draw(entered, status, lock_until); /* 首帧 */
|
||||
|
||||
int unlocked = 0;
|
||||
@@ -141,6 +148,14 @@ int run_lock_screen(void)
|
||||
time_t now = time(NULL);
|
||||
int redraw = 0;
|
||||
|
||||
/* 面板一次性解锁恢复口:锁屏页停留期(每次重试前/每轮)也消费 */
|
||||
if (lck_unlock_once_consume()) {
|
||||
lck_manual_lock_clear();
|
||||
logmsg("lock: unlock-once bypass consumed in-loop -> release");
|
||||
unlocked = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* 锁定到期自动解禁(清计数+戳),仅重画状态行 */
|
||||
if (lock_until > 0 && now >= lock_until) {
|
||||
lck_lock_remaining();
|
||||
@@ -209,6 +224,7 @@ int run_lock_screen(void)
|
||||
if (entered == LCK_PIN_LEN) {
|
||||
if (lck_pin_check(digits)) {
|
||||
lck_pin_success();
|
||||
lck_manual_lock_clear(); /* 主动锁标志消解 */
|
||||
logmsg("lock: PIN OK -> unlock");
|
||||
unlocked = 1;
|
||||
goto done;
|
||||
@@ -246,13 +262,135 @@ done:
|
||||
return unlocked;
|
||||
}
|
||||
|
||||
/* 电源菜单「锁定」/ 唤醒共用的进入点。未配凭据 → no-op(无鉴别物,锁了也解不开)。
|
||||
* 返回与 run_lock_screen 同(1 已解锁 / 0 电源息屏 / 0 无凭据跳过)。 */
|
||||
/* 电源菜单「锁定」:**主动锁屏**(用户定案 2026-09-02 强化)。
|
||||
* 语义 = 立即熄屏 + 进入锁定 + 作废挂起的面板绕过标志:
|
||||
* ① rm /tmp/meow_pin_unlock_once(主动锁屏作废一次性绕过);
|
||||
* ② 写 /tmp/meow_pin_locked(主动锁标志 → 唤醒时无论 system.pin_lock_on_wake 是否开都必锁屏);
|
||||
* ③ meow_panel_off() 立即熄屏(唤醒时经主屏唤醒路径弹锁屏页)。
|
||||
* 不立即弹锁屏页(已熄屏);未配凭据 → no-op。返回 0(关菜单,run_menu 继续)。 */
|
||||
int meow_lock_screen_engage(void)
|
||||
{
|
||||
if (!lck_pin_configured()) {
|
||||
logmsg("lock: no system.pin/panel.pin configured -> skip lock (no-op)");
|
||||
logmsg("lock: no system.pin/panel.pin configured -> skip manual lock (no-op)");
|
||||
return 0;
|
||||
}
|
||||
return run_lock_screen();
|
||||
if (access(LCK_UNLOCK_ONCE_FILE, F_OK) == 0) {
|
||||
unlink(LCK_UNLOCK_ONCE_FILE);
|
||||
logmsg("lock: manual active-lock revoked pending unlock-once bypass");
|
||||
}
|
||||
lck_manual_lock_set();
|
||||
meow_panel_off(); /* 立即熄屏;唤醒时必走锁屏 */
|
||||
logmsg("lock: manual active-lock -> screen off + lock on wake");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---- 设置页「锁屏 PIN」数字输入模态(system 级 PIN 设置,用 SDK 按钮画数字键盘)----
|
||||
* 全屏遮罩:title + 4 圆点(●)+ 数字键盘(1-9 / C / 0 / 退格)。输入满 4 位即返回 1 并拷贝到 out
|
||||
* (不校验——调用方做双输确认/旧 PIN 校验);电源键=取消返回 0;音量键不动。 */
|
||||
int lck_input_pin_modal(const char *title, char *out, int outcap)
|
||||
{
|
||||
meow_screen_on = 1;
|
||||
fb_pan_buf0_force();
|
||||
meow_touch mt; mt_reset(&mt);
|
||||
int tfd = open(DEV_TOUCH, O_RDONLY | O_NONBLOCK);
|
||||
struct keypoll kp_power, kp_keys;
|
||||
kp_open(&kp_power, DEV_POWER);
|
||||
kp_open(&kp_keys, DEV_KEYS);
|
||||
|
||||
int entered = 0;
|
||||
char digits[LCK_PIN_LEN + 1] = {0};
|
||||
int result = 0;
|
||||
int dirty = 1; /* 首帧必画 */
|
||||
|
||||
for (;;) {
|
||||
/* 只在首帧/输入变化时整页重绘(消频闪:锁屏低频交互),后续轮次不动 LCDC */
|
||||
if (dirty) {
|
||||
const meow_ui_theme_t *th = s_ui_theme();
|
||||
fill_rect(0, 0, fb_xres, fb_yres, th->surface);
|
||||
lk_text(fb_xres / 2, 120, title, 24, th->on_surface);
|
||||
lk_draw_pin(entered, th);
|
||||
for (int r = 0; r < LK_ROWS; r++) {
|
||||
for (int c = 0; c < LK_COLS; c++) {
|
||||
int x, y, w, h; lk_key_rect(r, c, &x, &y, &w, &h);
|
||||
fill_round_rect(x, y, w, h, 12, th->surface_container);
|
||||
int key = lk_keys[r][c];
|
||||
if (key >= 0) {
|
||||
char d[2] = { (char)('0' + key), 0 };
|
||||
if (mfont_ready) {
|
||||
int fw = meow_font_width_text(d, 30);
|
||||
meow_font_drawtext((uint16_t *)fb, x + w / 2 - fw / 2,
|
||||
y + LK_ROW_H / 2 - meow_font_line_height(30) / 2,
|
||||
d, rgb565(th->on_surface), 30);
|
||||
} else {
|
||||
draw_text(x + w / 2 - 7, y + LK_ROW_H / 2 - 14, d, 2, th->on_surface);
|
||||
}
|
||||
} else if (key == LK_ACT_CLR) {
|
||||
const char *t2 = "C"; if (mfont_ready) t2 = "清空";
|
||||
lk_text(x + w / 2, y + LK_ROW_H / 2 - 9, t2, 22, th->on_surface);
|
||||
} else {
|
||||
const char *t2 = "DEL"; if (mfont_ready) t2 = "退格";
|
||||
lk_text(x + w / 2, y + LK_ROW_H / 2 - 9, t2, 22, th->on_surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
meow_dirty_full();
|
||||
fb_pan_buf0_force();
|
||||
meow_ui_flush();
|
||||
dirty = 0;
|
||||
}
|
||||
|
||||
if (kp_power.ok) {
|
||||
kp_poll(&kp_power, NULL, NULL);
|
||||
if (kp_is_down(&kp_power, KEY_POWER)) { result = 0; break; } /* 取消 */
|
||||
}
|
||||
kp_poll(&kp_keys, NULL, NULL);
|
||||
(void)kp_is_down(&kp_keys, KEY_VOLUMEDOWN);
|
||||
(void)kp_is_down(&kp_keys, KEY_VOLUMEUP);
|
||||
|
||||
if (tfd >= 0) {
|
||||
struct pollfd pfd = { tfd, POLLIN, 0 };
|
||||
if (poll(&pfd, 1, 0) > 0) {
|
||||
unsigned char ev[16];
|
||||
while (read(tfd, ev, sizeof ev) == (ssize_t)sizeof ev) {
|
||||
uint16_t type = *(uint16_t *)(ev + 8), code = *(uint16_t *)(ev + 10);
|
||||
int32_t val = *(int32_t *)(ev + 12);
|
||||
if (type == EV_ABS) {
|
||||
if (code == ABS_X || code == ABS_MT_POSITION_X) mt_abs(&mt, val, mt.last_y);
|
||||
else if (code == ABS_Y || code == ABS_MT_POSITION_Y) mt_abs(&mt, mt.last_x, val);
|
||||
} else if (type == EV_KEY && code == BTN_TOUCH) {
|
||||
if (val && !mt.down) { mt_down(&mt); }
|
||||
else if (!val && mt.down) {
|
||||
int dx, dy;
|
||||
if (mt_up(&mt, &dx, &dy)) {
|
||||
for (int r = 0; r < LK_ROWS; r++) {
|
||||
for (int c = 0; c < LK_COLS; c++) {
|
||||
int x, y, w, h; lk_key_rect(r, c, &x, &y, &w, &h);
|
||||
if (!mt_in(&mt, x, y, w, h)) continue;
|
||||
int key = lk_keys[r][c];
|
||||
if (key >= 0) {
|
||||
if (entered < LCK_PIN_LEN) { digits[entered++] = (char)('0' + key); digits[entered] = 0; }
|
||||
} else if (key == LK_ACT_CLR) { entered = 0; digits[0] = 0; }
|
||||
else if (key == LK_ACT_BS) { if (entered > 0) { entered--; digits[entered] = 0; } }
|
||||
dirty = 1;
|
||||
if (entered == LCK_PIN_LEN) {
|
||||
if (out && outcap > LCK_PIN_LEN) { snprintf(out, (size_t)outcap, "%s", digits); result = 1; }
|
||||
else result = 1;
|
||||
goto done2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
usleep(POLL_MS * 1000);
|
||||
}
|
||||
done2:
|
||||
if (tfd >= 0) close(tfd);
|
||||
kp_close(&kp_power);
|
||||
kp_close(&kp_keys);
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/* lock_settings.c — MeowOS 系统设置「锁屏 PIN」独立子页面(subpage.c 脚手架,用户定案 2026-09-02)。
|
||||
*
|
||||
* 页面(sub_page_t 驱动,同 wifi_page/bt_page):
|
||||
* - 状态行(SUB_ROW):未设置 / 已设置 / 锁定中(剩余 mm:ss)
|
||||
* - [未设] 设置 PIN:4 位数字双输入确认(lck_input_pin_modal,SDK 数字键)
|
||||
* - [已设] 修改 PIN:需旧 PIN 一次校验 + 新 PIN 双输入确认
|
||||
* - [已设] 清除 PIN:**无需旧密码**(物理持机即授权,仅 s_dd_modal 二次确认)→ lck_pin_clear
|
||||
* - 唤醒后锁屏(system.pin_lock_on_wake)开关行
|
||||
* 全程走 lock_screen.c 纯逻辑 + meow_settings 后端(无旁路)。
|
||||
*/
|
||||
#include "meow_launcher_internal.h"
|
||||
|
||||
#define LS_ACT_STATUS 0
|
||||
#define LS_ACT_SET 1
|
||||
#define LS_ACT_MODIFY 2
|
||||
#define LS_ACT_CLEAR 3
|
||||
#define LS_ACT_WAKE 4
|
||||
|
||||
static char g_ls_status[48]; /* 状态行摘要(rows 填,paint 后不再变) */
|
||||
|
||||
static void ls_status_text(char *buf, int len)
|
||||
{
|
||||
if (!lck_pin_configured()) { snprintf(buf, len, "未设置"); return; }
|
||||
time_t rem = lck_lock_remaining();
|
||||
if (rem > 0) snprintf(buf, len, "锁定中(%d:%02d)", (int)(rem / 60), (int)(rem % 60));
|
||||
else snprintf(buf, len, "已设置");
|
||||
}
|
||||
|
||||
static int ls_rows(void *ctx, sub_row_t *rbuf, int max)
|
||||
{
|
||||
(void)ctx;
|
||||
int n = 0;
|
||||
if (n < max) { rbuf[n].kind = SUB_HDR; rbuf[n].label = "锁屏 PIN"; rbuf[n].sub = NULL; rbuf[n].on = 0; rbuf[n].act = 0; n++; }
|
||||
ls_status_text(g_ls_status, sizeof g_ls_status);
|
||||
if (n < max) { rbuf[n].kind = SUB_ROW; rbuf[n].label = "状态"; rbuf[n].sub = g_ls_status; rbuf[n].on = 0; rbuf[n].act = LS_ACT_STATUS; n++; }
|
||||
int configured = lck_pin_configured();
|
||||
if (!configured) {
|
||||
if (n < max) { rbuf[n].kind = SUB_ACT; rbuf[n].label = "设置 PIN"; rbuf[n].sub = NULL; rbuf[n].on = 0; rbuf[n].act = LS_ACT_SET; n++; }
|
||||
} else {
|
||||
if (n < max) { rbuf[n].kind = SUB_ACT; rbuf[n].label = "修改 PIN"; rbuf[n].sub = NULL; rbuf[n].on = 0; rbuf[n].act = LS_ACT_MODIFY; n++; }
|
||||
if (n < max) { rbuf[n].kind = SUB_ACT; rbuf[n].label = "清除 PIN"; rbuf[n].sub = NULL; rbuf[n].on = 0; rbuf[n].act = LS_ACT_CLEAR; n++; }
|
||||
}
|
||||
if (n < max) {
|
||||
int wake = 1;
|
||||
if (meow_settings_get_int("system.pin_lock_on_wake", &wake) != 0) wake = 1;
|
||||
rbuf[n].kind = SUB_SW; rbuf[n].label = "唤醒后锁屏"; rbuf[n].sub = NULL;
|
||||
rbuf[n].on = wake; rbuf[n].act = LS_ACT_WAKE; n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static void ls_modal(const char *title, const char *line)
|
||||
{
|
||||
const char *it[1]; it[0] = line;
|
||||
s_dd_modal(title, it, 1, -1);
|
||||
}
|
||||
|
||||
static int ls_do_modify(void)
|
||||
{
|
||||
char old[LCK_PIN_LEN + 1];
|
||||
if (!lck_input_pin_modal("输入当前 PIN", old, sizeof old)) return 0;
|
||||
if (!lck_pin_check(old)) { ls_modal("修改 PIN", "当前 PIN 错误"); return 1; }
|
||||
char a[LCK_PIN_LEN + 1], b[LCK_PIN_LEN + 1];
|
||||
if (!lck_input_pin_modal("设置新 PIN", a, sizeof a)) return 0;
|
||||
if (!lck_input_pin_modal("再次确认新 PIN", b, sizeof b)) return 0;
|
||||
if (strcmp(a, b) != 0) { ls_modal("修改 PIN", "两次输入不一致"); return 1; }
|
||||
if (lck_pin_set(a) == MEOW_OK) ls_modal("修改 PIN", "已修改");
|
||||
else ls_modal("修改 PIN", "设置失败");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ls_do_set(void)
|
||||
{
|
||||
char a[LCK_PIN_LEN + 1], b[LCK_PIN_LEN + 1];
|
||||
if (!lck_input_pin_modal("设置 4 位 PIN", a, sizeof a)) return 0;
|
||||
if (!lck_input_pin_modal("再次输入确认", b, sizeof b)) return 0;
|
||||
if (strcmp(a, b) != 0) { ls_modal("设置 PIN", "两次输入不一致"); return 1; }
|
||||
if (lck_pin_set(a) == MEOW_OK) ls_modal("设置 PIN", "已设置");
|
||||
else ls_modal("设置 PIN", "设置失败");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ls_do_clear(void)
|
||||
{
|
||||
const char *items[2]; items[0] = "是"; items[1] = "否";
|
||||
int pick = s_dd_modal("确定清除锁屏 PIN?", items, 2, 1); /* 默认「否」(安全) */
|
||||
if (pick != 0) return 1;
|
||||
if (lck_pin_clear() == MEOW_OK) ls_modal("清除 PIN", "已清除");
|
||||
else ls_modal("清除 PIN", "清除失败(settings 不可写)");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ls_act(void *ctx, int idx, int act)
|
||||
{
|
||||
(void)ctx; (void)idx;
|
||||
switch (act) {
|
||||
case LS_ACT_SET: return ls_do_set();
|
||||
case LS_ACT_MODIFY: return ls_do_modify();
|
||||
case LS_ACT_CLEAR: return ls_do_clear();
|
||||
case LS_ACT_WAKE: {
|
||||
int v = 1;
|
||||
if (meow_settings_get_int("system.pin_lock_on_wake", &v) != 0) v = 1;
|
||||
meow_settings_set_int("system.pin_lock_on_wake", v ? 0 : 1);
|
||||
meow_settings_save();
|
||||
logmsg("lock_settings: wake-lock toggle -> %d", v ? 0 : 1);
|
||||
return 1; /* 重绘 + 重填行(开关态) */
|
||||
}
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int ls_detail(void *ctx, int idx, int act)
|
||||
{
|
||||
(void)ctx; (void)idx;
|
||||
if (act == LS_ACT_STATUS) {
|
||||
char line[80];
|
||||
ls_status_text(line, sizeof line);
|
||||
int rem = (int)lck_lock_remaining();
|
||||
if (lck_pin_configured() && rem > 0) {
|
||||
char buff[96];
|
||||
snprintf(buff, sizeof buff, "连续错误已锁定,剩余 %d:%02d 后重试", rem / 60, rem % 60);
|
||||
ls_modal("锁屏 PIN", buff);
|
||||
} else {
|
||||
ls_modal("锁屏 PIN", line);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 运行「锁屏 PIN」独立子页面(阻塞到返回) */
|
||||
int run_lock_settings_page(void)
|
||||
{
|
||||
sub_page_t p;
|
||||
memset(&p, 0, sizeof p);
|
||||
p.title = "锁屏 PIN";
|
||||
p.top_sw = NULL;
|
||||
p.top_sw_set = NULL;
|
||||
p.rows = ls_rows;
|
||||
p.act = ls_act;
|
||||
p.detail = ls_detail;
|
||||
p.live = 0;
|
||||
p.ctx = NULL;
|
||||
return meow_subpage_run(&p);
|
||||
}
|
||||
@@ -1146,7 +1146,7 @@ static void run_menu(struct app apps[MAX_APPS], int napps, int state,
|
||||
* 先弹阻塞式锁屏页;解锁才重绘主屏,息屏则留 dirty 下次再锁。 */
|
||||
meow_auto_slept = 0; /* M2.17:手动/自动息屏后电源单击唤醒均清自动态 */
|
||||
last_input_ms = now_ms(); /* M2.18 Bug 1:用真实墙钟(防 t 过期回绕) */
|
||||
if (lck_lock_required(1)) {
|
||||
if (lck_wake_should_lock()) {
|
||||
int lr = run_lock_screen();
|
||||
/* 重播按键防抖基线(阻塞期间按键可能已变化,防误判新边沿) */
|
||||
memset(&kd_pwr, 0, sizeof kd_pwr);
|
||||
@@ -1553,7 +1553,7 @@ static void run_menu(struct app apps[MAX_APPS], int napps, int state,
|
||||
meow_auto_slept = 0;
|
||||
last_input_ms = now_ms();
|
||||
/* M2.x 锁屏:自动息屏唤醒后若需锁屏 → 弹阻塞式锁屏页;解锁才重绘,息屏留 dirty */
|
||||
if (lck_lock_required(1)) {
|
||||
if (lck_wake_should_lock()) {
|
||||
int lr = run_lock_screen();
|
||||
memset(&kd_pwr, 0, sizeof kd_pwr);
|
||||
memset(&kd_vold, 0, sizeof kd_vold);
|
||||
|
||||
@@ -190,6 +190,7 @@ extern "C" {
|
||||
#define NET_LIST_ABOUT 6 /* 系统设置「关于本机」:只读设备信息弹窗(复用 s_dd_modal) */
|
||||
#define NET_LIST_WIFI_PAGE 7 /* M2.76:WiFi 独立子页面入口(tap → run_wifi_page) */
|
||||
#define NET_LIST_BT_PAGE 8 /* M2.76:蓝牙独立子页面入口(tap → run_bt_page) */
|
||||
#define NET_LIST_PIN_PAGE 9 /* M6.x:锁屏 PIN 独立子页面入口(tap → run_lock_settings_page) */
|
||||
#define S_NET_MAX 8 /* 网络下拉一次最多展示项(屏幕高度限制) */
|
||||
#define BG_PRESETS_N 3
|
||||
#define HK_PRESETS_N 2
|
||||
@@ -826,6 +827,10 @@ int show_power_menu(void);
|
||||
* meow_lock_screen_engage() 供电源菜单「锁定」与唤醒路径用;未配凭据时 no-op。 */
|
||||
int run_lock_screen(void);
|
||||
int meow_lock_screen_engage(void);
|
||||
/* 设置页「锁屏 PIN」数字输入模态(系统级 PIN 设置/修改输入):满 4 位返回 1 并拷贝到 out,电源=取消返回 0。 */
|
||||
int lck_input_pin_modal(const char *title, char *out, int outcap);
|
||||
/* 设置页「锁屏 PIN」独立子页面(subpage.c 脚手架;阻塞到返回)。 */
|
||||
int run_lock_settings_page(void);
|
||||
int stop_player(void);
|
||||
/* 电源管理服务 IPC(SYSTEM_FRAMEWORK_SERVICES §3.2:launcher 电源动作经 meow_svc_power 执行) */
|
||||
int pm_power_ipc(uint32_t cmd, uint32_t flag, const char *arg, char *res, int reslen);
|
||||
|
||||
Binary file not shown.
@@ -694,6 +694,11 @@ int s_net_get(const srow_t *r, char *buf, int len)
|
||||
case NET_LIST_ABOUT: snprintf(buf, len, "MeowOS v%s", g_meowos_version); return 0;
|
||||
case NET_LIST_WIFI_PAGE: snprintf(buf, len, "%s", g_net_ssid); return 0; /* M2.76:子页入口摘要 */
|
||||
case NET_LIST_BT_PAGE: snprintf(buf, len, "%s", g_bt_mode); return 0; /* M2.76 */
|
||||
case NET_LIST_PIN_PAGE: { /* M6.x:锁屏 PIN 入口摘要 */
|
||||
if (!lck_pin_configured()) { snprintf(buf, len, "未设置"); }
|
||||
else if (lck_lock_remaining() > 0) { snprintf(buf, len, "锁定中"); }
|
||||
else { snprintf(buf, len, "已设置"); }
|
||||
return 0; }
|
||||
}
|
||||
snprintf(buf, len, "-");
|
||||
return 0;
|
||||
|
||||
@@ -115,6 +115,9 @@ static const srow_t SMENU[] = {
|
||||
{ "音量上限", "audio.volume_max", SC_SLIDER, 0,100,1, NULL,NULL,0,0 },
|
||||
{ "音量跳步", "audio.volume_step", SC_SLIDER, 1,5,1, NULL,NULL,0,0 },
|
||||
{ "输出设备", "audio.output", SC_PRESET, 0,0,0, out_presets, out_preset_labels, OUT_PRESETS_N,0 },
|
||||
/* M6.x 锁屏:安全组「锁屏 PIN」独立子页面(状态/设置/修改/清除/唤醒锁开关,见 lock_settings.c) */
|
||||
{ "安全", NULL, SC_HEADER, 0,0,0, NULL,NULL,0,0 },
|
||||
{ "锁屏 PIN", NULL, SC_LIST, 0,0,0, NULL,NULL,0, NET_LIST_PIN_PAGE },
|
||||
/* 关于(设置列表最底;「关于本机」点开 s_about_open 弹只读设备信息框) */
|
||||
{ "关于", NULL, SC_HEADER, 0,0,0, NULL,NULL,0,0 },
|
||||
{ "关于本机", NULL, SC_LIST, 0,0,0, NULL,NULL,0, NET_LIST_ABOUT },
|
||||
@@ -1276,6 +1279,7 @@ void run_settings_page(void)
|
||||
after_modal = 1;
|
||||
if (r->net_list == NET_LIST_WIFI_PAGE) { run_wifi_page(); s_net_refresh(); }
|
||||
else if (r->net_list == NET_LIST_BT_PAGE) { run_bt_page(); s_net_refresh(); }
|
||||
else if (r->net_list == NET_LIST_PIN_PAGE) { run_lock_settings_page(); s_net_refresh(); }
|
||||
else s_net_open(r);
|
||||
if (tfd >= 0) {
|
||||
unsigned char e[16];
|
||||
|
||||
@@ -62,6 +62,30 @@ int main(void)
|
||||
CHECK(lck_lock_required(1) == 1, "wake-required=1 after wake=1");
|
||||
/* 开机不锁是结构性(boot 路径不调 lck_lock_required)——此处断言决策函数正确即隔离该项 */
|
||||
|
||||
/* ---- 唤醒门=主动锁标志:唤醒锁关 + 主动锁标志 → 仍必锁屏(电源菜单「锁定」语义)---- */
|
||||
unlink("/tmp/meow_pin_locked");
|
||||
meow_settings_set_int("system.pin_lock_on_wake", 0);
|
||||
meow_settings_save();
|
||||
CHECK(lck_wake_should_lock() == 0, "wake_should_lock=0 (wake=0, no manual marker)");
|
||||
CHECK(lck_manual_lock_set() == MEOW_OK, "manual_lock_set ok");
|
||||
CHECK(lck_wake_should_lock() == 1, "wake_should_lock=1 (manual marker, wake=0)");
|
||||
lck_manual_lock_clear();
|
||||
CHECK(lck_wake_should_lock() == 0, "wake_should_lock=0 after manual marker cleared");
|
||||
meow_settings_set_int("system.pin_lock_on_wake", 1);
|
||||
meow_settings_save();
|
||||
CHECK(lck_wake_should_lock() == 1, "wake_should_lock=1 (wake=1)");
|
||||
|
||||
/* ---- 面板一次性解锁恢复口(bypass 标志)---- */
|
||||
CHECK(lck_unlock_once_consume() == 0, "unlock_once_consume=0 when flag absent");
|
||||
{
|
||||
int fd = open("/tmp/meow_pin_unlock_once", O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
CHECK(fd >= 0, "create unlock_once flag");
|
||||
if (fd >= 0) { write(fd, "1", 1); close(fd); }
|
||||
}
|
||||
CHECK(lck_unlock_once_consume() == 1, "unlock_once_consume=1 when flag present");
|
||||
CHECK(access("/tmp/meow_pin_unlock_once", F_OK) != 0, "bypass flag consumed (deleted)");
|
||||
CHECK(lck_unlock_once_consume() == 0, "unlock_once_consume=0 after consumed");
|
||||
|
||||
/* ---- 错 5 次锁定(持久化,重启不清)---- */
|
||||
CHECK(lck_lock_remaining() == 0, "not locked before fails");
|
||||
int r1 = lck_pin_fail(); /* 1 */
|
||||
@@ -109,14 +133,28 @@ int main(void)
|
||||
CHECK(strcmp(sp2, pphash) == 0, "system.pin == panel.pin after migrate");
|
||||
CHECK(lck_pin_check("5678") == 1, "still accept after migrate (via system.pin)");
|
||||
|
||||
/* ---- 清除免旧 PIN(设置页清除语义:物理持机即授权,无旧密码要求)---- */
|
||||
/* 先设一个 PIN,然后**不验旧 PIN** 直接 lck_pin_clear()(清除 API 本身无旧 PIN 前置)。
|
||||
* 先清 panel.pin(迁移残留),确保「已设」只由 system.pin 贡献。 */
|
||||
meow_settings_set_str("panel.pin", "");
|
||||
meow_settings_save();
|
||||
CHECK(lck_pin_set("2468") == MEOW_OK, "set pin 2468 for clear");
|
||||
CHECK(lck_pin_configured() == 1, "configured before clear");
|
||||
CHECK(lck_pin_clear() == MEOW_OK, "clear WITHOUT old PIN succeeds");
|
||||
CHECK(lck_pin_configured() == 0, "not configured after clear (no old PIN path)");
|
||||
|
||||
/* ---- 清除(兜底解锁):lck_pin_clear 后不再要求锁 ---- */
|
||||
/* lck_pin_clear 只清 system.pin;panel.pin 仍存(迁移源),先清掉再断言全部未配 */
|
||||
meow_settings_set_str("panel.pin", "");
|
||||
meow_settings_save();
|
||||
CHECK(lck_pin_clear() == MEOW_OK, "pin clear");
|
||||
CHECK(lck_pin_clear() == MEOW_OK, "pin clear (final)");
|
||||
CHECK(lck_pin_configured() == 0, "not configured after clear");
|
||||
CHECK(lck_lock_required(1) == 0, "wake-required=0 after clear");
|
||||
|
||||
/* 清理临时标志文件(幂等) */
|
||||
unlink("/tmp/meow_pin_unlock_once");
|
||||
unlink("/tmp/meow_pin_locked");
|
||||
|
||||
unlink(conf);
|
||||
printf("\n%s\n", g_fail ? "SOME TESTS FAILED" : "ALL PASS");
|
||||
return g_fail ? 1 : 0;
|
||||
|
||||
Reference in new issue
Block a user