Loading apex/appsearch/framework/Android.bp +3 −0 Original line number Diff line number Diff line Loading @@ -65,5 +65,8 @@ java_sdk_library { }, jarjar_rules: "jarjar-rules.txt", apex_available: ["com.android.appsearch"], impl_library_visibility: [ "//frameworks/base/apex/appsearch/service", ], unsafe_ignore_missing_latest_api: true, // TODO(b/146218515) should be removed } apex/appsearch/service/Android.bp +21 −11 Original line number Diff line number Diff line Loading @@ -28,31 +28,41 @@ genrule { } java_library { name: "service-appsearch", srcs: [ "java/**/*.java", ":statslog-appsearch-java-gen", name: "statslog-appsearch-lib", srcs: [":statslog-appsearch-java-gen"], libs: [ "framework-statsd.stubs.module_lib", ], sdk_version: "system_server_current", apex_available: ["com.android.appsearch"], } java_library { name: "service-appsearch", srcs: ["java/**/*.java"], sdk_version: "system_server_current", static_libs: [ "icing-java-proto-lite", "libicing-java", // This list must be kept in sync with jarjar.txt "statslog-appsearch-lib", // Entries below this line are outside of the appsearch package tree and must be kept in // sync with jarjar.txt "modules-utils-preconditions", ], libs: [ "framework", "framework-appsearch", "framework-statsd.stubs.module_lib", "services.core", "services.usage", "framework-appsearch.impl", "unsupportedappusage", // TODO(b/181887768) should be removed ], required: [ "libicing", ], defaults: ["framework-system-server-module-defaults"], permitted_packages: [ "com.android.server.appsearch", "com.google.android.icing", ], jarjar_rules: "jarjar-rules.txt", visibility: [ "//frameworks/base/apex/appsearch:__subpackages__", // These are required until appsearch is properly unbundled. "//frameworks/base/services/tests/mockingservicestests", "//frameworks/base/services/tests/servicestests", Loading apex/appsearch/service/jarjar-rules.txt +4 −1 Original line number Diff line number Diff line # Rename all icing classes to match our module name. OEMs could start using icing lib for some other # purpose in system service, which would cause class collisions when loading our apex into the # system service. rule com.google.protobuf.** com.android.server.appsearch.protobuf.@1 rule com.google.android.icing.proto.** com.android.server.appsearch.proto.@1 rule com.google.android.icing.proto.** com.android.server.appsearch.icing.proto.@1 # Rename all com.android.internal.util classes to prevent class name collisions # between this module and the other versions of the utility classes linked into Loading apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java +4 −1 Original line number Diff line number Diff line Loading @@ -82,7 +82,10 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** TODO(b/142567528): add comments when implement this class */ /** * The main service implementation which contains AppSearch's platform functionality. * @hide */ public class AppSearchManagerService extends SystemService { private static final String TAG = "AppSearchManagerService"; private final Context mContext; Loading apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +101 −25 Original line number Diff line number Diff line Loading @@ -73,7 +73,9 @@ import android.util.IndentingPrintWriter; import android.util.Log; import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; import android.util.SparseIntArray; import android.util.SparseLongArray; import android.util.SparseSetArray; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; Loading Loading @@ -686,26 +688,92 @@ public class JobSchedulerService extends com.android.server.SystemService final Constants mConstants; final ConstantsObserver mConstantsObserver; private static final Comparator<JobStatus> sPendingJobComparator = (o1, o2) -> { @VisibleForTesting class PendingJobComparator implements Comparator<JobStatus> { private final SparseBooleanArray mUidHasEjCache = new SparseBooleanArray(); private final SparseLongArray mEarliestRegEnqueueTimeCache = new SparseLongArray(); /** * Refresh sorting determinants based on the current state of {@link #mPendingJobs}. */ @GuardedBy("mLock") @VisibleForTesting void refreshLocked() { mUidHasEjCache.clear(); mEarliestRegEnqueueTimeCache.clear(); for (int i = 0; i < mPendingJobs.size(); ++i) { final JobStatus job = mPendingJobs.get(i); final int uid = job.getSourceUid(); if (job.isRequestedExpeditedJob()) { mUidHasEjCache.put(uid, true); } else { final long earliestEnqueueTime = mEarliestRegEnqueueTimeCache.get(uid, Long.MAX_VALUE); mEarliestRegEnqueueTimeCache.put(uid, Math.min(earliestEnqueueTime, job.enqueueTime)); } } } @Override public int compare(JobStatus o1, JobStatus o2) { if (o1 == o2) { return 0; } // Jobs with an override state set (via adb) should be put first as tests/developers // expect the jobs to run immediately. if (o1.overrideState != o2.overrideState) { // Higher override state (OVERRIDE_FULL) should be before lower state (OVERRIDE_SOFT) // Higher override state (OVERRIDE_FULL) should be before lower state // (OVERRIDE_SOFT) return o2.overrideState - o1.overrideState; } final boolean o1EJ = o1.isRequestedExpeditedJob(); final boolean o2EJ = o2.isRequestedExpeditedJob(); if (o1.getSourceUid() == o2.getSourceUid()) { final boolean o1FGJ = o1.isRequestedExpeditedJob(); if (o1FGJ != o2.isRequestedExpeditedJob()) { if (o1EJ != o2EJ) { // Attempt to run requested expedited jobs ahead of regular jobs, regardless of // expedited job quota. return o1FGJ ? -1 : 1; return o1EJ ? -1 : 1; } } final boolean uid1HasEj = mUidHasEjCache.get(o1.getSourceUid()); final boolean uid2HasEj = mUidHasEjCache.get(o2.getSourceUid()); if ((uid1HasEj || uid2HasEj) && (o1EJ || o2EJ)) { // We MUST prioritize EJs ahead of regular jobs within a single app. Since we do // that, in order to satisfy the transitivity constraint of the comparator, if // any UID has an EJ, we must ensure that the EJ is ordered ahead of the regular // job of a different app IF the app with an EJ had another job that came before // the differing app. For example, if app A has regJob1 at t1 and eJob3 at t3 and // app B has regJob2 at t2, eJob3 must be ordered before regJob2 because it will be // ordered before regJob1. // Regular jobs don't need to jump the line. final long uid1EarliestRegEnqueueTime = Math.min(o1.enqueueTime, mEarliestRegEnqueueTimeCache.get(o1.getSourceUid(), Long.MAX_VALUE)); final long uid2EarliestRegEnqueueTime = Math.min(o2.enqueueTime, mEarliestRegEnqueueTimeCache.get(o2.getSourceUid(), Long.MAX_VALUE)); if (o1EJ && o2EJ) { if (uid1EarliestRegEnqueueTime < uid2EarliestRegEnqueueTime) { return -1; } else if (uid1EarliestRegEnqueueTime > uid2EarliestRegEnqueueTime) { return 1; } } else if (o1EJ && uid1EarliestRegEnqueueTime < o2.enqueueTime) { return -1; } else if (o2EJ && uid2EarliestRegEnqueueTime < o1.enqueueTime) { return 1; } } if (o1.enqueueTime < o2.enqueueTime) { return -1; } return o1.enqueueTime > o2.enqueueTime ? 1 : 0; }; } } @VisibleForTesting final PendingJobComparator mPendingJobComparator = new PendingJobComparator(); static <T> void addOrderedItem(ArrayList<T> array, T newItem, Comparator<T> comparator) { int where = Collections.binarySearch(array, newItem, comparator); Loading Loading @@ -1115,7 +1183,7 @@ public class JobSchedulerService extends com.android.server.SystemService // This is a new job, we can just immediately put it on the pending // list and try to run it. mJobPackageTracker.notePending(jobStatus); addOrderedItem(mPendingJobs, jobStatus, sPendingJobComparator); addOrderedItem(mPendingJobs, jobStatus, mPendingJobComparator); maybeRunPendingJobsLocked(); } else { evaluateControllerStatesLocked(jobStatus); Loading Loading @@ -1919,7 +1987,7 @@ public class JobSchedulerService extends com.android.server.SystemService if (js != null) { if (isReadyToBeExecutedLocked(js)) { mJobPackageTracker.notePending(js); addOrderedItem(mPendingJobs, js, sPendingJobComparator); addOrderedItem(mPendingJobs, js, mPendingJobComparator); } } else { Slog.e(TAG, "Given null job to check individually"); Loading Loading @@ -2064,6 +2132,7 @@ public class JobSchedulerService extends com.android.server.SystemService * Run through list of jobs and execute all possible - at least one is expired so we do * as many as we can. */ @GuardedBy("mLock") private void queueReadyJobsForExecutionLocked() { // This method will check and capture all ready jobs, so we don't need to keep any messages // in the queue. Loading @@ -2079,7 +2148,7 @@ public class JobSchedulerService extends com.android.server.SystemService mPendingJobs.clear(); stopNonReadyActiveJobsLocked(); mJobs.forEachJob(mReadyQueueFunctor); mReadyQueueFunctor.postProcess(); mReadyQueueFunctor.postProcessLocked(); if (DEBUG) { final int queuedJobs = mPendingJobs.size(); Loading @@ -2106,16 +2175,19 @@ public class JobSchedulerService extends com.android.server.SystemService } } public void postProcess() { @GuardedBy("mLock") private void postProcessLocked() { noteJobsPending(newReadyJobs); mPendingJobs.addAll(newReadyJobs); if (mPendingJobs.size() > 1) { mPendingJobs.sort(sPendingJobComparator); mPendingJobComparator.refreshLocked(); mPendingJobs.sort(mPendingJobComparator); } newReadyJobs.clear(); } } private final ReadyJobQueueFunctor mReadyQueueFunctor = new ReadyJobQueueFunctor(); /** Loading Loading @@ -2180,7 +2252,9 @@ public class JobSchedulerService extends com.android.server.SystemService } } public void postProcess() { @GuardedBy("mLock") @VisibleForTesting void postProcessLocked() { if (unbatchedCount > 0 || forceBatchedCount >= mConstants.MIN_READY_NON_ACTIVE_JOBS_COUNT) { if (DEBUG) { Loading @@ -2189,7 +2263,8 @@ public class JobSchedulerService extends com.android.server.SystemService noteJobsPending(runnableJobs); mPendingJobs.addAll(runnableJobs); if (mPendingJobs.size() > 1) { mPendingJobs.sort(sPendingJobComparator); mPendingJobComparator.refreshLocked(); mPendingJobs.sort(mPendingJobComparator); } } else { if (DEBUG) { Loading @@ -2210,6 +2285,7 @@ public class JobSchedulerService extends com.android.server.SystemService } private final MaybeReadyJobQueueFunctor mMaybeQueueFunctor = new MaybeReadyJobQueueFunctor(); @GuardedBy("mLock") private void maybeQueueReadyJobsForExecutionLocked() { if (DEBUG) Slog.d(TAG, "Maybe queuing ready jobs..."); Loading @@ -2217,7 +2293,7 @@ public class JobSchedulerService extends com.android.server.SystemService mPendingJobs.clear(); stopNonReadyActiveJobsLocked(); mJobs.forEachJob(mMaybeQueueFunctor); mMaybeQueueFunctor.postProcess(); mMaybeQueueFunctor.postProcessLocked(); } /** Returns true if both the calling and source users for the job are started. */ Loading Loading
apex/appsearch/framework/Android.bp +3 −0 Original line number Diff line number Diff line Loading @@ -65,5 +65,8 @@ java_sdk_library { }, jarjar_rules: "jarjar-rules.txt", apex_available: ["com.android.appsearch"], impl_library_visibility: [ "//frameworks/base/apex/appsearch/service", ], unsafe_ignore_missing_latest_api: true, // TODO(b/146218515) should be removed }
apex/appsearch/service/Android.bp +21 −11 Original line number Diff line number Diff line Loading @@ -28,31 +28,41 @@ genrule { } java_library { name: "service-appsearch", srcs: [ "java/**/*.java", ":statslog-appsearch-java-gen", name: "statslog-appsearch-lib", srcs: [":statslog-appsearch-java-gen"], libs: [ "framework-statsd.stubs.module_lib", ], sdk_version: "system_server_current", apex_available: ["com.android.appsearch"], } java_library { name: "service-appsearch", srcs: ["java/**/*.java"], sdk_version: "system_server_current", static_libs: [ "icing-java-proto-lite", "libicing-java", // This list must be kept in sync with jarjar.txt "statslog-appsearch-lib", // Entries below this line are outside of the appsearch package tree and must be kept in // sync with jarjar.txt "modules-utils-preconditions", ], libs: [ "framework", "framework-appsearch", "framework-statsd.stubs.module_lib", "services.core", "services.usage", "framework-appsearch.impl", "unsupportedappusage", // TODO(b/181887768) should be removed ], required: [ "libicing", ], defaults: ["framework-system-server-module-defaults"], permitted_packages: [ "com.android.server.appsearch", "com.google.android.icing", ], jarjar_rules: "jarjar-rules.txt", visibility: [ "//frameworks/base/apex/appsearch:__subpackages__", // These are required until appsearch is properly unbundled. "//frameworks/base/services/tests/mockingservicestests", "//frameworks/base/services/tests/servicestests", Loading
apex/appsearch/service/jarjar-rules.txt +4 −1 Original line number Diff line number Diff line # Rename all icing classes to match our module name. OEMs could start using icing lib for some other # purpose in system service, which would cause class collisions when loading our apex into the # system service. rule com.google.protobuf.** com.android.server.appsearch.protobuf.@1 rule com.google.android.icing.proto.** com.android.server.appsearch.proto.@1 rule com.google.android.icing.proto.** com.android.server.appsearch.icing.proto.@1 # Rename all com.android.internal.util classes to prevent class name collisions # between this module and the other versions of the utility classes linked into Loading
apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java +4 −1 Original line number Diff line number Diff line Loading @@ -82,7 +82,10 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** TODO(b/142567528): add comments when implement this class */ /** * The main service implementation which contains AppSearch's platform functionality. * @hide */ public class AppSearchManagerService extends SystemService { private static final String TAG = "AppSearchManagerService"; private final Context mContext; Loading
apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +101 −25 Original line number Diff line number Diff line Loading @@ -73,7 +73,9 @@ import android.util.IndentingPrintWriter; import android.util.Log; import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; import android.util.SparseIntArray; import android.util.SparseLongArray; import android.util.SparseSetArray; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; Loading Loading @@ -686,26 +688,92 @@ public class JobSchedulerService extends com.android.server.SystemService final Constants mConstants; final ConstantsObserver mConstantsObserver; private static final Comparator<JobStatus> sPendingJobComparator = (o1, o2) -> { @VisibleForTesting class PendingJobComparator implements Comparator<JobStatus> { private final SparseBooleanArray mUidHasEjCache = new SparseBooleanArray(); private final SparseLongArray mEarliestRegEnqueueTimeCache = new SparseLongArray(); /** * Refresh sorting determinants based on the current state of {@link #mPendingJobs}. */ @GuardedBy("mLock") @VisibleForTesting void refreshLocked() { mUidHasEjCache.clear(); mEarliestRegEnqueueTimeCache.clear(); for (int i = 0; i < mPendingJobs.size(); ++i) { final JobStatus job = mPendingJobs.get(i); final int uid = job.getSourceUid(); if (job.isRequestedExpeditedJob()) { mUidHasEjCache.put(uid, true); } else { final long earliestEnqueueTime = mEarliestRegEnqueueTimeCache.get(uid, Long.MAX_VALUE); mEarliestRegEnqueueTimeCache.put(uid, Math.min(earliestEnqueueTime, job.enqueueTime)); } } } @Override public int compare(JobStatus o1, JobStatus o2) { if (o1 == o2) { return 0; } // Jobs with an override state set (via adb) should be put first as tests/developers // expect the jobs to run immediately. if (o1.overrideState != o2.overrideState) { // Higher override state (OVERRIDE_FULL) should be before lower state (OVERRIDE_SOFT) // Higher override state (OVERRIDE_FULL) should be before lower state // (OVERRIDE_SOFT) return o2.overrideState - o1.overrideState; } final boolean o1EJ = o1.isRequestedExpeditedJob(); final boolean o2EJ = o2.isRequestedExpeditedJob(); if (o1.getSourceUid() == o2.getSourceUid()) { final boolean o1FGJ = o1.isRequestedExpeditedJob(); if (o1FGJ != o2.isRequestedExpeditedJob()) { if (o1EJ != o2EJ) { // Attempt to run requested expedited jobs ahead of regular jobs, regardless of // expedited job quota. return o1FGJ ? -1 : 1; return o1EJ ? -1 : 1; } } final boolean uid1HasEj = mUidHasEjCache.get(o1.getSourceUid()); final boolean uid2HasEj = mUidHasEjCache.get(o2.getSourceUid()); if ((uid1HasEj || uid2HasEj) && (o1EJ || o2EJ)) { // We MUST prioritize EJs ahead of regular jobs within a single app. Since we do // that, in order to satisfy the transitivity constraint of the comparator, if // any UID has an EJ, we must ensure that the EJ is ordered ahead of the regular // job of a different app IF the app with an EJ had another job that came before // the differing app. For example, if app A has regJob1 at t1 and eJob3 at t3 and // app B has regJob2 at t2, eJob3 must be ordered before regJob2 because it will be // ordered before regJob1. // Regular jobs don't need to jump the line. final long uid1EarliestRegEnqueueTime = Math.min(o1.enqueueTime, mEarliestRegEnqueueTimeCache.get(o1.getSourceUid(), Long.MAX_VALUE)); final long uid2EarliestRegEnqueueTime = Math.min(o2.enqueueTime, mEarliestRegEnqueueTimeCache.get(o2.getSourceUid(), Long.MAX_VALUE)); if (o1EJ && o2EJ) { if (uid1EarliestRegEnqueueTime < uid2EarliestRegEnqueueTime) { return -1; } else if (uid1EarliestRegEnqueueTime > uid2EarliestRegEnqueueTime) { return 1; } } else if (o1EJ && uid1EarliestRegEnqueueTime < o2.enqueueTime) { return -1; } else if (o2EJ && uid2EarliestRegEnqueueTime < o1.enqueueTime) { return 1; } } if (o1.enqueueTime < o2.enqueueTime) { return -1; } return o1.enqueueTime > o2.enqueueTime ? 1 : 0; }; } } @VisibleForTesting final PendingJobComparator mPendingJobComparator = new PendingJobComparator(); static <T> void addOrderedItem(ArrayList<T> array, T newItem, Comparator<T> comparator) { int where = Collections.binarySearch(array, newItem, comparator); Loading Loading @@ -1115,7 +1183,7 @@ public class JobSchedulerService extends com.android.server.SystemService // This is a new job, we can just immediately put it on the pending // list and try to run it. mJobPackageTracker.notePending(jobStatus); addOrderedItem(mPendingJobs, jobStatus, sPendingJobComparator); addOrderedItem(mPendingJobs, jobStatus, mPendingJobComparator); maybeRunPendingJobsLocked(); } else { evaluateControllerStatesLocked(jobStatus); Loading Loading @@ -1919,7 +1987,7 @@ public class JobSchedulerService extends com.android.server.SystemService if (js != null) { if (isReadyToBeExecutedLocked(js)) { mJobPackageTracker.notePending(js); addOrderedItem(mPendingJobs, js, sPendingJobComparator); addOrderedItem(mPendingJobs, js, mPendingJobComparator); } } else { Slog.e(TAG, "Given null job to check individually"); Loading Loading @@ -2064,6 +2132,7 @@ public class JobSchedulerService extends com.android.server.SystemService * Run through list of jobs and execute all possible - at least one is expired so we do * as many as we can. */ @GuardedBy("mLock") private void queueReadyJobsForExecutionLocked() { // This method will check and capture all ready jobs, so we don't need to keep any messages // in the queue. Loading @@ -2079,7 +2148,7 @@ public class JobSchedulerService extends com.android.server.SystemService mPendingJobs.clear(); stopNonReadyActiveJobsLocked(); mJobs.forEachJob(mReadyQueueFunctor); mReadyQueueFunctor.postProcess(); mReadyQueueFunctor.postProcessLocked(); if (DEBUG) { final int queuedJobs = mPendingJobs.size(); Loading @@ -2106,16 +2175,19 @@ public class JobSchedulerService extends com.android.server.SystemService } } public void postProcess() { @GuardedBy("mLock") private void postProcessLocked() { noteJobsPending(newReadyJobs); mPendingJobs.addAll(newReadyJobs); if (mPendingJobs.size() > 1) { mPendingJobs.sort(sPendingJobComparator); mPendingJobComparator.refreshLocked(); mPendingJobs.sort(mPendingJobComparator); } newReadyJobs.clear(); } } private final ReadyJobQueueFunctor mReadyQueueFunctor = new ReadyJobQueueFunctor(); /** Loading Loading @@ -2180,7 +2252,9 @@ public class JobSchedulerService extends com.android.server.SystemService } } public void postProcess() { @GuardedBy("mLock") @VisibleForTesting void postProcessLocked() { if (unbatchedCount > 0 || forceBatchedCount >= mConstants.MIN_READY_NON_ACTIVE_JOBS_COUNT) { if (DEBUG) { Loading @@ -2189,7 +2263,8 @@ public class JobSchedulerService extends com.android.server.SystemService noteJobsPending(runnableJobs); mPendingJobs.addAll(runnableJobs); if (mPendingJobs.size() > 1) { mPendingJobs.sort(sPendingJobComparator); mPendingJobComparator.refreshLocked(); mPendingJobs.sort(mPendingJobComparator); } } else { if (DEBUG) { Loading @@ -2210,6 +2285,7 @@ public class JobSchedulerService extends com.android.server.SystemService } private final MaybeReadyJobQueueFunctor mMaybeQueueFunctor = new MaybeReadyJobQueueFunctor(); @GuardedBy("mLock") private void maybeQueueReadyJobsForExecutionLocked() { if (DEBUG) Slog.d(TAG, "Maybe queuing ready jobs..."); Loading @@ -2217,7 +2293,7 @@ public class JobSchedulerService extends com.android.server.SystemService mPendingJobs.clear(); stopNonReadyActiveJobsLocked(); mJobs.forEachJob(mMaybeQueueFunctor); mMaybeQueueFunctor.postProcess(); mMaybeQueueFunctor.postProcessLocked(); } /** Returns true if both the calling and source users for the job are started. */ Loading