- M7 launcher 重写 5 期(虚拟化宫格/meow_theme 单一权威/横幅动画/自定义 PIN 键盘) - OOM 通用化(cachegov 上收 SDK)、自动切歌根治、meowpanel jv_free 泄漏修复、Hello 滚动卡顿修复 - ncm 歌词 UI / 媒体通知封面 / 封面分辨率 640 - 5 bug 修复:ncm 后台化 UI 叠层+点击穿透、再进 ncm 桌面叠层、播放页新旧 UI 叠层抢刷脏区(meow_ui_gfx 恢复边沿整帧重画)、PIN 亮屏亮度跳(keys.c meow_panel_on 按 settings_brightness_clamped 恢复)、通知中心封面显歌单封面(cover.c save_cover_raw 加 is_song + 命中块守卫) - 四 App 统一重链新 meow_ui.a 51caee4a;M6.19=0.8.19 固件 2d2331f2 推卡自刷验收全绿
705 lines
37 KiB
C
705 lines
37 KiB
C
/* power_menu.c — MeowOS launcher 拆分模块(LAUNCHER_SPLIT_PLAN 拆分)。*/
|
||
/* 本文件由拆分工具从 meow_launcherd.c 按职责搬移;逻辑与原文 0-diff(仅 static 可见性按跨模块需求调整)。*/
|
||
#include "meow_launcher_internal.h"
|
||
|
||
/* M2.x 锁屏:电源菜单增「锁定」手动锁。网格 2 列×3 行:0=关机 1=重启 2=回HiBy 3=升级
|
||
* 4=锁定 5=取消;取消仍是安全默认项(PM_NUM-1),电源键确认/导航不会误触发关机。 */
|
||
static const int pm_cy[PM_NUM] = { 250, 250, 390, 390, 530, 530 }; /* 圆心 y(行距 140) */
|
||
|
||
static const char *pm_labels_cn[PM_NUM] = { "关机", "重启", "回HiBy", "升级", "锁定", "取消" };
|
||
|
||
static const char *pm_labels_en[PM_NUM] = { "POWER OFF", "RESTART", "HIBYOS", "UPGRADE", "LOCK", "CANCEL" };
|
||
|
||
|
||
/* 电源菜单圆钮图标:从 pm_icons.h 的 56×56 alpha 位图 blit 到 fb(以圆钮中心 cx,cy 为锚居中)。
|
||
* alpha 按 col(RGB565)映射:图标前景色随选中/未选中主题色变化(日夜间由 pm_theme_* 提供)。
|
||
* dst_px 为 fb16bpp 写入:新像素 = col 前景与背景(btn bg)按 alpha 混合。 */
|
||
static void blit_pm_icon(int idx, int cx, int cy, uint16_t col)
|
||
{
|
||
const unsigned char *src = pm_icons[idx].data;
|
||
int S = PM_ICON_SIZE;
|
||
int x0 = cx - S / 2, y0 = cy - S / 2;
|
||
for (int y = 0; y < S; y++) {
|
||
int yy = y0 + y;
|
||
if (yy < 0 || yy >= fb_yres) continue;
|
||
uint16_t *row = (uint16_t *)fb + yy * (fb_line / 2);
|
||
for (int x = 0; x < S; x++) {
|
||
int a = src[y * S + x];
|
||
if (a < 8) continue; /* 透明像素跳过 */
|
||
int xx = x0 + x;
|
||
if (xx < 0 || xx >= fb_xres) continue;
|
||
/* 前景 col 已含所需亮度;此处仅做软边 alpha 混合到背景,避免锯齿 */
|
||
uint16_t bg = row[xx];
|
||
if (a >= 240) { row[xx] = col; continue; }
|
||
int a4 = a >> 4; /* 0..15 */
|
||
int r = ((col >> 11) * a4 + ((bg >> 11) & 0x1F) * (16 - a4)) >> 4;
|
||
int g = (((col >> 5) & 0x3F) * a4 + ((bg >> 5) & 0x3F) * (16 - a4)) >> 4;
|
||
int b = ((col & 0x1F) * a4 + (bg & 0x1F) * (16 - a4)) >> 4;
|
||
row[xx] = (uint16_t)((r << 11) | (g << 5) | b);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
#if 0 /* ================================================================
|
||
* M7.0b 退役:电源菜单圆钮改走 SDK 控件(meow_card/meow_iconbtn/自定义画布),
|
||
* 命中/选中/按压态全由 SDK 接管;本块保留作回退位(删除 #if 0 行恢复旧手绘)。
|
||
* ================================================================ */
|
||
/* 绘制电源菜单圆钮 i(MD3 圆形:外描边+内填充+圆内 Material 图标;选中高亮)。
|
||
* 圆内放 Material Symbols 位图,文字标签放圆下(Android 12 式:icon 上、label 下)。 */
|
||
static void draw_pm_button(int i, int selected)
|
||
{
|
||
int cx = pm_cx[i], cy = pm_cy[i];
|
||
/* 主题(日夜间由 pm_theme_* 决定;默认取 dark,后续接设置) */
|
||
const pm_theme_t *th = &pm_theme_dark;
|
||
/* 先铺一块比任何选中圈都大的卡片底色圆,盖掉上一态残留的选中描边(问题3:
|
||
* 焦点移走后 PM_R+2..PM_R+6 之间残留亮圈。以 0x1C2438 卡片色清底)。 */
|
||
fill_circle(cx, cy, PM_R + 10, 0x1C2438);
|
||
/* MD3 无边框高亮:选中=未选中底色稍亮填充(无描边圈),仅底色区分焦点;避免圆形描边残留。 */
|
||
if (selected)
|
||
fill_circle(cx, cy, PM_R, th->btn_sel_bg);
|
||
else
|
||
fill_circle(cx, cy, PM_R, th->btn_nor_bg);
|
||
/* 圆内 Material 图标(alpha 位图 + 主题前景色) */
|
||
blit_pm_icon(i, cx, cy, selected ? th->icon_sel : th->icon_nor);
|
||
uint32_t col = selected ? 0xFFFFFF : 0xC8D0E8;
|
||
/* 圆下文字标签(真字体/中文 或 点阵 ASCII 回退) */
|
||
int ly = cy + PM_R + 8;
|
||
if (mfont_ready) {
|
||
const char *lab = pm_labels_cn[i];
|
||
int lw = meow_font_width_text(lab, 18);
|
||
meow_font_drawtext((uint16_t *)fb, cx - lw / 2, ly, lab, rgb565(col), 18);
|
||
} else {
|
||
const char *lab = pm_labels_en[i];
|
||
int lw = (int)strlen(lab) * 5;
|
||
draw_text(cx - lw / 2, ly + 1, lab, 1, col);
|
||
}
|
||
}
|
||
#endif /* M7.0b 退役:电源菜单旧手绘圆钮 */
|
||
|
||
/* ==================================================================
|
||
* M7.0b 电源菜单控件化(launcher 无 meow_ui_run,手动驱动 SDK 控件):
|
||
* - 圆角卡 → meow_card(SDK 主题 surfaceContainerLow);
|
||
* - 六个圆钮 → meow_widget_custom_create(pm_icons 专有位图:关机/重启/回HiBy/升级/锁定/取消,
|
||
* 均 56×56 1:1 blit,无放大)。meow_iconbtn 分支保留(回HiBy/取消曾改走 sb_icons,因放大锯齿
|
||
* 定案回退 pm_icons,见 pm_sdk_icon[] 注释;后续 SDK 出更高清图标可再启用);
|
||
* - 命中/选中/按压态全走 SDK(meow_widget_hit/set_state/draw);
|
||
* - 主题 = 读 SDK meow_theme(单一权威),后台遮罩仍 dim_screen(会话骨架不动)。
|
||
* 控件 lazy 创建一次(owner=PM_SENTINEL_ACT 哨兵 activity),跨多次进入复用;
|
||
* show_power_menu() 进入时 push 哨兵、退出时 pop(owner 闸门使控件命中生效)。
|
||
* ================================================================== */
|
||
#define PM_SENTINEL_ACT 0x50 /* 电源菜单哨兵 activity(不与 launcher 其它页冲突) */
|
||
#define PM_BTN_SIZE (PM_R * 2) /* 圆钮 = 外接正方形边长(直径) */
|
||
|
||
/* 哪些 pm 图标走 SDK sb_icons 表(可用 meow_iconbtn 直接出图);-1=不在 → 自定义画布 blit pm_icons。
|
||
* M7.0b 曾把 2=回HiBy / 5=取消 走 meow_iconbtn(SB_ARROW_BACK / SB_CLOSE),但 meow_iconbtn 按
|
||
* 0.6*size 把 32×32 sb_icons 位图放大到 ~60px(>位图原生墨高),最近邻放大导致明显锯齿;且此尺寸
|
||
* 大于 M6.8 及更早电源菜单圆钮图标(pm_icons 56×56,1:1 无放大)。定案:这两钮也回退 pm_icons 专有
|
||
* 位图(PM_ICON_BACK/PM_ICON_CANCEL,同为 Material Symbols 56×56),统一其余四钮画法,恢复旧尺寸。
|
||
* pm_icons[] 全部专用 → meow_iconbtn 分支保留(后续 SDK 出更高清图标可再启用)。 */
|
||
static const int pm_sdk_icon[PM_NUM] = {
|
||
-1, /* 0 关机:pm_icons 专有(SDK 无 power 位图) */
|
||
-1, /* 1 重启:pm_icons 专有 */
|
||
-1, /* 2 回HiBy:pm_icons 专有(恢复 M6.8 56×56,避免 meow_iconbtn 放大锯齿) */
|
||
-1, /* 3 升级:pm_icons 专有 */
|
||
-1, /* 4 锁定:pm_icons 专有(SDK 无 lock 位图) */
|
||
-1, /* 5 取消:pm_icons 专有(同 2,恢复旧尺寸) */
|
||
};
|
||
|
||
/* 圆钮文案 i18n id(meow_str)。common.cancel 内嵌已有;power.* 需 TF 覆盖表/后续并入 SDK 内嵌。 */
|
||
static const char *pm_str_id[PM_NUM] = {
|
||
"power.off", "power.restart", "power.back_hiby",
|
||
"power.upgrade", "power.lock", "common.cancel",
|
||
};
|
||
|
||
static meow_widget *g_pm_card = NULL;
|
||
static meow_widget *g_pm_btns[PM_NUM] = {NULL};
|
||
static int g_pm_init = 0;
|
||
|
||
/* 按主题混合(pct 0..100:base 向 top 混 pct%,24-bit 每通道;近似 SDK state_tint/blend)。 */
|
||
static uint32_t pm_blend(uint32_t base, uint32_t top, int pct)
|
||
{
|
||
int br = (base >> 16) & 0xFF, bg = (base >> 8) & 0xFF, bb = base & 0xFF;
|
||
int tr = (top >> 16) & 0xFF, tg = (top >> 8) & 0xFF, tb = top & 0xFF;
|
||
int r = (br * (100 - pct) + tr * pct) / 100;
|
||
int g = (bg * (100 - pct) + tg * pct) / 100;
|
||
int b = (bb * (100 - pct) + tb * pct) / 100;
|
||
return ((uint32_t)r << 16) | ((uint32_t)g << 8) | (uint32_t)b;
|
||
}
|
||
|
||
/* 自定义画布:绘制 pm_icons 专有圆钮(图标不在 SDK sb_icons 表时用)。
|
||
* SDK 已把绘制 clip 设为控件矩形;圆形底色按 selected 取主题容器色,图标墨色随之;
|
||
* 禁用/按压态由本回调自叠(SDK 不替 W_CUSTOM 自动叠,meow_widget_draw_state_layer 铺方矩形,
|
||
* 圆形钮此处手工按圆域混合,更贴合)。 */
|
||
static void pm_render_cb(meow_widget *w, const meow_theme *th, void *ctx)
|
||
{
|
||
int i = (int)(intptr_t)ctx;
|
||
int rc[4]; meow_widget_rect(w, rc); /* 绝对坐标 x,y,w,h(launcher 侧 meow_widget 不透明) */
|
||
int cx = rc[0] + rc[2] / 2, cy = rc[1] + rc[3] / 2;
|
||
int r = (rc[2] < rc[3] ? rc[2] : rc[3]) / 2;
|
||
unsigned st = meow_widget_state(w);
|
||
int sel = (st & MEOW_WS_SELECTED) != 0;
|
||
int disabled = (st & MEOW_WS_ENABLED) == 0;
|
||
int pressed = (st & MEOW_WS_PRESSED) != 0;
|
||
uint32_t base = sel ? th->primaryContainer : th->surfaceContainer;
|
||
uint32_t fg = sel ? th->onPrimaryContainer : th->onSurface;
|
||
if (disabled) base = pm_blend(base, th->onSurface, 38); /* 禁用变暗(向灰) */
|
||
else if (pressed) base = pm_blend(base, th->onSurface, sel ? 24 : 12); /* 按压状态层 */
|
||
meow_gfx_fill_circle(cx, cy, r, base);
|
||
blit_pm_icon(i, cx, cy, rgb565(fg));
|
||
}
|
||
|
||
/* 自定义画布命中:圆形(圆心=控件中心,半径=size/2)。 */
|
||
static int pm_hit_cb(meow_widget *w, int x, int y, void *ctx)
|
||
{
|
||
(void)ctx;
|
||
int rc[4]; meow_widget_rect(w, rc);
|
||
int cx = rc[0] + rc[2] / 2, cy = rc[1] + rc[3] / 2;
|
||
int r = (rc[2] < rc[3] ? rc[2] : rc[3]) / 2;
|
||
int dx = x - cx, dy = y - cy;
|
||
return dx * dx + dy * dy <= r * r;
|
||
}
|
||
|
||
/* 创建卡片 + 六钮(owner 钉 = PM_SENTINEL_ACT,仅首进创建一次,复用)。 */
|
||
static void pm_widgets_create(void)
|
||
{
|
||
meow_ui_activity_push(PM_SENTINEL_ACT);
|
||
g_pm_card = meow_card_create(PM_CARD_X0, PM_CARD_Y0, PM_CARD_W, PM_CARD_H);
|
||
for (int i = 0; i < PM_NUM; i++) {
|
||
int sz = PM_BTN_SIZE;
|
||
int x = pm_cx[i] - sz / 2, y = pm_cy[i] - sz / 2;
|
||
if (pm_sdk_icon[i] >= 0)
|
||
g_pm_btns[i] = meow_iconbtn_create(x, y, sz, pm_sdk_icon[i]);
|
||
else
|
||
g_pm_btns[i] = meow_widget_custom_create(x, y, sz, sz,
|
||
pm_render_cb, pm_hit_cb,
|
||
(void *)(intptr_t)i);
|
||
}
|
||
meow_ui_activity_pop(); /* 回主 activity(控件 owner 已钉为哨兵) */
|
||
g_pm_init = 1;
|
||
}
|
||
|
||
/* 主题刷新:iconbtn 底色=surfaceContainer(与卡片 surfaceContainerLow 拉开对比)。
|
||
* custom 钮由 render_cb 读 th 自带;此处只补 iconbtn 的 opts.bg(跨开放切主题也跟手)。 */
|
||
static void pm_refresh_theme(void)
|
||
{
|
||
const meow_theme *th = meow_theme_get();
|
||
meow_widget_opts op; memset(&op, 0, sizeof op);
|
||
op.bg = th->surfaceContainer;
|
||
for (int i = 0; i < PM_NUM; i++)
|
||
if (g_pm_btns[i] && pm_sdk_icon[i] >= 0)
|
||
meow_widget_set_opts(g_pm_btns[i], &op);
|
||
}
|
||
|
||
/* i18n 文案(meow_str_zh:未知 id → 中文兜底)。TF 覆盖表/后续 SDK 内嵌并入后自动换语。 */
|
||
static const char *pm_label(int i)
|
||
{
|
||
return meow_str_zh(pm_str_id[i], pm_labels_cn[i]);
|
||
}
|
||
|
||
/* 绘制单个圆钮(SDK 控件)+ 圆下标签(主题色,选中亮/未选次色)。 */
|
||
static void pm_draw_button(int i, int selected)
|
||
{
|
||
meow_widget *w = g_pm_btns[i];
|
||
if (!w) return;
|
||
meow_widget_set_selected(w, selected);
|
||
meow_widget_draw(w);
|
||
const meow_ui_theme_t *th = s_ui_theme();
|
||
int cx = pm_cx[i], cy = pm_cy[i];
|
||
int ly = cy + PM_R + 8;
|
||
uint32_t col = selected ? th->on_surface : th->on_surface_variant;
|
||
if (mfont_ready) {
|
||
const char *lab = pm_label(i);
|
||
int lw = meow_font_width_text(lab, 18);
|
||
meow_font_drawtext((uint16_t *)fb, cx - lw / 2, ly, lab, rgb565(col), 18);
|
||
} else {
|
||
const char *lab = pm_labels_en[i];
|
||
draw_text(cx - (int)strlen(lab) * 5 / 2, ly + 1, lab, 1, col);
|
||
}
|
||
}
|
||
|
||
/* 标脏一个圆钮的整块区域(圆外接框 + 圆下标签),供局部 flush。 */
|
||
static void pm_button_dirty(int i)
|
||
{
|
||
int sz = PM_BTN_SIZE, cy = pm_cy[i];
|
||
meow_dirty_add(pm_cx[i] - sz / 2 - 4, cy - sz / 2 - 4, sz + 8, sz + PM_R + 44);
|
||
}
|
||
|
||
/* 命中检测:返回命中的钮下标(0..PM_NUM-1),否则 -1。 */
|
||
static int pm_hit_button(int x, int y)
|
||
{
|
||
for (int i = 0; i < PM_NUM; i++)
|
||
if (g_pm_btns[i] && meow_widget_hit(g_pm_btns[i], x, y)) return i;
|
||
return -1;
|
||
}
|
||
|
||
/* 绘制卡片 + 标题 + 底部提示 + 全部圆钮(进入/全刷时调用一次)。 */
|
||
static void pm_draw_card(void)
|
||
{
|
||
pm_refresh_theme();
|
||
if (g_pm_card) meow_widget_draw(g_pm_card);
|
||
const meow_ui_theme_t *th = s_ui_theme();
|
||
const char *title = "POWER MENU";
|
||
int title_y = PM_CARD_Y0 + 26;
|
||
if (mfont_ready)
|
||
meow_font_drawtext((uint16_t *)fb, (fb_xres - meow_font_width_text(title, 20)) / 2,
|
||
title_y, title, rgb565(th->on_surface), 20);
|
||
else
|
||
draw_text((fb_xres - (int)strlen(title) * 6) / 2, title_y, title, 2, th->on_surface);
|
||
const char *hint = meow_str_zh("power.hint_nav", "音量导航 电源确认");
|
||
int hint_y = PM_CARD_Y0 + PM_CARD_H + 10;
|
||
if (mfont_ready)
|
||
meow_font_drawtext((uint16_t *)fb, (fb_xres - meow_font_width_text(hint, 18)) / 2,
|
||
hint_y, hint, rgb565(th->on_surface_variant), 18);
|
||
else
|
||
draw_text((fb_xres - (int)strlen("VOLUME NAV POWER OK") * 5) / 2,
|
||
hint_y + 1, "VOLUME NAV POWER OK", 1, th->on_surface_variant);
|
||
}
|
||
|
||
/* ---- 电源管理服务 IPC 客户端(SYSTEM_FRAMEWORK_SERVICES §3.2:launcher 经服务触发电源动作)----
|
||
* launcher 不再直连 reboot(2)syscall/写 mtd5/写 boot 默认 —— 统一经 meow_svc_power 的
|
||
* `/usr/data/meow_power.sock`(`MEOW_IPC_POWER_SOCK` 可覆盖)发 MSG_POWER_ACTION。 */
|
||
#define PW_SOCK_DEFAULT "/usr/data/meow_power.sock"
|
||
|
||
static int pw_write_all(int fd, const uint8_t *b, size_t n)
|
||
{
|
||
size_t off = 0;
|
||
while (off < n) { ssize_t w = write(fd, b + off, n - off); if (w <= 0) return -1; off += (size_t)w; }
|
||
return 0;
|
||
}
|
||
static int pw_read_all(int fd, uint8_t *b, size_t n)
|
||
{
|
||
size_t off = 0;
|
||
while (off < n) { ssize_t r = read(fd, b + off, n - off); if (r <= 0) return -1; off += (size_t)r; }
|
||
return 0;
|
||
}
|
||
/* 发一帧并等应答(读超时 1.5s,服务不可达/无响应不至于卡死菜单)。 */
|
||
static int pw_xchg(int fd, uint16_t type, uint32_t req, const void *pl, uint32_t len,
|
||
uint8_t *rbuf, uint32_t rcap, uint16_t *rtype)
|
||
{
|
||
uint8_t hdr[MEOW_IPC_HDR_LEN];
|
||
uint32_t magic = MEOW_IPC_MAGIC, rlen = len;
|
||
uint16_t ver = MEOW_IPC_VERSION, t = type;
|
||
memcpy(hdr + 0, &magic, 4); memcpy(hdr + 4, &ver, 2); memcpy(hdr + 6, &t, 2);
|
||
memcpy(hdr + 8, &req, 4); memcpy(hdr + 12, &rlen, 4);
|
||
if (pw_write_all(fd, hdr, sizeof hdr) < 0) return -1;
|
||
if (len && pl && pw_write_all(fd, pl, len) < 0) return -1;
|
||
struct pollfd pf = { fd, POLLIN, 0 };
|
||
int pr = poll(&pf, 1, 1500);
|
||
if (pr <= 0) return -1;
|
||
uint8_t rhdr[MEOW_IPC_HDR_LEN];
|
||
if (pw_read_all(fd, rhdr, sizeof rhdr) < 0) return -1;
|
||
uint32_t rmagic, rlen2; uint16_t rver, rt;
|
||
memcpy(&rmagic, rhdr, 4); memcpy(&rver, rhdr + 4, 2); memcpy(&rt, rhdr + 6, 2);
|
||
memcpy(&rlen2, rhdr + 12, 4);
|
||
if (rmagic != MEOW_IPC_MAGIC || rver != MEOW_IPC_VERSION) return -1;
|
||
if (rlen2 > rcap) rlen2 = rcap;
|
||
if (rlen2 && pw_read_all(fd, rbuf, rlen2) < 0) return -1;
|
||
if (rtype) *rtype = rt;
|
||
return 0;
|
||
}
|
||
|
||
/* 经电源服务执行动作。返回 MEOW_OK 或错误码;res/reslen 可收状态文本。 */
|
||
int pm_power_ipc(uint32_t cmd, uint32_t flag, const char *arg, char *res, int reslen)
|
||
{
|
||
const char *sock = getenv("MEOW_IPC_POWER_SOCK");
|
||
if (!sock || !sock[0]) sock = PW_SOCK_DEFAULT;
|
||
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||
if (fd < 0) return MEOW_ERR_IO;
|
||
struct sockaddr_un a;
|
||
memset(&a, 0, sizeof a);
|
||
a.sun_family = AF_UNIX;
|
||
strncpy(a.sun_path, sock, sizeof a.sun_path - 1);
|
||
if (connect(fd, (struct sockaddr *)&a, sizeof a) < 0) { close(fd); return MEOW_ERR_IO; }
|
||
m_hello_t h;
|
||
memset(&h, 0, sizeof h);
|
||
snprintf(h.app_id, sizeof h.app_id, "%s", "os.meow.launcher");
|
||
h.version = 1;
|
||
uint8_t rbuf[256]; uint16_t rtype = 0;
|
||
if (pw_xchg(fd, MSG_HELLO, 0x100, &h, sizeof h, rbuf, sizeof rbuf, &rtype) < 0 || rtype != MSG_ACK) {
|
||
close(fd); return MEOW_ERR_IO;
|
||
}
|
||
m_ack_t ak;
|
||
memcpy(&ak, rbuf, sizeof ak);
|
||
if (ak.code != MEOW_OK) { close(fd); return (int)ak.code; }
|
||
m_power_action_t pa;
|
||
memset(&pa, 0, sizeof pa);
|
||
pa.cmd = cmd;
|
||
pa.flag = flag;
|
||
if (arg) snprintf(pa.arg, sizeof pa.arg, "%s", arg);
|
||
if (pw_xchg(fd, MSG_POWER_ACTION, 0x101, &pa, sizeof pa, rbuf, sizeof rbuf, &rtype) < 0 || rtype != MSG_POWER_STATUS) {
|
||
close(fd); return MEOW_ERR_IO;
|
||
}
|
||
m_power_status_t st;
|
||
memcpy(&st, rbuf, sizeof st);
|
||
close(fd);
|
||
if (res && reslen > 0) {
|
||
uint16_t ml = st.msg_len;
|
||
if (ml >= (uint16_t)reslen) ml = (uint16_t)(reslen - 1);
|
||
memcpy(res, st.msg, ml);
|
||
res[ml] = 0;
|
||
}
|
||
return (int)st.code;
|
||
}
|
||
|
||
/* launcher 侧统一电源动作入口:先转储未上卡通知(进程本地,见 §3.2 定案),再经服务 IPC 执行。
|
||
* 返回 MEOW_OK=已受理(服务将执行,通常随即 reboot/poweroff);非 OK=服务不可达/拒绝,调用方应
|
||
* 稳妥处理(如菜单按「取消」返回,绝不误报动作成功导致 launcher 退出卡死)。 */
|
||
int meow_power_action(uint32_t cmd)
|
||
{
|
||
meow_notif_before_poweroff(); /* 幂等安全(未 init 直接返回) */
|
||
int rc = pm_power_ipc(cmd, 0, NULL, NULL, 0);
|
||
if (rc != MEOW_OK)
|
||
logmsg("meow_power_action cmd=%u FAILED rc=%d (power service unavailable?)", cmd, rc);
|
||
return rc;
|
||
}
|
||
|
||
|
||
/* 电源菜单(M2.6):2×2 网格,dirty 绘制消频闪;输入修复:
|
||
* - 触摸按下捕获坐标、抬起命中按钮即确认(同 run_menu MT 防抖);
|
||
* - 音量上/下导航;播放=确认;电源新按(松开长按后)=确认当前钮(非取消);
|
||
* - 取消=选「取消」钮;8s 持续按住=强制关机(绕过)。
|
||
* 返回 1=采取动作,0=取消。 */
|
||
int show_power_menu(void)
|
||
{
|
||
int fbfd = open(FB_DEV, O_RDWR);
|
||
if (fbfd >= 0) { ioctl(fbfd, FBIOBLANK, 0); close(fbfd); } /* 亮起面板 */
|
||
pm_capture_app_frame(); /* A-0:菜单背景 = app 当前帧(fb0 buffer0),再压暗绘制其上 */
|
||
dim_screen();
|
||
/* M2.8 Bug 3-residual:若电源菜单是在「息屏」态打开(按住 3s),此处 FBIOBLANK(0)
|
||
* 刚上电,LCDC 扫描地址可能非 buffer0;强制 re-pan 让压暗的应用列表 + 菜单落在被显示的
|
||
* 缓冲,否则菜单画在非显示缓冲上不可见。 */
|
||
fb_pan_buf0_force();
|
||
meow_screen_on = 1; /* 菜单打开即视为亮屏 */
|
||
|
||
/* M2.11 B:默认光标 = 「取消」(安全项,index 4)。用户打开菜单后未导航就按电源/播放,
|
||
* 只会取消关菜单,绝不因「按电源键」本身关机/重启。要真关机必须先导航到「关机」再确认。 */
|
||
int sel = PM_NUM - 1; /* 默认取消(安全) */
|
||
/* M7.0b 控件化:进入 push 哨兵(控件 owner 闸门使 meow_widget_hit 生效)+ lazy 建卡/钮。
|
||
* 卡片=meow_card(SDK 主题 surfaceContainerLow),圆钮=meow_iconbtn/自定义画布,命中/选中/
|
||
* 按压态全走 SDK;背景遮罩仍 dim_screen(会话骨架不动)。 */
|
||
meow_ui_activity_push(PM_SENTINEL_ACT);
|
||
if (!g_pm_init) pm_widgets_create();
|
||
pm_draw_card(); /* 卡片 + 标题 POWER MENU + 底部提示(SDK 主题色,i18n 文案) */
|
||
meow_dirty_full(); /* M2.16:把压暗列表+卡片+标题+(下方圆钮)作为一整帧呈现 */
|
||
|
||
/* 触摸状态(按下→抬起):统一 meow_touch 接口(goodix 时序免疫,原点由首个有效 ABS 锁) */
|
||
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 prev_vold = 0, prev_volu = 0, prev_pwr = 0;
|
||
kp_poll(&kp_power, NULL, NULL); kp_poll(&kp_keys, NULL, NULL);
|
||
prev_pwr = kp_is_down(&kp_power, KEY_POWER) ? 1 : 0;
|
||
prev_vold = kp_is_down(&kp_keys, KEY_VOLUMEDOWN) ? 1 : 0;
|
||
prev_volu = kp_is_down(&kp_keys, KEY_VOLUMEUP) ? 1 : 0;
|
||
|
||
int act = -1;
|
||
unsigned long long pm_t0 = now_ms();
|
||
unsigned long long pm_last_interact = pm_t0; /* M2.33:菜单空闲自动关闭基准(任何互动刷新) */
|
||
int pm_init = 0, last_sel = -1;
|
||
/* M2.10 Bug:电源菜单 8s 强关(按住电源≥8s=绕过强关)会覆盖用户的菜单操作 —— 用户按住
|
||
* 电源打开菜单后(尤其仍按着电源)点选「回到HibyOS/重启」等按钮,8s 一到先触发强关 → 关机
|
||
* 而非执行所选动作。修法:一旦用户与菜单互动(音量导航/触摸/播放/电源确认),置 pm_interacted=1
|
||
* 取消 8s 强关,让所选动作(如「回到HibyOS」→ reboot RESTART)生效。仅当全程未互动才保留「按住
|
||
* 8s=强关」。*/
|
||
int pm_interacted = 0;
|
||
int pm_press_idx = -1; /* M7.0b:当前按下钮(按压态走 SDK 状态机位) */
|
||
for (;;) {
|
||
/* dirty 绘制:首次全画;此后仅选中变化才重画受影响两钮(消频闪)→ 标脏 + present。 */
|
||
if (!pm_init) {
|
||
for (int i = 0; i < PM_NUM; i++) pm_draw_button(i, i == sel);
|
||
pm_init = 1; last_sel = sel;
|
||
meow_ui_flush(); /* A-1/A-2:SDK present(vsync+帧率门控+blit 脏=全帧,含压暗列表+标题+按钮) */
|
||
} else if (sel != last_sel) {
|
||
pm_draw_button(last_sel, 0);
|
||
pm_draw_button(sel, 1);
|
||
pm_button_dirty(last_sel);
|
||
pm_button_dirty(sel);
|
||
last_sel = sel;
|
||
meow_ui_flush(); /* A-1/A-2:SDK present,blit 两钮区 */
|
||
}
|
||
|
||
if (sim_power_pick >= 0 && now_ms() - pm_t0 >= 2000) act = sim_power_pick;
|
||
|
||
int vold = 0, volu = 0, play = 0, pwr = 0;
|
||
if (kp_keys.ok) { kp_poll(&kp_keys, NULL, NULL);
|
||
vold = kp_is_down(&kp_keys, KEY_VOLUMEDOWN);
|
||
volu = kp_is_down(&kp_keys, KEY_VOLUMEUP);
|
||
play = kp_is_down(&kp_keys, KEY_PLAYPAUSE); }
|
||
if (kp_power.ok) { kp_poll(&kp_power, NULL, NULL); pwr = kp_is_down(&kp_power, KEY_POWER); }
|
||
|
||
if (vold && !prev_vold) { sel = (sel + 1) % PM_NUM; pm_interacted = 1; pm_last_interact = now_ms(); }
|
||
if (volu && !prev_volu) { sel = (sel - 1 + PM_NUM) % PM_NUM; pm_interacted = 1; pm_last_interact = now_ms(); }
|
||
/* M2.19:播放键不再作确认(让位给全局媒体控制)。电源菜单的物理确认
|
||
* 已由电源键负责(下行),播放键删除,重复确认移除。 */
|
||
(void)play;
|
||
if (pwr && !prev_pwr) { act = sel; pm_interacted = 1; pm_last_interact = now_ms(); } /* 电源新按=确认(非取消) */
|
||
prev_vold = vold; prev_volu = volu; prev_pwr = pwr;
|
||
|
||
/* 触摸:按下(meow_touch 原点锁定,goodix 时序免疫),抬起按按钮命中确认 */
|
||
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);
|
||
pm_interacted = 1;
|
||
pm_last_interact = now_ms();
|
||
/* M7.0b 按压态:按下命中钮 → 置 PRESSED 并重绘(SDK 状态层,实时) */
|
||
pm_press_idx = pm_hit_button(mt.down_x, mt.down_y);
|
||
if (pm_press_idx >= 0) {
|
||
meow_widget_set_state(g_pm_btns[pm_press_idx], MEOW_WS_PRESSED, 1);
|
||
meow_widget_draw(g_pm_btns[pm_press_idx]);
|
||
pm_button_dirty(pm_press_idx);
|
||
meow_ui_flush();
|
||
}
|
||
} else if (!val && mt.down) {
|
||
pm_interacted = 1;
|
||
pm_last_interact = now_ms();
|
||
if (pm_press_idx >= 0) { /* 清按压态(SDK 状态层随 PRESSED 位清除) */
|
||
meow_widget_set_state(g_pm_btns[pm_press_idx], MEOW_WS_PRESSED, 0);
|
||
meow_widget_draw(g_pm_btns[pm_press_idx]);
|
||
pm_button_dirty(pm_press_idx);
|
||
pm_press_idx = -1;
|
||
meow_ui_flush();
|
||
}
|
||
int dx, dy;
|
||
/* M2.25:抬手位移 >= MEOW_TOUCH_SWIPE_THRESH 判滑动(返回0),
|
||
* 不做确认;否则有效 tap,按下原点命中的按钮即确认。 */
|
||
if (mt_up(&mt, &dx, &dy)) {
|
||
/* M7.0b 命中走 SDK(owner==哨兵 + enabled + 圆形命中) */
|
||
int hit = pm_hit_button(mt.down_x, mt.down_y);
|
||
if (hit >= 0) { sel = hit; act = hit; }
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 8s 强关(绕过):仅当电源持续按住、且用户全程未与菜单互动才触发 —— 放在触摸/按键处理
|
||
* 之后,避免「用户已点选按钮」的同一轮被强关抢先(M2.10 Bug)。 */
|
||
if (pwr && !pm_interacted && now_ms() - pm_t0 >= 5000) {
|
||
if (sim_no_exec) { logmsg("pm: [sim-no-exec] POWER HOLD 8s -> would force poweroff"); meow_ui_activity_pop(); return 1; }
|
||
logmsg("pm: POWER HOLD 8s -> force poweroff");
|
||
if (meow_power_action(POWER_SHUTDOWN) != MEOW_OK) {
|
||
logmsg("pm: power service unavailable, abort force-off (menu closed, no action)");
|
||
meow_ui_activity_pop(); return 0;
|
||
}
|
||
meow_ui_activity_pop();
|
||
return 1;
|
||
}
|
||
|
||
/* M2.33 菜单空闲超时自动关闭:菜单受 MeowOS screen_off_timeout 管理(系统界面不豁免)。
|
||
* 超过超时无任何互动 → 关闭菜单(视为取消)并自动息屏。目的是:息屏后单击电源亮屏时,
|
||
* 电源按下信号不会命中菜单按钮(菜单已关),杜绝误触关机/执行菜单动作。 */
|
||
if (screen_off_timeout > 0 &&
|
||
(unsigned long long)(now_ms() - pm_last_interact) >= (unsigned long long)screen_off_timeout * 1000) {
|
||
logmsg("pm: idle %ds -> close menu + auto screen-off (act=cancel)", screen_off_timeout);
|
||
meow_panel_off();
|
||
meow_auto_slept = 1;
|
||
act = PM_NUM - 1; /* 取消(关菜单) */
|
||
break;
|
||
}
|
||
|
||
if (act >= 0) break;
|
||
usleep(POLL_MS * 1000);
|
||
}
|
||
if (tfd >= 0) close(tfd);
|
||
meow_ui_activity_pop(); /* M7.0b:退出电源菜单,回主 activity(控件 owner 仍钉哨兵,复用) */
|
||
|
||
/* M2.11 B:电源键在菜单 = 按当前项确认。act 与电源动作逐项核对:
|
||
* act==PM_NUM-1(取消) -> 只关菜单,绝不关机(return 0,永不到电源动作);
|
||
* act==4(锁定) -> 手动锁(meow_lock_screen_engage,未配 PIN 则 no-op),关菜单;
|
||
* act==0(关机)/act==1(重启)/act==2(回HibyOS)/act==3(升级模式) -> 才经服务 IPC 执行电源动作。
|
||
* 只有 act 为 0/1/2/3 才可能发电源动作;power 键本身绝不触发关机。 */
|
||
logmsg("pm: act=%d -> %s", act,
|
||
act == 0 ? "关机" : act == 1 ? "重启" : act == 2 ? "回HibyOS" : act == 3 ? "升级模式"
|
||
: act == 4 ? "锁定" : "取消");
|
||
if (act == PM_NUM - 1) { logmsg("pm: cancel (close menu only)"); return 0; }
|
||
if (act == 4) {
|
||
logmsg("pm: LOCK SCREEN");
|
||
meow_lock_screen_engage();
|
||
return 0; /* 关菜单;run_menu 继续(锁屏页已阻塞到解锁或电源息屏) */
|
||
}
|
||
/* 动作统一经电源管理服务 IPC(meow_svc_power);launcher 不再直连 poweroff/reboot(2)/写 mtd5/
|
||
* 写 boot 默认——关机/重启/升级/回HiBy 的动作原语都在服务内实现(§3.2 单一动作链路)。 */
|
||
/* 公共服务:执行动作;服务不可达 → 按「取消」返回(launcher 存活,绝不误报已动作卡死)。
|
||
* meow_power_action 内部已先 meow_notif_before_poweroff()(转储未上卡通知)。 */
|
||
if (act == 0) {
|
||
logmsg("pm: POWER OFF");
|
||
if (sim_no_exec) { logmsg("pm: [sim-no-exec] would poweroff"); return 1; }
|
||
if (meow_power_action(POWER_SHUTDOWN) != MEOW_OK) {
|
||
logmsg("pm: power service unavailable, abort (menu closed, no action)");
|
||
return 0;
|
||
}
|
||
} else if (act == 1) {
|
||
logmsg("pm: REBOOT");
|
||
if (sim_no_exec) { logmsg("pm: [sim-no-exec] would reboot"); return 1; }
|
||
if (meow_power_action(POWER_REBOOT) != MEOW_OK) {
|
||
logmsg("pm: power service unavailable, abort (menu closed, no action)");
|
||
return 0;
|
||
}
|
||
} else if (act == 2) {
|
||
logmsg("pm: RETURN TO HIBYOS");
|
||
if (sim_no_exec) { logmsg("pm: [sim-no-exec] would reboot to hiby"); return 1; }
|
||
if (meow_power_action(POWER_BACK_HIBY) != MEOW_OK) {
|
||
logmsg("pm: power service unavailable, abort (menu closed, no action)");
|
||
return 0;
|
||
}
|
||
} else if (act == 3) {
|
||
logmsg("pm: ENTER UPGRADE");
|
||
if (sim_no_exec) { logmsg("pm: [sim-no-exec] would enter upgrade"); return 1; }
|
||
if (meow_power_action(POWER_UPGRADE) != MEOW_OK) {
|
||
logmsg("pm: power service unavailable, abort (menu closed, no action)");
|
||
return 0;
|
||
}
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
|
||
/* M2.6 G「Reboot to player」:MeowOS 常驻模式点「返回播放器」时,播放器已死,弹确认框
|
||
* 「返回播放器需重启,现在重启?[是/否]」。是=写选单默认 HibyOS + reboot;否=留在 MeowOS。
|
||
* VOL=是/否 切换;PLAY=确认;POWER=取消;触摸点 是/否 确认。风格同电源菜单。
|
||
* 返回 1=是(已 reboot,通常不回),0=否/取消(调用方重绘应用列表)。 */
|
||
/* 「返回播放器」确认框「是/否」按钮(左右),选中高亮。
|
||
* M2.9 Bug 4:改为 dirty 绘制 —— 仅 sel 变化时重画两钮(旧钮取消高亮 + 新钮高亮),
|
||
* 不随主循环每 10ms 全刷(原实现每帧重画同一内容,与 LCD 刷新竞争产生频闪)。 */
|
||
static void draw_cr_button(int sel, int i)
|
||
{
|
||
const meow_theme *mt = meow_theme_get(); /* M7.5:主题语义色(深/浅×MD3/MIUIx 单一权威) */
|
||
int x0 = (i == 0) ? 80 : 280, y0 = 420, w = 120, h = 60;
|
||
uint32_t bg = (i == sel) ? mt->primary : mt->surfaceContainer;
|
||
fill_round_rect(x0, y0, w, h, 12, bg);
|
||
/* M7.0b i18n:是/否 经 meow_str 抽取(未知 id 回退中文) */
|
||
const char *lbl = (i == 0) ? meow_str_zh("power.confirm_yes", "是")
|
||
: meow_str_zh("power.confirm_no", "否");
|
||
uint32_t fg = (i == sel) ? mt->onPrimary : mt->onSurface;
|
||
if (mfont_ready) {
|
||
int lw = meow_font_width_text(lbl, 20);
|
||
meow_font_drawtext((uint16_t *)fb, x0 + w / 2 - lw / 2, y0 + 30 - meow_font_line_height(20) / 2,
|
||
lbl, rgb565(fg), 20);
|
||
} else {
|
||
draw_text(x0 + w / 2 - 6, y0 + 24, (i == 0) ? "YES" : "NO", 2, fg);
|
||
}
|
||
}
|
||
|
||
|
||
int confirm_reboot_player(void)
|
||
{
|
||
dim_screen();
|
||
/* M2.8 Bug 3-residual:确认框同电源菜单 —— 若打开前刚经历息屏/blank,LCDC 扫描地址可能
|
||
* 非 buffer0;强制 re-pan 让「压暗列表 + 是/否」落在被显示的缓冲。 */
|
||
fb_pan_buf0_force();
|
||
const meow_theme *mt0 = meow_theme_get(); /* M7.5:标题颜色走主题语义色 */
|
||
if (mfont_ready) meow_font_drawtext((uint16_t *)fb, 20, 320,
|
||
meow_str_zh("power.reboot_confirm", "返回播放器需重启,现在重启?"), rgb565(mt0->onSurface), 20);
|
||
else draw_text(20, 322, "REBOOT TO RETURN TO PLAYER?", 2, mt0->onSurface);
|
||
|
||
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 prev_vold = 0, prev_volu = 0, prev_pwr = 0;
|
||
kp_poll(&kp_power, NULL, NULL); kp_poll(&kp_keys, NULL, NULL);
|
||
prev_pwr = kp_is_down(&kp_power, KEY_POWER) ? 1 : 0;
|
||
prev_vold = kp_is_down(&kp_keys, KEY_VOLUMEDOWN) ? 1 : 0;
|
||
prev_volu = kp_is_down(&kp_keys, KEY_VOLUMEUP) ? 1 : 0;
|
||
|
||
int sel = 1; /* 默认「否」:不误重启 */
|
||
int act = -1;
|
||
int cr_init = 0, cr_last_sel = -1; /* M2.9 Bug 4:dirty——仅 sel 变化才重画两钮 */
|
||
/* 标题/按键提示:打开时画一次(原实现把它们放主循环每 10ms 全刷,与 LCD 刷新竞争 →
|
||
* 「是/否」钮频闪;改为只在打开/状态变化时绘制)。标题在前面已画一次,这里画提示行。 */
|
||
if (mfont_ready) meow_font_drawtext((uint16_t *)fb, 20, 560,
|
||
meow_str_zh("power.confirm_hint", "音量切换 电源取消"), rgb565(mt0->onSurfaceVariant), 20);
|
||
else draw_text(20, 562, "VOL NAV POWER EXIT", 1, mt0->onSurfaceVariant);
|
||
meow_dirty_full(); /* M2.16:压暗列表+标题+提示作为一整帧呈现 */
|
||
for (;;) {
|
||
/* dirty 绘制:首次全画两钮;此后仅 sel 变化才重画(消频闪)→ 标脏 + present。 */
|
||
if (!cr_init) {
|
||
for (int i = 0; i < 2; i++) draw_cr_button(sel, i);
|
||
cr_init = 1; cr_last_sel = sel;
|
||
meow_ui_flush();
|
||
} else if (sel != cr_last_sel) {
|
||
draw_cr_button(sel, cr_last_sel); /* 旧选中:取消高亮 */
|
||
draw_cr_button(sel, sel); /* 新选中:高亮 */
|
||
meow_dirty_add((cr_last_sel == 0 ? 80 : 280) - 10, 412, 140, 76);
|
||
meow_dirty_add((sel == 0 ? 80 : 280) - 10, 412, 140, 76);
|
||
cr_last_sel = sel;
|
||
meow_ui_flush();
|
||
}
|
||
|
||
int vold = 0, volu = 0, play = 0, pwr = 0;
|
||
if (kp_keys.ok) { kp_poll(&kp_keys, NULL, NULL);
|
||
vold = kp_is_down(&kp_keys, KEY_VOLUMEDOWN); volu = kp_is_down(&kp_keys, KEY_VOLUMEUP);
|
||
play = kp_is_down(&kp_keys, KEY_PLAYPAUSE); }
|
||
if (kp_power.ok) { kp_poll(&kp_power, NULL, NULL); pwr = kp_is_down(&kp_power, KEY_POWER); }
|
||
if (vold && !prev_vold) sel = (sel + 1) % 2;
|
||
if (volu && !prev_volu) sel = (sel - 1 + 2) % 2;
|
||
/* M2.19:播放键不再作「是/确认」(让位给全局媒体控制)。确认框的确认
|
||
* 走触摸点选(下方 tfd 命中),电源键=取消(下行);播放键删除。 */
|
||
(void)play;
|
||
if (pwr && !prev_pwr) act = 3; /* 电源=取消 */
|
||
prev_vold = vold; prev_volu = volu; prev_pwr = pwr;
|
||
|
||
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 i = 0; i < 2; i++) {
|
||
int x0 = (i == 0) ? 80 : 280;
|
||
/* 命中「是/否」钮:x∈[x0-8, x0+128], y∈[412, 488](含端点) */
|
||
if (mt_in(&mt, x0 - 8, 412, 137, 77))
|
||
{ sel = i; act = i; break; }
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (act >= 0) break;
|
||
usleep(POLL_MS * 1000);
|
||
}
|
||
if (tfd >= 0) close(tfd);
|
||
if (act == 0) {
|
||
logmsg("reboot-to-player: YES -> default HibyOS + reboot");
|
||
if (sim_no_exec) { logmsg("reboot-to-player: [sim-no-exec] would reboot to hiby"); return 1; }
|
||
if (meow_power_action(POWER_BACK_HIBY) != MEOW_OK) {
|
||
logmsg("reboot-to-player: power service unavailable, abort (stay in MeowOS)");
|
||
return 0;
|
||
}
|
||
return 1;
|
||
}
|
||
logmsg("reboot-to-player: cancel");
|
||
return 0;
|
||
}
|
||
|