From 104d21d0841e9ada1f090b3c73c1d9dd951633ec Mon Sep 17 00:00:00 2001
From: Kweku Adams <kwekua@google.com>
Date: Sat, 1 Jul 2023 18:06:08 +0000
Subject: [PATCH] Avoid loading duplicate jobs.

If the persisted files have somehow accumulated duplicate versions of
the same job (identified by uid-namespace-jobId), then drop the
duplicates and only keep one.

Bug: 289062813
Bug: 296890885
Test: atest JobStoreTest
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:c8fbd937940b83944492c4ccaf2830611285999a)
Merged-In: I3179261309031801f0506cf905206376e59af1fe
Change-Id: I3179261309031801f0506cf905206376e59af1fe
---
 .../java/com/android/server/job/JobStore.java     | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
index 0a7bffc786cc..4b4e51290abd 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
@@ -1118,6 +1118,7 @@ public final class JobStore {
             }
             boolean needFileMigration = false;
             long nowElapsed = sElapsedRealtimeClock.millis();
+            int numDuplicates = 0;
             synchronized (mLock) {
                 for (File file : files) {
                     final AtomicFile aFile = createJobFile(file);
@@ -1126,6 +1127,16 @@ public final class JobStore {
                         if (jobs != null) {
                             for (int i = 0; i < jobs.size(); i++) {
                                 JobStatus js = jobs.get(i);
+                                final JobStatus existingJob = this.jobSet.get(
+                                        js.getUid(), js.getNamespace(), js.getJobId());
+                                if (existingJob != null) {
+                                    numDuplicates++;
+                                    // Jobs are meant to have unique uid-namespace-jobId
+                                    // combinations, but we've somehow read multiple jobs with the
+                                    // combination. Drop the latter one since keeping both will
+                                    // result in other issues.
+                                    continue;
+                                }
                                 js.prepareLocked();
                                 js.enqueueTime = nowElapsed;
                                 this.jobSet.add(js);
@@ -1174,6 +1185,10 @@ public final class JobStore {
                 migrateJobFilesAsync();
             }
 
+            if (numDuplicates > 0) {
+                Slog.wtf(TAG, "Encountered " + numDuplicates + " duplicate persisted jobs");
+            }
+
             // Log the count immediately after loading from boot.
             mCurrentJobSetSize = numJobs;
             mScheduledJob30MinHighWaterMark = mCurrentJobSetSize;
-- 
GitLab