CleanTool v2.3.1 权限与后台机制拆包报告
CleanTool v2.3.1 权限与后台机制拆包报告返回竞品库
报告口径本页直接渲染本地报告真源;静态能力、动态观察、推断和线上未验证项不得互相替代。

CleanTool v2.3.1 权限与后台机制拆包报告#

文档日期:2026-10-12

1. 结论#

CleanTool 的后台不是单点保活,而是一组互相兜底的链路:进程启动前置 Provider → 特殊用途前台服务 → JobScheduler fallback → 15 分钟持久 Job → 15 分钟 PeriodicWork → 每日 10:00 Alarm → 开机/包更新/系统事件/Widget/FCM 再触发。主编排和 FGS 启动方法先检查通知权限/通知总开关;满足后,常驻 FGS 使用通知 ID 1,并在被销毁、任务划走或常驻通知删除时再次尝试启动。

静态代码证明“尝试”存在,不证明 Android 12L-16 与各 OEM 一定允许每次后台启动。特别是 targetSdk 36 对 FGS 启动、specialUse 类型和后台限制更严格,实际成功率属于 U。

2. 权限清单#

权限 来源 静态用途 风险/说明 等级
INTERNET App/SDK 广告、Firebase、Adjust、远端配置 网络数据类型需抓包核验 S1/U
ACCESS_NETWORK_STATE App/SDK 网络状态、广告、VPN判断 普通权限 S1
ACCESS_WIFI_STATE App/SDK Wi-Fi/网络工具与 SDK 普通权限 S1
READ_EXTERNAL_STORAGE App 文件扫描兼容 target 36 上已不足以覆盖现代媒体访问 S1
WRITE_EXTERNAL_STORAGE maxSdk=28 App 旧 Android 文件删除兼容 仅旧系统生效 S1
MANAGE_EXTERNAL_STORAGE App 全盘文件扫描、删除、FileObserver 高敏感 All files access S1
PACKAGE_USAGE_STATS App 最近使用、流量/应用统计 必须用户到特殊访问页授权 S1
BIND_NOTIFICATION_LISTENER_SERVICE(uses-permission) App Manifest 同时声明通知监听 Service 该权限本质用于保护 Service,普通 App 不能自行获得;用户需在设置授权 S1
REQUEST_DELETE_PACKAGES App 发起应用卸载 最终仍需系统/用户确认 S1
FOREGROUND_SERVICE App 常驻前台服务 target 36 受严格限制 S1
FOREGROUND_SERVICE_SPECIAL_USE App specialUse FGS 合规敏感;需与 Play 声明一致 S1
POST_NOTIFICATIONS App 常驻通知、场景提醒、FCM Android 13+ 运行时授权 S1
RECEIVE_BOOT_COMPLETED App 开机/更新后重建后台链路 自启动敏感 S1
WAKE_LOCK App/FCM/SDK 后台任务/消息处理 实际持锁点未逐一归属 S1/U
AD_ID 广告/归因 广告标识符 Data safety/同意管理相关 S1
ACCESS_ADSERVICES_TOPICS Google Ads Privacy Sandbox Topics SDK 合并权限 S1
ACCESS_ADSERVICES_ATTRIBUTION Google Ads Privacy Sandbox Attribution SDK 合并权限 S1
ACCESS_ADSERVICES_AD_ID Google Ads Privacy Sandbox Ad ID SDK 合并权限 S1
com.google.android.c2dm.permission.RECEIVE FCM 接收推送 SDK 合并权限 S1
Install Referrer bind Adjust/Ads 安装归因 SDK 合并权限 S1
VIBRATE 通知/SDK 通知振动 普通权限 S1
Play CHECK_LICENSE SDK Play 许可/完整性能力 未发现 App 自有直接调用 S1/U
Amazon Privacy Pass attestation SDK 广告/反欺诈 未发现 App 自有直接调用 S1/U
自定义 dynamic receiver signature 权限 AndroidX 保护动态 Receiver 库级基础设施 S1

Manifest 证据:jadx/resources/AndroidManifest.xml:15-30,67-79。

3. 用户授权路径#

能力 检查/跳转 证据
All files access Environment.isExternalStorageManager();MANAGE_APP_ALL_FILES_ACCESS_PERMISSION we.java:76-132
Usage access USAGE_ACCESS_SETTINGS + package URI MainActivity.java:140-162、SuccessEndActivity.java:1375-1378
Notification access ACTION_NOTIFICATION_LISTENER_SETTINGS;读取 enabled_notification_listeners c9.java:100、im2.java:377-404
Post notifications 运行时请求;拒绝后可跳 APP_NOTIFICATION_SETTINGS SplashActivity.java:182、v2.java:133-142

