Storage Manager v1.0.5 保活与拉活反编译代码册#
文档日期:2026-10-14
用途:给开发直接回查前台服务、进程存活、开机/FCM 拉活、任务移除、调度和通知点击代码。
范围:列出当前 APK 中识别到的一方保活/拉活主链全部入口与关键实现;不展开 Google/Firebase/广告 SDK 内部通用代码。JADX 有 147 个方法级错误,残缺位置已标明。
一、机制总图#
App 首启 / Boot / 高优先级 FCM data
│
▼
w3.a.q()
│ notification_is_open=true
▼
startForegroundService / startService
│
▼
LongRunningService
├─ startForeground(ID=1001, specialUse)
├─ return START_STICKY
├─ 屏幕/方向/前后台监听
├─ 卸载/电池事件监听
├─ 每 60 秒检查本地提醒
└─ 每 2 小时内部事件上报
本地提醒 ID=2000 / FCM 通知 ID>=3001
│ 点击
▼
SplashActivity
│ scan_type 等 extras
▼
Junk / App Manager / Battery / Photo / Large
二、Manifest 声明#
路径:jadx/resources/AndroidManifest.xml:218-249
<service
android:name="com.sweepeeer.manager.ssstorage.service.LongRunningService"
android:exported="false"
android:foregroundServiceType="specialUse">
<property
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="Clean up junk files in the background" />
</service>
<receiver
android:name="com.sweepeeer.manager.ssstorage.receiver.StartReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
<action android:name="com.huawei.android.intent.action.STARTUP_COMPLETED" />
</intent-filter>
</receiver>
同时声明:POST_NOTIFICATIONS、FOREGROUND_SERVICE、FOREGROUND_SERVICE_SPECIAL_USE、RECEIVE_BOOT_COMPLETED、WAKE_LOCK、FCM RECEIVE。(S1)
三、统一服务启动入口#
路径:jadx/sources/w3/a.java:77-91
public static void q(Context context, String str) {
kotlin.jvm.internal.a.a(context, "context");
if (LongRunningService.f23061m0) {
return;
}
y1.Companion.getClass();
if (x1.qazwsxedcrfvtgbyhnujmikolp("notification_is_open", true)) {
Intent intent = new Intent(context, (Class<?>) LongRunningService.class);
intent.putExtra("data_start", str);
if (Build.VERSION.SDK_INT >= 26) {
context.startForegroundService(intent);
} else {
context.startService(intent);
}
}
}
含义:服务是否启动与 App 内总通知开关绑定;静态布尔值认为服务已活时直接返回。该静态值不能跨进程死亡保存。(S1)
四、前台服务创建与 ID 1001#
路径:LongRunningService.java:411-435
@Override
public final void onCreate() {
super.onCreate();
try {
this.f23063f0 = new com.sweepeeer.manager.ssstorage.notification.ponmlkjihgfedcba(this);
Notification notification = ponmlkjihgfedcba();
int sdk = Build.VERSION.SDK_INT;
if (sdk >= 34) {
startForeground(1001, notification, 1073741824);
} else {
startForeground(1001, notification);
}
f23061m0 = true;
} catch (Exception e) {
e.printStackTrace();
f23061m0 = false;
if (Build.VERSION.SDK_INT >= 26) {
stopSelf();
return;
}
}
BuildersKt__Builders_commonKt.launch$default(
this.f23065h0,
Dispatchers.getIO(),
null,
new LongRunningService$initializeComponentsInBackground$1(this, null),
2,
null
);
}
1073741824 对应 API 34 的 FOREGROUND_SERVICE_TYPE_SPECIAL_USE 位。真机 dumpsys 观测到 isForeground=true、foregroundId=1001。(S1/D1)
五、onStartCommand 与 START_STICKY#
路径:LongRunningService.java:490-525
@Override
public final int onStartCommand(Intent intent, int flags, int startId) {
String source;
if (intent == null || (source = intent.getStringExtra("data_start")) == null) {
source = "";
}
if (!source.equals("") && source.equals("data_start")) {
i.trackEvent$default(i.INSTANCE, "Firebase_Data_StartService", null, null, false, 2, 14, null);
}
try {
Notification notification = this.f23063f0.i();
if (Build.VERSION.SDK_INT >= 34) {
startForeground(1001, notification, 1073741824);
} else {
startForeground(1001, notification);
}
f23061m0 = true;
i.trackEvent$default(i.INSTANCE, "Notify_Show", null, null, false, 2, 14, null);
Job job = this.f23067j0;
if (job != null && job.isActive()) {
return 1;
}
this.f23067j0 = BuildersKt__Builders_commonKt.launch$default(
this.f23065h0, null, null,
new LongRunningService$startPeriodicReporting$2(this, null),
3, null
);
return 1;
} catch (Exception e) {
stopSelf();
return 2;
}
}
- 返回
1=START_STICKY:进程被系统回收后,系统可尝试重建服务。 - 返回
2=START_NOT_STICKY:启动异常时不要求重建。 - 这不等于能突破 Force Stop。(S1/D1)
六、常驻通知构建#
路径:notification/ponmlkjihgfedcba.java:921-960,983-1008
NotificationCompat.Builder builder =
new NotificationCompat.Builder(context, "resident_notification_channel")
.setSmallIcon(R.drawable.icon_notification)
.setOngoing(true)
.setPriority(1)
.setAutoCancel(false)
.setGroupAlertBehavior(0)
.setGroup("foreground_service_isolated_group_" + System.currentTimeMillis())
.setGroupSummary(false)
.setOnlyAlertOnce(false)
.setSortKey(UUID.randomUUID().toString())
.setLocalOnly(true)
.setCategory(NotificationCompat.CATEGORY_SERVICE)
.setWhen(System.currentTimeMillis());
builder.setCustomContentView(collapsed);
builder.setCustomBigContentView(expanded);
builder.setStyle(new NotificationCompat.DecoratedCustomViewStyle());
builder.setContentIntent(
abcdefghijklmnopqrstuvwx(this, "JUNK_CLEANER", 1000, null, null, 28)
);
快捷入口:
// collapsed
H(this, remoteViews, "ll_junk", "JUNK_CLEANER", 1, "resident_jc", 80);
H(this, remoteViews, "ll_appManager", "APP_MANAGER", 2, "resident_am", 80);
H(this, remoteViews, "ll_battery_info", "BATTERY_INFO", 3, "resident_bi", 80);
// expanded 使用 requestCode 4/5/6,路由相同
七、服务初始化的监控组件#
路径:LongRunningService$initializeComponentsInBackground$1.java:69-178,229-247
// 启动初始化前先延迟 2 秒,再切 Main dispatcher
DelayKt.delay(2000L, continuation);
BuildersKt.withContext(Dispatchers.getMain(), initBlock, continuation);
方向轮询:
h2Var.zyxwvutsrqponmlkji = new Runnable() {
@Override public void run() {
h2Var.qazwsxedcrfvtgbyhnujmikolp();
if (h2Var.abcdefghijklmnopqrstuvwx) {
handler.postDelayed(this, 1000L);
}
}
};
handler.postDelayed(h2Var.zyxwvutsrqponmlkji, 1000L);
屏幕状态:
IntentFilter screen = new IntentFilter();
screen.addAction("android.intent.action.SCREEN_ON");
screen.addAction("android.intent.action.SCREEN_OFF");
screen.addAction("android.intent.action.USER_PRESENT");
service.registerReceiver(screenMonitor.receiver, screen);
首次启动、调度与卸载监控:
if (!prefs.contains("first_start_time")) {
prefs.encode("first_start_time", System.currentTimeMillis());
}
service.d(); // 每日计数重置
service.f(); // 启动 60 秒通知循环
w.Companion.qazwsxedcrfvtgbyhnujmikolp(service).ponmlkjihgfedcba(); // 卸载监控
电量/电源监听:
IntentFilter power = new IntentFilter();
power.addAction("android.intent.action.BATTERY_CHANGED");
power.addAction("android.intent.action.ACTION_POWER_CONNECTED");
power.addAction("android.intent.action.ACTION_POWER_DISCONNECTED");
power.addAction("android.intent.action.BATTERY_LOW");
power.addAction("android.intent.action.BATTERY_OKAY");
context.registerReceiver(powerReceiver, power);
八、60 秒通知资格循环#
路径:LongRunningService$startNotificationScheduler$1.java:37-54
while (CoroutineScopeKt.isActive(coroutineScope)) {
LongRunningService.qazwsxedcrfvtgbyhnujmikolp(this.this$0);
if (DelayKt.delay(60000L, this) == coroutine_suspended) {
return coroutine_suspended;
}
}
它是 App 自有本地提醒的主循环;不是系统级 Alarm,因此依赖前台服务持续存活。(S1)
九、通知门禁关键代码#
路径:LongRunningService.java:233-343
int style = notificationManager.x();
// referrer==7 时受 reminderstatus 控制
if (prefs.getInt("referrer", 7) == 7) {
NotifyConfigData cfg = MyApp.instance.f22975f0;
if (cfg != null && !cfg.getReminderstatus()) return;
}
if (!MyApp.instance.f22980k0) return; // 屏幕不适合/锁屏
if (AppState.isForeground(service)) return; // App 在前台
TimeSlot slot = findCurrentSlot(hour);
if (slot == null) return;
if (todayCount(slot) >= slot.maxCount) return;
if (MyApp.instance.f22979j0) return; // 横屏
if (shouldShowByFirstDelayOrInterval(now)) {
if (notificationManager.show(style)) {
recordNotificationShown(slot, now);
}
}
注:变量/方法名为便于阅读的等价语义;逐行原始输出见上述行号。完整规则见《拉活通知规则与文案全量报告》。(S1)
十、onTaskRemoved:只检查通知,不显式重启#
路径:LongRunningService.java:88-130,529-533
@Override
public final void onTaskRemoved(Intent intent) {
super.onTaskRemoved(intent);
BuildersKt__Builders_commonKt.launch$default(
this.f23065h0, null, null, new AnonymousClass1(null), 3, null
);
}
// AnonymousClass1
DelayKt.delay(500L, this);
LongRunningService.qazwsxedcrfvtgbyhnujmikolp(LongRunningService.this);
没有 startService() / startForegroundService();本轮划卡后仍活是“原 FGS 未死”,不是该回调完成了拉起。(S1/D1)
十一、Boot 拉活#
路径:receiver/StartReceiver.java:14-37
String action = intent != null ? intent.getAction() : null;
if (action != null) {
int hash = action.hashCode();
if (hash != -905063602) {
if (hash != 798292259 || !action.equals("android.intent.action.BOOT_COMPLETED")) {
return;
}
} else if (!action.equals("android.intent.action.LOCKED_BOOT_COMPLETED")) {
return;
}
w3.a.q(context, "");
}
Manifest 虽还声明 Huawei STARTUP_COMPLETED,该 onReceive 没有处理它。(S1)
十二、FCM 拉活与远程通知#
路径:service/FirebaseMsgService.java:15-56
public final void onMessageReceived(RemoteMessage message) {
Map<String, String> data = message.getData();
if (!data.isEmpty() && message.getPriority() == 1) {
i.trackEvent$default(i.INSTANCE, "Firebase_Data_Get", "type", "high", false, 2, 8, null);
w3.a.q(this, "data_start");
}
RemoteMessage.Notification notification = message.getNotification();
if (notification != null) {
new notification.zyxwvutsrqponmlkjihgfedcba(this)
.qazwsxedcrfvtgbyhnujmikolp(
String.valueOf(notification.getTitle()),
String.valueOf(notification.getBody())
);
}
}
public final void onNewToken(String token) {
super.onNewToken(token);
i.zyxwvutsrqponmlkji(token);
}
- 只有 high priority data 分支显式启动 FGS;普通优先级只记录降级日志。(S1)
- notification payload 用服务端标题/正文发布简单通知,APK 无法枚举服务端全部文案。(S1/U)
- Token 日志/上报逻辑存在;本报告不记录任何真实 Token。(安全边界)
十三、FCM 简单通知#
路径:notification/zyxwvutsrqponmlkjihgfedcba.java:36-80
if (prefs.getBoolean("notification_is_open", true)
&& NotificationManagerCompat.from(context).areNotificationsEnabled()) {
int id = counter.incrementAndGet(); // 从 3001 开始
Intent intent = new Intent(context, SplashActivity.class);
intent.setFlags(268468224);
Notification notification = new NotificationCompat.Builder(context, "simple_notification_channel")
.setSmallIcon(R.drawable.icon_notification)
.setContentTitle(serverTitle)
.setContentText(serverBody)
.setAutoCancel(true)
.setPriority(2)
.setDefaults(-1)
.setVisibility(1)
.setCategory("msg")
.setStyle(new NotificationCompat.BigTextStyle().bigText(serverBody))
.setContentIntent(PendingIntent.getActivity(context, id, intent, flags))
.build();
notificationManager.notify(id, notification);
}
十四、WorkManager 清理旧任务#
路径:workmanage/NotificationWorkManager$initializeWorkManager$1.java:43-58
WorkManager manager = WorkManager.getInstance(context);
List<WorkInfo> list = manager.getWorkInfosForUniqueWork("periodic_notification_work").get();
WorkInfo first = firstOrNull(list);
if (first != null) {
manager.cancelUniqueWork("periodic_notification_work");
}
当前一方代码找到的是“发现并取消旧周期通知 Work”,没有找到重新 enqueue 同名周期任务的调用。(S1)
十五、提醒被删除后的取消逻辑#
路径:receiver/NotifyDeleteReceiver.java:15-24
if (Objects.equals(intent != null ? intent.getAction() : null, "notifyDeleteAction")) {
Job job = MyApp.instance.X;
if (job != null) {
Job.DefaultImpls.cancel$default(job, null, 1, null);
}
}
本地提醒 ID 2000 绑定该 deleteIntent;用户划掉提醒后会取消用于重复显示/更新的协程 Job。(S1)
十六、每 2 小时内部上报#
路径:LongRunningService$startPeriodicReporting$2.java:33-148
等价逻辑:
trackEvent("A");
delay(7_200_000L);
while (scope.isActive()) {
trackEvent("A");
delay(7_200_000L);
}
// 异常时延迟 180_000ms,再尝试恢复该协程
该方法反编译失败,但指令残留明确包含 7,200,000ms 和 180,000ms。它是后台埋点循环,不是恢复服务的系统入口。(S1)
十七、销毁清理#
路径:LongRunningService.java:439-486
@Override
public final void onDestroy() {
f23061m0 = false;
cancel(notificationSchedulerJob);
cancel(periodicReportingJob);
cancel(serviceScope);
cancel(stickyObserverJob);
stopOrientationMonitor();
unregisterScreenReceiver();
stopUninstallMonitor();
stopPowerMonitor();
stopForeground(1);
super.onDestroy();
}
原始代码逐项取消 Job、Handler、动态 Receiver 和监控器,没有在 onDestroy() 自启或注册闹钟。(S1)
十八、开发复核清单#
| 问题 | 当前结论 | 建议验证 |
|---|---|---|
| 划卡后是否重启服务 | 没有;原服务继续存活 | 主动杀进程而非划卡,观察 START_STICKY |
| Force Stop 后能否恢复 | 30 秒未恢复 | 无需尝试规避;这是系统边界 |
| Boot 是否成功 | 代码存在 | 真机重启并核 StartReceiver、ID 1001 |
| FCM data 是否拉起 FGS | 高优先级分支存在 | 受控发送 high/normal 两类 payload |
| 普通提醒是否依赖 WorkManager | 否,主路径是 FGS 60 秒循环 | 停止 FGS 后观察提醒不再运行 |
| Huawei action 是否有效 | Receiver 未处理 | 不应依赖该 action |
| 通知开关关掉后服务行为 | 启动入口被阻断;已运行服务的停止时机需测试 | 设置页关闭后观察服务/通知 |
十九、证据边界#
- 以上代码来自当前
1.0.5 (7)APK,不代表后续版本。 START_STICKY、Boot Receiver、FCM Service 的存在不等于永久保活。- 真机只验证 Home、最近任务划卡和 Force Stop;未验证重启、低内存回收、Doze、厂商省电或 24 小时稳定性。