Swift Clean v1.0.9 保活与拉活反编译代码册
Swift Clean v1.0.9 保活与拉活反编译代码册返回竞品库
报告口径本页直接渲染本地报告真源;静态能力、动态观察、推断和线上未验证项不得互相替代。

Swift Clean v1.0.9 保活与拉活反编译代码册#

样本:com.swiftclean.phone.managerpro v1.0.9 (11)
文档日期:2026-10-12
面向:Android 开发、测试与合规复核
标签:[S1] 反编译直接证据;[I] 合理判断;[U] 动态/线上未验证。

1. 阅读结论#

这套实现应拆成三层理解:

  1. 保活/恢复执行层 [S1]:前台服务 mowxgu + 启动失败 Job JMgHOxJfa + 15 分钟 JobScheduler + 15 分钟 WorkManager + Boot/package replaced + Alarm。
  2. 拉活/回前台层 [S1]:Activity 生命周期观察器在 App 从后台恢复时重开 FirstPage;广告外跳时用通知返回;ongoing 通知提供 6 个功能快捷入口。
  3. 通知召回层 [S1]:系统广播、FileObserver、周期候选、通知拦截计数与 FCM 高优先级统一进入 ID 21 的通知管线。

[I] 多路代码提高“有机会恢复”的覆盖面,不等于可突破系统 Force Stop 或 OEM 后台策略。开发对标时应复制业务目标,不应直接复制混淆实现或无保护 exported 组件。

2. 原始代码位置#

  • 普通完整反编译:jadx/sources/
  • 合并资源/Manifest:jadx/resources/
  • 关键失败方法 simple-mode 补证:jadx-simple/

JADX 1.5.5 全量运行报告 61 个错误。以下所有关键方法均给出稳定路径和行号;simple-mode 仍可能有 goto/类型推断误差,因此本册把“直接代码”和“解释”分开。

3. 启动初始化与总装配#

3.1 cIPhUu.onCreate():进程级早启动#

源码:jadx-simple/crown.arithmetic.floor.cIPhUu.java:63-160
Manifest:jadx/resources/AndroidManifest.xml:253-257

职责 [S1]:

  • ContentProvider、initOrder=100,进程创建阶段早于常规页面执行。
  • 保存 Application Context 与专用 SharedPreferences。
  • 从 Manifest metadata 反射加载 PageCellar 回调配置。
  • 记录首次基准时间。
  • 注册 qf.r ActivityLifecycleCallbacks。
  • 请求 Adjust attribution / adid。
  • 启动两个后台协程,再调用 qf.u.b(context) 装配保活体系。

忠实逻辑摘要:

onCreate() {
    appContext = getContext().getApplicationContext();
    prefs = context.getSharedPreferences(packageName + "_logger", 0);
    callback = reflectManifestMetadata("crown.cellar.config");
    recordFirstTimeIfMissing();
    application.registerActivityLifecycleCallbacks(qf.r.INSTANCE);
    requestAttributionAndAdId();
    launchStartupCoroutine();
    qf.u.b(context);
}

3.2 TotalPage.onCreate():业务 Application#

源码:jadx/sources/crown/arithmetic/floor/TotalPage.java:49-73

  • 注册 TotalPageObserver 到 Activity 生命周期与 ProcessLifecycleOwner。
  • 首次归因缺失时连接 Install Referrer。
  • 初始化 Adjust production 环境、允许后台发送、读取 adid。
  • 启动业务初始化协程。

初始化标识不在本文记录;开发如需核对只在授权环境查看源码,不应复制到文档或日志。

3.3 qf.u.b(Context):保活总开关#

源码:jadx/sources/qf/u.java:57-131

void initKeep(Context c) {
    createNotificationChannels(c);
    if (!notificationAllowed(c)) return;

    ensureForegroundService();
    scheduleAlarm(c);
    registerRuntimeSystemReceivers(c);
    registerReliveReceivers(c);
    schedulePersistentJob(c);
    schedulePeriodicWork(c);
}

关键边界 [S1]:通知不可用时,函数在创建 Channel 后不再进入主要 FGS/Alarm/Job/Work 装配。