4. App 自有后台组件#

组件 触发/周期 行为 等级
WpCyBN ContentProvider 进程创建,initOrder=100 初始化 keep callback、生命周期、归因并调用 dn.a() S1(方法部分 JADX 失败)
gXXfik FGS 初始化、系统事件、Job、Worker、FCM、Widget、销毁/划走 ID 1 前台通知;API<34 返回 START_STICKY,API≥34 返回 START_NOT_STICKY S1
PsaeNNErXb JobService FGS start 异常 fallback,job ID 3857 5 秒最小延迟/7 秒 deadline;自身先前台化,再启动 FGS;15 秒后 jobFinished S1
sToBblBqZa JobService job ID 3432,15 分钟 onCreate 启动 FGS;onStartJob 再次排下一轮 S1
kcTBvDgL Worker Unique periodic work,15 分钟(WorkManager 下限) doWork() 调 im2.d() 并成功结束 S1
BpFZcYhmZ Receiver Alarm requestCode 74655;每天 10:00;type=2 / ELAPSED_REALTIME_WAKEUP 唤醒型 Alarm 到达后启动 FGS、记录 live point、重排次日 Alarm S1
ZPHDnIht Receiver BOOT_COMPLETED / MY_PACKAGE_REPLACED 启动 FGS、记录 live point S1
z7 动态 Receiver 9 类系统事件 500ms 去抖后启动 FGS并记录 live point S1
三个 AppWidget Provider Widget 广播 每次 onReceive 都调用 im2.d() S1
NaKMPne FCM Service FCM 消息/token 每次消息先调用 im2.d() S1

5. 保活链路#

5.1 启动入口#

WpCyBN.onCreate() 在 Application 之前执行。包名哈希校验通过后,它从 Manifest metadata 反射得到 KeepCallbackImp,注册 Activity lifecycle,并调用 dn.a(context)。见 WpCyBN.java:79-168。

KeepCallbackImp 的内置配置为:

  • 每日 Alarm 时间:10:00;
  • 周期 Job:15 分钟;
  • PeriodicWork:15 分钟;
  • 常驻通知 ID:1。

5.2 FGS 与 Job fallback#

dn.a() 与 im2.d() 都先经过 f92.a(context):Android 13+ 检查 POST_NOTIFICATIONS,旧版本检查 areNotificationsEnabled()。也就是说,静态主链显示通知权限/总开关未满足时不会继续启动这组 FGS、Job、Alarm 与 PeriodicWork。权限满足后,im2.d() 在 gXXfik.f4807c=false 时调用 startForegroundService;如果该调用抛异常,才调度 job ID 3857:

  • network type:none;
  • charging/device idle:false;
  • persisted:true;
  • minimum latency:5,000ms;
  • override deadline:7,000ms;
  • API 33+ priority:400。

因此 PsaeNNErXb 是异常兜底,不是常规固定周期 Job。见 im2.java:69-139。

5.3 周期与自重建#

  1. hd3.a() 以 job ID 3432 调度 sToBblBqZa,默认延迟 15 分钟、deadline 为延迟+5秒、persisted。
  2. sToBblBqZa.onCreate() 调 im2.d();onStartJob() 再调用 hd3.a(this),形成自重排。
  3. wu3.c() 创建 kcTBvDgL 的 unique periodic work,默认 15 分钟,flex 5 分钟。
  4. wu3.b() 每天 10:00 通过 AlarmManager.set(type=2 / ELAPSED_REALTIME_WAKEUP, ...) 安排唤醒型 Alarm;Receiver 触发后再次调用 wu3.b(),形成次日重排。

注意:Alarm 使用 wakeup 类型,但 set() 仍是非 exact 调度,可能被系统合批、Doze 或 OEM 策略延迟;10:00 是请求时间,不保证准点。JobScheduler/WorkManager 同样受系统配额约束,15 分钟是请求参数,不是精确定时承诺。

5.4 被杀/划任务/删通知后的动作#

  • gXXfik.onDestroy():标记未运行、停止前台,然后立即 im2.d()。
  • gXXfik.onTaskRemoved():立即 im2.d()。
  • 常驻通知 deleteIntent:API<35 使用 getForegroundService,API≥35 使用 getService,目标均为 gXXfik。
  • PsaeNNErXb.onCreate():若 FGS 未运行,再调用 startForegroundService(gXXfik)。

这些均是 S1“重启尝试”。Android 是否执行 deleteIntent、后台启动是否获准为 U。

