Merge "Move the job scheduler service code to its own jar file."
diff --git a/apex/jobscheduler/README_js-mainline.md b/apex/jobscheduler/README_js-mainline.md
new file mode 100644
index 0000000..b5fea5e
--- /dev/null
+++ b/apex/jobscheduler/README_js-mainline.md
@@ -0,0 +1,51 @@
+# Making Job Scheduler into a Mainline Module
+
+## TODOs
+
+See also:
+- http://go/moving-js-code-for-mainline
+- http://go/jobscheduler-code-dependencies-2019-07
+
+- [ ] Move client code
+  - [ ] Move code
+  - [ ] Make build file
+  - [ ] "m jobscheduler-framework" pass
+  - [ ] "m framework" pass
+  - [ ] "m service" pass
+- [ ] Move proto
+  - No, couldn't do it, because it's referred to by incidentd_proto
+- [ ] Move service
+  - [X] Move code (done, but it won't compile yet)
+  - [X] Make build file
+  - [X] "m service" pass
+  - [X] "m jobscheduler-service" pass
+    - To make it pass, jobscheduler-service has to link services.jar too. Many dependencies.
+- [ ] Move this into `frameworks/apex/jobscheduler/...`. Currently it's in `frameworks/base/apex/...`
+because `frameworks/apex/` is not a part of any git projects. (and also working on multiple
+projects is a pain.)
+
+
+## Problems
+- Couldn't move dumpsys proto files. They are used by incidentd_proto, which is in the platform
+  (not updatable).
+  - One idea is *not* to move the proto files into apex but keep them in the platform.
+    Then we make sure to extend the proto files in a backward-compat way (which we do anyway)
+    and always use the latest file from the JS apex.
+
+- There are a lot of build tasks that use "framework.jar". (Examples: hiddenapi-greylist.txt check,
+  update-api / public API check and SDK stub (android.jar) creation)
+  To make the downstream build modules buildable, we need to include js-framework.jar in
+  framework.jar. However it turned out to be tricky because soong has special logic for "framework"
+  and "framework.jar".
+  i.e. Conceptually, we can do it by renaming `framework` to `framework-minus-jobscheduler`, build
+  `jobscheduler-framework` with `framework-minus-jobscheduler`, and create `framework` by merging
+  `framework-minus-jobscheduler` and `jobscheduler-framework`.
+  However it didn't quite work because of the special casing.
+
+- JS-service uses a lot of other code in `services`, so it needs to link services.core.jar e.g.
+ - Common system service code, e.g. `com.android.server.SystemService`
+ - Common utility code, e.g. `FgThread` and `IoThread`
+ - Other system services such as `DeviceIdleController` and `ActivityManagerService`
+ - Server side singleton. `AppStateTracker`
+ - `DeviceIdleController.LocalService`, which is a local service but there's no interface class.
+ - `XxxInternal` interfaces that are not in the framework side. -> We should be able to move them.
diff --git a/apex/jobscheduler/service/Android.bp b/apex/jobscheduler/service/Android.bp
new file mode 100644
index 0000000..ca6dc45
--- /dev/null
+++ b/apex/jobscheduler/service/Android.bp
@@ -0,0 +1,15 @@
+// Job Scheduler Service jar, which will eventually be put in the jobscheduler mainline apex.
+// jobscheduler-service needs to be added to PRODUCT_SYSTEM_SERVER_JARS.
+java_library {
+    name: "jobscheduler-service",
+    installable: true,
+
+    srcs: [
+        "java/**/*.java",
+    ],
+
+    libs: [
+        "framework",
+        "services.core",
+    ],
+}
diff --git a/services/core/java/com/android/server/job/GrantedUriPermissions.java b/apex/jobscheduler/service/java/com/android/server/job/GrantedUriPermissions.java
similarity index 100%
rename from services/core/java/com/android/server/job/GrantedUriPermissions.java
rename to apex/jobscheduler/service/java/com/android/server/job/GrantedUriPermissions.java
diff --git a/services/core/java/com/android/server/job/JobCompletedListener.java b/apex/jobscheduler/service/java/com/android/server/job/JobCompletedListener.java
similarity index 100%
rename from services/core/java/com/android/server/job/JobCompletedListener.java
rename to apex/jobscheduler/service/java/com/android/server/job/JobCompletedListener.java
diff --git a/services/core/java/com/android/server/job/JobConcurrencyManager.java b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
similarity index 100%
rename from services/core/java/com/android/server/job/JobConcurrencyManager.java
rename to apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
diff --git a/services/core/java/com/android/server/job/JobPackageTracker.java b/apex/jobscheduler/service/java/com/android/server/job/JobPackageTracker.java
similarity index 100%
rename from services/core/java/com/android/server/job/JobPackageTracker.java
rename to apex/jobscheduler/service/java/com/android/server/job/JobPackageTracker.java
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
similarity index 100%
rename from services/core/java/com/android/server/job/JobSchedulerService.java
rename to apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
diff --git a/services/core/java/com/android/server/job/JobSchedulerShellCommand.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
similarity index 100%
rename from services/core/java/com/android/server/job/JobSchedulerShellCommand.java
rename to apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
similarity index 100%
rename from services/core/java/com/android/server/job/JobServiceContext.java
rename to apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
diff --git a/services/core/java/com/android/server/job/JobStore.java b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
similarity index 100%
rename from services/core/java/com/android/server/job/JobStore.java
rename to apex/jobscheduler/service/java/com/android/server/job/JobStore.java
diff --git a/services/core/java/com/android/server/job/StateChangedListener.java b/apex/jobscheduler/service/java/com/android/server/job/StateChangedListener.java
similarity index 100%
rename from services/core/java/com/android/server/job/StateChangedListener.java
rename to apex/jobscheduler/service/java/com/android/server/job/StateChangedListener.java
diff --git a/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
similarity index 100%
rename from services/core/java/com/android/server/job/controllers/BackgroundJobsController.java
rename to apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
diff --git a/services/core/java/com/android/server/job/controllers/BatteryController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java
similarity index 100%
rename from services/core/java/com/android/server/job/controllers/BatteryController.java
rename to apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java
diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
similarity index 100%
rename from services/core/java/com/android/server/job/controllers/ConnectivityController.java
rename to apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
diff --git a/services/core/java/com/android/server/job/controllers/ContentObserverController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ContentObserverController.java
similarity index 100%
rename from services/core/java/com/android/server/job/controllers/ContentObserverController.java
rename to apex/jobscheduler/service/java/com/android/server/job/controllers/ContentObserverController.java
diff --git a/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java
similarity index 100%
rename from services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java
rename to apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java
diff --git a/services/core/java/com/android/server/job/controllers/IdleController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java
similarity index 100%
rename from services/core/java/com/android/server/job/controllers/IdleController.java
rename to apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
similarity index 100%
rename from services/core/java/com/android/server/job/controllers/JobStatus.java
rename to apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
diff --git a/services/core/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
similarity index 100%
rename from services/core/java/com/android/server/job/controllers/QuotaController.java
rename to apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
diff --git a/services/core/java/com/android/server/job/controllers/StateController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java
similarity index 100%
rename from services/core/java/com/android/server/job/controllers/StateController.java
rename to apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java
diff --git a/services/core/java/com/android/server/job/controllers/StorageController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/StorageController.java
similarity index 100%
rename from services/core/java/com/android/server/job/controllers/StorageController.java
rename to apex/jobscheduler/service/java/com/android/server/job/controllers/StorageController.java
diff --git a/services/core/java/com/android/server/job/controllers/TimeController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
similarity index 100%
rename from services/core/java/com/android/server/job/controllers/TimeController.java
rename to apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
diff --git a/services/core/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
similarity index 100%
rename from services/core/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
rename to apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
diff --git a/services/core/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java
similarity index 100%
rename from services/core/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java
rename to apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java
diff --git a/services/core/java/com/android/server/job/controllers/idle/IdlenessListener.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/IdlenessListener.java
similarity index 100%
rename from services/core/java/com/android/server/job/controllers/idle/IdlenessListener.java
rename to apex/jobscheduler/service/java/com/android/server/job/controllers/idle/IdlenessListener.java
diff --git a/services/core/java/com/android/server/job/controllers/idle/IdlenessTracker.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/IdlenessTracker.java
similarity index 100%
rename from services/core/java/com/android/server/job/controllers/idle/IdlenessTracker.java
rename to apex/jobscheduler/service/java/com/android/server/job/controllers/idle/IdlenessTracker.java
diff --git a/config/preloaded-classes b/config/preloaded-classes
index 03e3b82..ea50999 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -563,6 +563,7 @@
 android.app.job.JobParameters$1
 android.app.job.JobParameters
 android.app.job.JobScheduler
+android.app.job.JobSchedulerFrameworkInitializer
 android.app.job.JobService$1
 android.app.job.JobService
 android.app.job.JobServiceEngine$JobHandler
diff --git a/config/preloaded-classes-extra b/config/preloaded-classes-extra
index 09f393a..94849fb 100644
--- a/config/preloaded-classes-extra
+++ b/config/preloaded-classes-extra
@@ -1,3 +1,6 @@
+# JobSchedulerFrameworkInitializer must always be preloaded because it registers the job scheduler
+# service wrapper to SystemServiceRegistry.
+android.app.job.JobSchedulerFrameworkInitializer
 android.icu.impl.coll.CollationRoot
 android.icu.impl.IDNA2003
 android.icu.impl.number.Parse
diff --git a/core/java/android/app/JobSchedulerImpl.java b/core/java/android/app/JobSchedulerImpl.java
index e877018..924a708 100644
--- a/core/java/android/app/JobSchedulerImpl.java
+++ b/core/java/android/app/JobSchedulerImpl.java
@@ -26,6 +26,9 @@
 
 import java.util.List;
 
+
+// APEX NOTE: Class path referred to by robolectric, so can't move it.
+
 /**
  * Concrete implementation of the JobScheduler interface
  * @hide 
@@ -33,7 +36,7 @@
 public class JobSchedulerImpl extends JobScheduler {
     IJobScheduler mBinder;
 
-    /* package */ JobSchedulerImpl(IJobScheduler binder) {
+    public JobSchedulerImpl(IJobScheduler binder) {
         mBinder = binder;
     }
 
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index cfe2cf0..5034b53 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -23,8 +23,6 @@
 import android.app.admin.IDevicePolicyManager;
 import android.app.contentsuggestions.ContentSuggestionsManager;
 import android.app.contentsuggestions.IContentSuggestionsManager;
-import android.app.job.IJobScheduler;
-import android.app.job.JobScheduler;
 import android.app.prediction.AppPredictionManager;
 import android.app.role.RoleControllerManager;
 import android.app.role.RoleManager;
@@ -198,12 +196,15 @@
 import com.android.internal.policy.PhoneLayoutInflater;
 
 import java.util.Map;
+import java.util.function.Function;
 
 /**
  * Manages all of the system services that can be returned by {@link Context#getSystemService}.
  * Used by {@link ContextImpl}.
+ *
+ * @hide
  */
-final class SystemServiceRegistry {
+public final class SystemServiceRegistry {
     private static final String TAG = "SystemServiceRegistry";
 
     // Service registry information.
@@ -979,14 +980,6 @@
                 return new NetworkStatsManager(ctx.getOuterContext());
             }});
 
-        registerService(Context.JOB_SCHEDULER_SERVICE, JobScheduler.class,
-                new StaticServiceFetcher<JobScheduler>() {
-            @Override
-            public JobScheduler createService() throws ServiceNotFoundException {
-                IBinder b = ServiceManager.getServiceOrThrow(Context.JOB_SCHEDULER_SERVICE);
-                return new JobSchedulerImpl(IJobScheduler.Stub.asInterface(b));
-            }});
-
         registerService(Context.PERSISTENT_DATA_BLOCK_SERVICE, PersistentDataBlockManager.class,
                 new StaticServiceFetcher<PersistentDataBlockManager>() {
             @Override
@@ -1324,6 +1317,22 @@
     }
 
     /**
+     * APEX modules will use it to register their service wrapper.
+     *
+     * @hide
+     */
+    public static <T> void registerStaticService(String serviceName, Class<T> serviceClass,
+            Function<IBinder, T> serviceFetcher) {
+        registerService(serviceName, serviceClass,
+                new StaticServiceFetcher<T>() {
+                    @Override
+                    public T createService() throws ServiceNotFoundException {
+                        IBinder b = ServiceManager.getServiceOrThrow(serviceName);
+                        return serviceFetcher.apply(b);
+                    }});
+    }
+
+    /**
      * Base interface for classes that fetch services.
      * These objects must only be created during static initialization.
      */
diff --git a/core/java/android/app/job/JobSchedulerFrameworkInitializer.java b/core/java/android/app/job/JobSchedulerFrameworkInitializer.java
new file mode 100644
index 0000000..cf2979c
--- /dev/null
+++ b/core/java/android/app/job/JobSchedulerFrameworkInitializer.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.job;
+
+import android.app.JobSchedulerImpl;
+import android.app.SystemServiceRegistry;
+import android.content.Context;
+
+/**
+ * This class needs to be pre-loaded by zygote.  This is where the job scheduler service wrapper
+ * is registered.
+ *
+ * @hide
+ */
+public class JobSchedulerFrameworkInitializer {
+    static {
+        SystemServiceRegistry.registerStaticService(
+                Context.JOB_SCHEDULER_SERVICE, JobScheduler.class,
+                (b) -> new JobSchedulerImpl(IJobScheduler.Stub.asInterface(b)));
+    }
+}
diff --git a/services/core/java/com/android/server/job/JobSchedulerInternal.java b/core/java/com/android/server/job/JobSchedulerInternal.java
similarity index 100%
rename from services/core/java/com/android/server/job/JobSchedulerInternal.java
rename to core/java/com/android/server/job/JobSchedulerInternal.java
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 9fe44dc..8161ac9 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -102,7 +102,6 @@
 import com.android.server.input.InputManagerService;
 import com.android.server.inputmethod.InputMethodManagerService;
 import com.android.server.inputmethod.MultiClientInputMethodManagerService;
-import com.android.server.job.JobSchedulerService;
 import com.android.server.lights.LightsService;
 import com.android.server.media.MediaResourceMonitorService;
 import com.android.server.media.MediaRouterService;
@@ -1575,8 +1574,9 @@
             mSystemServiceManager.startService(ColorDisplayService.class);
             t.traceEnd();
 
+            // TODO(aml-jobscheduler): Think about how to do it properly.
             t.traceBegin("StartJobScheduler");
-            mSystemServiceManager.startService(JobSchedulerService.class);
+            mSystemServiceManager.startService(JOB_SCHEDULER_SERVICE_CLASS);
             t.traceEnd();
 
             t.traceBegin("StartSoundTrigger");
diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp
index 2baa4d8..ad94e61 100644
--- a/services/tests/mockingservicestests/Android.bp
+++ b/services/tests/mockingservicestests/Android.bp
@@ -20,6 +20,7 @@
     static_libs: [
         "services.core",
         "services.net",
+        "jobscheduler-service",
         "androidx.test.runner",
         "mockito-target-extended-minus-junit4",
         "platform-test-annotations",
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 869913d..856e67c 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -39,6 +39,7 @@
         "platformprotosnano",
         "hamcrest-library",
         "servicestests-utils",
+        "jobscheduler-service",
     ],
 
     aidl: {
diff --git a/tests/JobSchedulerPerfTests/Android.bp b/tests/JobSchedulerPerfTests/Android.bp
index 2230807..c51b811 100644
--- a/tests/JobSchedulerPerfTests/Android.bp
+++ b/tests/JobSchedulerPerfTests/Android.bp
@@ -19,6 +19,7 @@
         "androidx.test.rules",
         "apct-perftests-utils",
         "services",
+        "jobscheduler-service",
     ],
     platform_apis: true,
     certificate: "platform",