静态配置集中在 jadx/sources/crown/arithmetic/floor/manager/PageCellar.java:39-55:Job 15 分钟、Work 15 分钟、业务通知追加间隔 3,500 ms、3 个 Channel、ongoing ID 20、业务 ID 21,以及两个公开后端地址。

4. 前台服务与自恢复#

4.1 qf.b.m():确保 FGS;失败转短 Job#

源码:jadx/sources/qf/b.java:213-282

if (notificationAllowed(context) && !mowxgu.running) {
    try {
        startForegroundService(explicitIntent(mowxgu.class));
    } catch (Throwable startFailure) {
        schedule JobInfo(
            id = 22002,
            service = JMgHOxJfa.class,
            persisted = true,
            minimumLatency = 5_000ms,
            overrideDeadline = about 7_000ms,
            priority = 400 on API 33+
        );
    }
}

4.2 mowxgu:主前台服务#

源码:jadx/sources/crown/arithmetic/floor/mowxgu.java:34-121

方法 行号 行为
a() 34-83 构造 ongoing 通知;ID 20;API >29 使用 FGS type 1073741824(specialUse);设置 running
onCreate() 97-101 立即调用 a()
onDestroy() 103-109 running=false、停止前台后调用 qf.b.m() 再尝试拉起
onStartCommand() 111-115 再调用 a();API >=34 返回 2/START_NOT_STICKY,否则 1/START_STICKY
onTaskRemoved() 117-121 最近任务移除时调用 qf.b.m()

mowxgu.a() 还包含一个隐藏调试开关:约 5 秒窗口内服务启动调用累计 10 次会翻转日志 flag;这不是业务保活条件 [S1]。

4.3 JMgHOxJfa:FGS 启动失败兜底 Job#

源码:

  • jadx/sources/crown/arithmetic/floor/JMgHOxJfa.java:44-119,121-153
  • jadx/sources/qf/d.java:42-81

职责 [S1]:JobService 自己先用 ongoing ID 20 进入 foreground,然后显式启动 mowxgu;onStartJob() 启动协程,等待 15 秒后 jobFinished(params,false)。

5. 三种周期调度#

5.1 AlarmManager#

调度:jadx/sources/qf/b.java:295-346
接收:jadx/sources/crown/arithmetic/floor/kQuACgQQ.java:17-25

PendingIntent pi = getBroadcast(context, 18488, Intent(kQuACgQQ.class), flags);
alarm.cancel(pi);
LocalTime t = parseConfiguredTimeOrDefault(10, 0);
long delta = nextOccurrence(t) - System.currentTimeMillis();
alarm.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
          SystemClock.elapsedRealtime() + delta,
          pi);

纠错重点:type=2 对应 ELAPSED_REALTIME_WAKEUP(唤醒型);调用 set() 而非 setExact*(),因此具 wakeup 但允许系统漂移/合并。receiver 触发后依次 ensureForegroundService()、进入周期回调、重新排下次 Alarm。

5.2 WorkManager#

调度:jadx/sources/qf/b.java:419-459
Worker:jadx/sources/crown/arithmetic/floor/ZOaubC.java:14-31

PeriodicWorkRequest request = periodic(
    worker = ZOaubC.class,
    interval = max(configMinutes, 15min),
    flex = max(5min, allowedFlex)
);
enqueueUniquePeriodicWork(obfuscatedUniqueName, REPLACE_OR_KEEP_MODE_1, request);

doWork() {
    ensureForegroundService();
    enterPeriodicCallback("work");
    return success();
}

5.3 JobScheduler#

调度:jadx/sources/qf/b.java:461-507
JobService:jadx/sources/crown/arithmetic/floor/vjfcJyUsQs.java:18-50

参数 [S1]:Job ID 20、无网络/充电/idle 要求、persisted、minimumLatency 15 分钟、overrideDeadline 约为 15 分钟 + 5 秒、API 33+ priority 400。Job 创建时确保 FGS并进入周期回调;onStartJob() 重新安排下一次。

6. Boot、升级、通知删除与循环广播#