5.5 系统事件拉起#

dn.a() 动态注册的 z7 监听:

  • SCREEN_OFF
  • SCREEN_ON
  • PACKAGE_REPLACED
  • CLOSE_SYSTEM_DIALOGS
  • CONFIGURATION_CHANGED
  • PACKAGE_REMOVED
  • USER_PRESENT
  • ACTION_POWER_CONNECTED
  • PACKAGE_ADDED

任一事件经每 action 500ms 去抖后调用 im2.d()。另有 Manifest Receiver 处理开机和自身包替换。

6. 通知监听与文件监听#

6.1 NotificationListener 的实际行为#

NotificationListener.onNotificationPosted() 对每条非 ongoing 且非 CleanTool 自身的通知执行:

  1. 读取来源包、标题、正文;
  2. cancelNotification(statusBarNotification.getKey());
  3. 异步保存/处理记录;
  4. 当日计数 +1;
  5. 计数达到 20 时尝试发出 notify_notifyClean 召回通知,并把计数清零。

异步分支实际构造 NotificationItem(id=0, pkg, title, content, time) 并通过 Room DAO 写入本地数据库;写入前对 title/content 做长度截断。可见入口只排除 ongoing 通知和 CleanTool 自身,没有第三方包白名单。证据:cw.java:704-724、j32.java:18-53、dx1.java:259-285。这意味着它是“撤下其他 App 通知 + 保存其包名/标题/正文/时间”的实现,而不仅是展示统计。数据库保留/清理周期、备份范围和是否上传仍为 U。

6.2 FileObserver#

App 启动协程会递归监听 Music、Podcasts、Ringtones、Alarms、Notifications、Movies、Downloads、Documents、Pictures、DCIM、Screenshots、Camera 等公共目录。新图片触发截图/图片类提醒,新非图片文件触发 notify_new_fileA。进入销毁生命周期状态时停止所有 observer。见 as0.java:18-70、zr0.java:30-100、xe.java:188-210、kf.java:83-101。

7. FCM 与 Remote Config#

7.1 FCM#

  • 自有服务:NaKMPne extends FirebaseMessagingService。
  • 新 token 同时传给 Adjust,并缓存后订阅内置 topic tZDmW。
  • 消息到达先启动/维持 FGS,再处理通知。
  • RemoteMessage.c()==1(Firebase 类中对应 delivered priority 为 high)时随机选择 10 条本地文案之一,action 统一为 notify_sub_high。
  • high-priority 代码可见后台、未锁屏、非横屏、距上次 live point ≥5 分钟、07:00-23:00 等判断,但实际执行体因 JADX 失败未完整恢复,记 U。

7.2 Remote Config#

已确认远控键:openTime、notifyCoolTime、day0_ad...day3_ad、VPN 广告开关、notify_interval_10m。未发现远端直接下发通知 title/body 的读取代码;当前通知文本来自本地 string 资源。线上参数值未验证。

8. 安全与合规观察#

发现 影响 等级
network_config 允许 cleartext traffic 允许 HTTP 明文链路;是否实际使用需抓包 S1/U
allowBackup=true 且备份规则为空 可能按系统默认备份符合条件的数据 S1/I
FileProvider 暴露 external storage 根路径 . 若 App 生成错误 URI/grant,分享面过宽 S1/I
gXXfik exported=true 且无组件权限 其他 App 可显式尝试启动该 Service;系统仍会施加 FGS 限制 S1
NotifyRepeatReceiver、WidgetCreateReceiver exported=true 且自定义 action 无权限 存在外部显式/广播触发面,需做输入验证 S1/I
OutOpenActivity exported=true 外部 App 可显式打开统一入口并传 action S1
NotificationListener 会取消其他 App 通知 用户信息可达性与合规风险高 S1
NotificationListener 本地保存第三方通知的 pkg/title/content/time,且 allowBackup=true 通知正文可能包含敏感信息;数据库是否被备份规则排除未确认 S1/U
specialUse FGS + 多重重启链 Play foreground service 声明与实际用途需严格一致 S1/I

9. 未验证项#

  1. targetSdk 36 真机上各后台入口的成功率、系统日志与电量影响。
  2. specialUse subtype/Play Console 申报内容。
  3. 远端参数是否关闭部分保活或调整周期。
  4. FCM high-priority 失败方法中的完整动作。
  5. 通知记录的保留/清理周期、备份范围和是否上传。
  6. 明文网络、外部 Provider 与 exported 组件是否能被实际利用。
竞品拆包报告库 · 逆向结论按证据等级阅读