类/方法 路径:行号 直接行为
weqTnpsB.onReceive() jadx/sources/crown/arithmetic/floor/weqTnpsB.java:18-35 Boot/package replaced/动态 action 后确保 FGS;按 action 进入不同周期回调或取消重复通知
CycleReceiver.onReceive() .../notify/CycleReceiver.java:13-23 收到 base.cycle.break 后发送 ongoing 通知对应 PendingIntent
kQuACgQQ.onReceive() .../kQuACgQQ.java:17-25 Alarm 触发:确保 FGS、周期回调、重排 Alarm
ZOaubC.doWork() .../ZOaubC.java:22-30 Work 触发:确保 FGS、周期回调
vjfcJyUsQs.onCreate/onStartJob() .../vjfcJyUsQs.java:18-45 Job 触发:确保 FGS、周期回调、重排 Job
qf.c.onReceive() jadx/sources/qf/c.java:20-92 对 9 类动态系统广播做 500 ms 去重,然后确保 FGS并进入周期回调
qf.i.onReceive() jadx/sources/qf/i.java:19-42 设备解锁后调用 TotalPageObserver.e(),再反注册自身

Manifest 静态 action 直接确认 BOOT_COMPLETED、MY_PACKAGE_REPLACED、base.cycle.break。qf.u 中 qf.c 的 9 个动态 action 已通过常量解码与 hash 分支交叉确认 [S1]:USER_PRESENT、ACTION_POWER_CONNECTED、SCREEN_ON、SCREEN_OFF、PACKAGE_ADDED、PACKAGE_REMOVED、PACKAGE_REPLACED、CLOSE_SYSTEM_DIALOGS、CONFIGURATION_CHANGED。仍有少量删除/内部回调 action 名称未稳定恢复 [U]。

7. 生命周期拉回与广告恢复#

7.1 TotalPageObserver.e():恢复时重开 FirstPage#

源码:jadx-simple/crown.arithmetic.floor.TotalPageObserver.java:69-116

Activity top = currentActivity();
if (top == null || top instanceof AutoBackPage ||
    top instanceof AgreePage || top instanceof FirstPage ||
    isAdActivity(top)) return;

if (deviceLocked()) {
    register USER_PRESENT receiver;
} else {
    top.startActivity(Intent(top, FirstPage.class).addFlags(0x24000000));
}

onStateChanged() 的关键状态 [S1]:

  • ON_STOP:标记 App 后台;若正在广告页,处理广告跳过/结束;若广告状态标记存在,构造广告恢复通知。
  • ON_RESUME:如果此前确实处于后台,清标记并调用 e()。
  • 广告恢复:notify_click_ad 进入 FirstPage;notify_click_applovin 进入 AutoBackPage。

源码:jadx-simple/...TotalPageObserver.java:225-365。

7.2 qf.r:Activity 计数、通知点击与后台任务#

源码:jadx/sources/qf/r.java:23-142

方法 行号 行为
a(Activity) 23-46 消费通知点击 extras、记录 action、取消匹配的重复任务
onActivityStarted() 75-135 检查通知权限、有限次数请求 FCM token/上传、再次装配保活、activityCount++、进入前台回调并启动网络协程
onActivityStopped() 138-142 activityCount--;FCM 用此判断 App 是否有活动页面

8. 系统事件与文件事件召回代码#

8.1 注册入口 qf.h.invokeSuspend()#

源码:jadx/sources/qf/h.java:43-182

  • 初始化 Firebase Remote Config。
  • Android 10+ 递归监听 Music、Podcasts、Ringtones、Alarms、Notifications、Movies、Downloads、Documents、Pictures、DCIM 与 Screenshot 目录。
  • 注册 USER_PRESENT、SCREEN_OFF、CLOSE_SYSTEM_DIALOGS、CONFIGURATION_CHANGED、PACKAGE_ADDED/REMOVED、POWER_CONNECTED/DISCONNECTED、CONNECTIVITY_CHANGE。

8.2 广播分发 gd.c.onReceive()#

源码:jadx-simple/gd.c.java:75-218

系统事件 代码动作
PACKAGE_ADDED 构造 notify_installapp;能取 label 时用动态文案
PACKAGE_REMOVED 构造 notify_uninstallapp
ACTION_POWER_CONNECTED 构造 notify_startcharge
ACTION_POWER_DISCONNECTED 构造 notify_stopcharge
USER_PRESENT 启动 uf.a,2 秒后选择未清理天数或 4 个随机解锁模板
CLOSE_SYSTEM_DIALOGS/recentapps 启动 uf.b,1.5 秒后 notify_recenttask
CONNECTIVITY_CHANGE 启动 uf.c,1.6 秒后仅在非蜂窝→蜂窝时 notify_SwitchTraffic

8.3 FileObserver uf.d.onEvent()#

源码:jadx/sources/uf/d.java:30-105

  • Screenshot 目录:取文件名与缩略图,构造 notify_screenshots。
  • 其他公共目录:取文件名,构造 notify_downloadfile。
  • 两类都继续进入通知总闸,不代表每个文件事件都会展示。

8.4 周期候选 tf.a0.invokeSuspend()#

源码:jadx-simple/tf.a0.java:24-87

delay(2_000ms);
action = randomOf(
  "notify_timing_cache01",
  "notify_timing_cache02",
  "notify_timing_bigfile",
  "notify_timing_appmanage"
);
buildLocalizedNotification(action);
NotifySender.send(context, config);

9. 通知总闸、Channel、重复刷新与路由#

9.1 a.a.r(Context, uf.i):全部本地通知总闸#

源码:jadx-simple/a.a.java:503-916

忠实伪代码:

sendLocalNotify(config) {
    cancelPreviousRepeat(reason = 4);
    if (!notificationAllowed()) return;
    if (!appInBackground()) return;
    if (deviceLocked()) return;

    if (!isAdRecovery(config.action) && installAge < 5min) return;

    if (attributionBranchFalse && action != HIGH_PRIORITY) {
        if (0 < now - globalLastNotify < 2h) return;
    } else if (action != HIGH_PRIORITY) {
        if (!passesPerActionCooldown(action)) return;
    }

    postId21AndStartRepeat(config);
    updateGlobalAndPerActionTimestamps();
}

完整逐 action 冷却见《拉活通知规则与文案全量报告》;代码行集中在 a.a.java:693-890。

9.2 qf.t#

源码:jadx/sources/qf/t.java

方法 行号 行为
a(Context) 52-87 创建 ongoing、正常业务、静默业务 3 个 Channel
b(Context) 89-109 未锁屏时刷新 ongoing ID 20
c(...) 111-196 构造业务自定义 Notification;选择 normal/silent Channel
f(Context) 234-299 构造 ongoing 通知与 6 个快捷入口
e(...) 301-342 首发 ID 21,记录 action,启动重复 coroutine
d(int) 198-232 取消/终止正在重复的通知任务

9.3 qf.w.invokeSuspend():短时重复刷新#

源码:jadx-simple/qf.w.java:60-151

repeatCount = manufacturer.equalsIgnoreCase("samsung") ? 1 : 3;
for (i = 0; i < repeatCount; i++) {
    delay(3_500ms);
    if (!stillBackground || deviceLocked || landscape) break;
    notify(id = 21, channel = silentChannel, sameContent);
}

9.4 uf.j 与 MainPage:点击路由#

源码:

  • jadx/sources/uf/j.java:23-97
  • jadx/sources/crown/arithmetic/floor/page/MainPage.java:97-318

uf.j.a() 默认把业务通知点到 FirstPage;只有 notify_click_applovin 直达 AutoBackPage。MainPage.m() 再按 KEY_FROM 路由 Cache、Large File、App Manager、Screenshot、Network、Notification Clean 或 RAM。

10. Notification Listener 闭环#

源码:

  • 监听/取消:jadx/sources/crown/arithmetic/floor/notify/NotifyManagerServices.java:51-75
  • 今日计数:jadx-simple/crown.arithmetic.floor.notify.NotifyManagerServices.java:55-103
onNotificationPosted(sbn) {
    if (thirdParty && !ongoing && !whitelisted) {
        cancelNotification(sbn.key);
        saveTitleAndTextToRoom();
        long todayCount = queryTodayBlockedCount();
        if (todayCount >= 20 && todayCount % 10 == 0) {
            sendLocalNotify("notify_block_notification");
        }
    }
}

11. FCM 拉活通知代码#

源码:jadx-simple/crown.arithmetic.floor.wSfChcdBg.java:50-254

onMessageReceived(message) {
    ensureForegroundService();
    enterPeriodicCallback("fcm");

    if (incomingPriority != HIGH) return;
    if (!notificationAllowed()) return;
    if (activityCount > 0) return;
    if (landscape) return;
    if (ageFromStartupBaseline < 5min) return;
    if (localHour < 7 || localHour >= 23) return;

    index = random(0..9);
    content = localizedHighPriorityCopy(index);
    postBusinessNotification(id = 21,
        internalName = "notify_highpriority_" + index,
        clickAction = "notify_highpriority");
    recordDeliveredPriorityOrPriorityReduction();
}

onNewToken(token) {
    forwardToAttributionSdkAndOwnBackend(token);
}

[U] simple-mode 未稳定恢复“锁屏直接拒绝”分支,因此伪代码不加入该条件;服务端发送策略不在 APK。

12. Remote Config、FCM token 与自有后端#

方法 路径:行号 保活/拉活相关职责
tf.u.c() jadx-simple/tf.u.java:221-300 RC 最短 fetch 3600 秒、fetch/activate、realtime listener
tf.r.b() jadx/sources/tf/r.java:39-48 相关广告/配置 key 更新时重新应用
qf.r.onActivityStarted() jadx/sources/qf/r.java:75-135 有限次数获取/同步 FCM token,启动网络任务
qf.b.p() jadx/sources/qf/b.java:348-384 通知可用时向 FCM 订阅配置中的 topic;具体 topic 不写入文档
wSfChcdBg.d() jadx-simple/...wSfChcdBg.java:250-254 token 更新转交统一上传路径
qf.q.invokeSuspend() jadx/sources/qf/q.java:48-217 IP/条件后端,8 秒超时与指数退避
qf.p.invokeSuspend() jadx-simple/qf.p.java:57-246 包名 + 本地 ID/token 类值上报,8 秒超时与指数退避

报告不记录 SDK 初始化标识、topic、FCM token、设备标识或认证信息。

13. App 自有保活/拉活方法完整索引#

层 类/方法 源码范围 作用
启动 cIPhUu.onCreate jadx-simple/crown.arithmetic.floor.cIPhUu.java:63-160 Provider 早启动、配置反射、生命周期、后台总装配
启动 TotalPage.onCreate jadx/sources/crown/arithmetic/floor/TotalPage.java:49-73 归因、生命周期与业务初始化
配置 PageCellar.<clinit> jadx/sources/crown/arithmetic/floor/manager/PageCellar.java:39-55 调度周期、后端、Channel、ID、追加间隔
总装配 qf.u.b jadx/sources/qf/u.java:57-131 Channel、FGS、Alarm、receiver、Job、Work
权限 qf.e.a jadx/sources/qf/e.java:29-32 通知是否可用
FGS qf.b.m jadx/sources/qf/b.java:213-282 启动主 FGS;失败 Job 兜底
FGS mowxgu.a/onCreate/onDestroy/onStartCommand/onTaskRemoved .../mowxgu.java:34-121 ongoing、sticky 与主动重启
兜底 JMgHOxJfa .../JMgHOxJfa.java:44-153 失败 Job 自己前台化并启动主 FGS
兜底 qf.d.invokeSuspend jadx/sources/qf/d.java:42-81 15 秒后结束失败 Job
Alarm qf.b.o jadx/sources/qf/b.java:295-346 计算未来时刻并 ELAPSED_REALTIME_WAKEUP set()
Alarm kQuACgQQ.onReceive .../kQuACgQQ.java:17-25 保活、周期回调、重排
Work qf.b.u jadx/sources/qf/b.java:419-459 15 分钟 unique periodic work
Work ZOaubC.doWork .../ZOaubC.java:22-30 确保 FGS并进入周期回调
Job qf.b.v jadx/sources/qf/b.java:461-507 持久 15 分钟 Job ID 20
Job vjfcJyUsQs .../vjfcJyUsQs.java:18-50 确保 FGS、回调、重排
Boot weqTnpsB.onReceive .../weqTnpsB.java:18-35 Boot/升级/动态 action 后恢复
Cycle CycleReceiver.onReceive .../notify/CycleReceiver.java:13-23 发送 ongoing PendingIntent
广播保活 qf.c.onReceive jadx/sources/qf/c.java:20-92 9 类系统广播、500 ms 去重、确保 FGS
解锁拉回 qf.i.onReceive jadx/sources/qf/i.java:19-42 USER_PRESENT 后重进 TotalPageObserver.e()
回调 qf.v.d jadx/sources/qf/v.java:89-141 周期来源汇合、定时通知候选、事件上报/token 同步
生命周期 qf.r jadx/sources/qf/r.java:23-142 点击消费、Activity 计数、前台任务、token 同步
生命周期 TotalPageObserver.e/onStateChanged jadx-simple/...TotalPageObserver.java:69-116,225-365 热恢复重开 FirstPage、广告回跳通知
事件注册 qf.h.invokeSuspend jadx/sources/qf/h.java:43-182 FileObserver + 7 类系统广播
广播 gd.c.onReceive jadx-simple/gd.c.java:75-218 安装、卸载、充电、解锁、最近任务、网络触发
解锁 uf.a.invokeSuspend jadx-simple/uf.a.java:42-136 2 秒后未清理/随机解锁候选
最近任务 uf.b.invokeSuspend jadx/sources/uf/b.java:37-62 1.5 秒后候选
网络 uf.c.invokeSuspend jadx/sources/uf/c.java:38-71 1.6 秒后蜂窝切换候选
文件 uf.d.onEvent jadx/sources/uf/d.java:30-105 截图/新文件候选
定时通知 tf.a0.invokeSuspend jadx-simple/tf.a0.java:24-87 2 秒后 4 选 1
通知总闸 a.a.r jadx-simple/a.a.java:503-916 权限、后台、锁屏、安装时长、归因、冷却
通知构建 qf.t.a/b/c/d/e/f jadx/sources/qf/t.java:52-342 Channel、ID20/21、自定义布局、重复控制
通知重复 qf.w.invokeSuspend jadx-simple/qf.w.java:60-151 3.5 秒静默刷新
通知路由 uf.j.a/c/d jadx/sources/uf/j.java:23-97 FirstPage/AutoBack 与 ongoing 快捷入口
通知路由 MainPage.m .../page/MainPage.java:97-318 action → func
通知监听 NotifyManagerServices.onNotificationPosted/checkCount 普通 :51-75;simple :55-103 取消/记录第三方通知,20/10 计数召回
FCM wSfChcdBg.c/d jadx-simple/...wSfChcdBg.java:50-254 高优先级通知、priority telemetry、token 更新
RC tf.u.c/e、tf.r.b simple tf.u:221-300;普通 tf/u.java:71-126、tf/r.java:39-48 拉取/实时应用广告与配置
后端 qf.q.invokeSuspend jadx/sources/qf/q.java:48-217 条件检查、指数退避
后端 qf.p.invokeSuspend jadx-simple/qf.p.java:57-246 ID/token 类数据上传、指数退避

14. 开发复核清单#

  1. 先按上述路径逐个打开源码,不要只看混淆类名。
  2. 对 a.a.r、gd.c、tf.a0、qf.w、wSfChcdBg、TotalPageObserver 使用 simple-mode 文件;普通模式相应方法直接抛 UnsupportedOperationException。
  3. 对 Alarm 明确按 ELAPSED_REALTIME_WAKEUP + 非 exact set() 理解。
  4. 对 Android 14+ 的 specialUse FGS、通知拒绝、Doze、最近任务划掉、OEM、自启动和 Force Stop 单独做矩阵。
  5. 对 exported mowxgu、CycleReceiver、kQuACgQQ、MainPage 做显式 Intent/广播滥用测试。
  6. 抓包核对两个公开后端的字段与重试;任何 token、ID 或认证信息只在受控环境查看,不写报告。

15. 未验证项#

  • [U] simple-mode 的 goto/类型推断可能对极少数边缘分支有偏差;关键主路径已与 Manifest、资源和调用方交叉对照。
  • [U] 线上 Remote Config、FCM 服务端策略、topic、广告 waterfall 与后端响应未知。
  • [U] 本轮未操作设备,不能用本册单独证明划卡、Doze、待机桶、重启或 Force Stop 后的实际存活时长。
  • [U] 未对 Android 8–16/OEM 做兼容矩阵,也未做 exported 组件安全利用测试。
竞品拆包报告库 · 逆向结论按证据等级阅读