Check feature bits before loading optional services

At startup, we check with PackageManager whether a system service is
available before attempting to load it. A system service is available
if its associated feature (similar to hardware features) is present.
This does not remove unavailable services from the compiled jar.

Change-Id: I13571805083aa4e65519a74acb52efd17b9fb3d7
diff --git a/packages/Keyguard/Android.mk b/packages/Keyguard/Android.mk
index f6f441d..1f2b5fb 100644
--- a/packages/Keyguard/Android.mk
+++ b/packages/Keyguard/Android.mk
@@ -18,8 +18,6 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-subdir-Iaidl-files)
 
-LOCAL_JAVA_LIBRARIES := services
-
 LOCAL_PACKAGE_NAME := Keyguard
 
 LOCAL_CERTIFICATE := platform
diff --git a/services/Android.mk b/services/Android.mk
index 80fd35a..a8881b6 100644
--- a/services/Android.mk
+++ b/services/Android.mk
@@ -1,27 +1,23 @@
 LOCAL_PATH:= $(call my-dir)
 
-# the java library
+# merge all required services into one jar
 # ============================================================
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES :=
+LOCAL_MODULE := services
 
-# TODO: Move this to the product makefiles
-REQUIRED_SERVICES := core accessibility appwidget backup devicepolicy print
+LOCAL_SRC_FILES := $(call all-java-files-under,java)
 
-include $(patsubst %,$(LOCAL_PATH)/%/java/service.mk,$(REQUIRED_SERVICES))
-
-LOCAL_MODULE:= services
-
-LOCAL_JAVA_LIBRARIES := android.policy conscrypt telephony-common
-
-#LOCAL_PROGUARD_ENABLED := full
-#LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    services.core \
+    services.accessibility \
+    services.appwidget \
+    services.backup \
+    services.devicepolicy \
+    services.print
 
 include $(BUILD_JAVA_LIBRARY)
 
-include $(BUILD_DROIDDOC)
-
 # native library
 # =============================================================
 
diff --git a/services/accessibility/Android.mk b/services/accessibility/Android.mk
new file mode 100644
index 0000000..d98fc28
--- /dev/null
+++ b/services/accessibility/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := services.accessibility
+
+LOCAL_SRC_FILES += \
+      $(call all-java-files-under,java)
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/accessibility/java/service.mk b/services/accessibility/java/service.mk
deleted file mode 100644
index 5e8f375..0000000
--- a/services/accessibility/java/service.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-# Include only if the service is required
-ifneq ($(findstring accessibility,$(REQUIRED_SERVICES)),)
-
-SUB_DIR := accessibility/java
-
-LOCAL_SRC_FILES += \
-      $(call all-java-files-under,$(SUB_DIR))
-
-#DEFINED_SERVICES += com.android.server.accessibility.AccessibilityManagerService
-
-endif
diff --git a/services/appwidget/Android.mk b/services/appwidget/Android.mk
new file mode 100644
index 0000000..ca38f2f
--- /dev/null
+++ b/services/appwidget/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := services.appwidget
+
+LOCAL_SRC_FILES += \
+      $(call all-java-files-under,java)
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/appwidget/java/service.mk b/services/appwidget/java/service.mk
deleted file mode 100644
index 0e33446..0000000
--- a/services/appwidget/java/service.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-# Include only if the service is required
-ifneq ($(findstring appwidget,$(REQUIRED_SERVICES)),)
-
-SUB_DIR := appwidget/java
-
-LOCAL_SRC_FILES += \
-      $(call all-java-files-under,$(SUB_DIR))
-
-#DEFINED_SERVICES += com.android.server.appwidget.AppWidgetService
-
-endif
diff --git a/services/backup/Android.mk b/services/backup/Android.mk
new file mode 100644
index 0000000..3e686d1
--- /dev/null
+++ b/services/backup/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := services.backup
+
+LOCAL_SRC_FILES += \
+      $(call all-java-files-under,java)
+
+LOCAL_JAVA_LIBRARIES := services.core
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/backup/java/service.mk b/services/backup/java/service.mk
deleted file mode 100644
index bd22b95..0000000
--- a/services/backup/java/service.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-# Include only if the service is required
-ifneq ($(findstring backup,$(REQUIRED_SERVICES)),)
-
-SUB_DIR := backup/java
-
-LOCAL_SRC_FILES += \
-      $(call all-java-files-under,$(SUB_DIR))
-
-#DEFINED_SERVICES += com.android.server.backup.BackupManagerService
-
-endif
diff --git a/services/core/Android.mk b/services/core/Android.mk
new file mode 100644
index 0000000..5c45201
--- /dev/null
+++ b/services/core/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := services.core
+
+LOCAL_SRC_FILES += \
+    $(call all-java-files-under,java) \
+    java/com/android/server/EventLogTags.logtags \
+    java/com/android/server/am/EventLogTags.logtags
+
+LOCAL_JAVA_LIBRARIES := android.policy telephony-common
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 019e6f5..74e18c0 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -50,7 +50,6 @@
 import com.android.server.AttributeCache;
 import com.android.server.IntentResolver;
 import com.android.server.ServiceThread;
-import com.android.server.SystemServer;
 import com.android.server.SystemService;
 import com.android.server.Watchdog;
 import com.android.server.am.ActivityStack.ActivityState;
diff --git a/services/core/java/service.mk b/services/core/java/service.mk
deleted file mode 100644
index 4cb411b..0000000
--- a/services/core/java/service.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-SUB_DIR := core/java
-
-LOCAL_SRC_FILES += \
-      $(call all-java-files-under,$(SUB_DIR)) \
-      $(SUB_DIR)/com/android/server/EventLogTags.logtags \
-      $(SUB_DIR)/com/android/server/am/EventLogTags.logtags
diff --git a/services/devicepolicy/Android.mk b/services/devicepolicy/Android.mk
new file mode 100644
index 0000000..a55d138
--- /dev/null
+++ b/services/devicepolicy/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := services.devicepolicy
+
+LOCAL_SRC_FILES += \
+      $(call all-java-files-under,java)
+
+LOCAL_JAVA_LIBRARIES := conscrypt
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/devicepolicy/java/service.mk b/services/devicepolicy/java/service.mk
deleted file mode 100644
index e64cc96..0000000
--- a/services/devicepolicy/java/service.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-# Include only if the service is required
-ifneq ($(findstring devicepolicy,$(REQUIRED_SERVICES)),)
-
-SUB_DIR := devicepolicy/java
-
-LOCAL_SRC_FILES += \
-      $(call all-java-files-under,$(SUB_DIR))
-
-#DEFINED_SERVICES += com.android.server.devicepolicy.DevicePolicyManagerService
-
-endif
diff --git a/services/core/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
similarity index 97%
rename from services/core/java/com/android/server/SystemServer.java
rename to services/java/com/android/server/SystemServer.java
index 6a76388..269c056 100644
--- a/services/core/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -52,7 +52,6 @@
 import com.android.internal.R;
 import com.android.internal.os.BinderInternal;
 import com.android.internal.os.SamplingProfilerIntegration;
-import com.android.server.accessibility.AccessibilityManagerService;
 import com.android.server.accounts.AccountManagerService;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.am.BatteryStatsService;
@@ -482,8 +481,8 @@
 
                 try {
                     Slog.i(TAG, "Accessibility Manager");
-                    ServiceManager.addService(Context.ACCESSIBILITY_SERVICE,
-                            new AccessibilityManagerService(context));
+                    ServiceManager.addService(Context.ACCESSIBILITY_SERVICE, (IBinder)
+                            getClass().getClassLoader().loadClass("com.android.server.accessibility.AccessibilityManagerService").getConstructor(Context.class).newInstance(context));
                 } catch (Throwable e) {
                     reportWtf("starting Accessibility Manager", e);
                 }
@@ -536,8 +535,10 @@
                 }
 
                 try {
-                    Slog.i(TAG, "Device Policy");
-                    mSystemServiceManager.startServiceIfExists(DEVICE_POLICY_MANAGER_SERVICE_CLASS);
+                    if (pm.hasSystemFeature("android.software.device_admin")) {
+                        mSystemServiceManager.startServiceIfExists(
+                                DEVICE_POLICY_MANAGER_SERVICE_CLASS);
+                    }
                 } catch (Throwable e) {
                     reportWtf("starting DevicePolicyService", e);
                 }
@@ -787,15 +788,17 @@
 
             if (!disableNonCoreServices) {
                 try {
-                    Slog.i(TAG, "Backup Service");
-                    mSystemServiceManager.startServiceIfExists(BACKUP_MANAGER_SERVICE_CLASS);
+                    if (pm.hasSystemFeature("android.software.backup")) {
+                        mSystemServiceManager.startServiceIfExists(BACKUP_MANAGER_SERVICE_CLASS);
+                    }
                 } catch (Throwable e) {
                     Slog.e(TAG, "Failure starting Backup Service", e);
                 }
 
                 try {
-                    Slog.i(TAG, "AppWidget Service");
-                    mSystemServiceManager.startServiceIfExists(APPWIDGET_SERVICE_CLASS);
+                    if (pm.hasSystemFeature("android.software.app_widgets")) {
+                        mSystemServiceManager.startServiceIfExists(APPWIDGET_SERVICE_CLASS);
+                    }
                 } catch (Throwable e) {
                     reportWtf("starting AppWidget Service", e);
                 }
@@ -855,7 +858,7 @@
                 }
             }
 
-            if (!disableNonCoreServices && 
+            if (!disableNonCoreServices &&
                 context.getResources().getBoolean(R.bool.config_dreamsSupported)) {
                 try {
                     Slog.i(TAG, "Dreams Service");
@@ -885,8 +888,9 @@
             }
 
             try {
-                Slog.i(TAG, "Print Service");
-                mSystemServiceManager.startServiceIfExists(PRINT_MANAGER_SERVICE_CLASS);
+                if (pm.hasSystemFeature("android.software.print")) {
+                    mSystemServiceManager.startServiceIfExists(PRINT_MANAGER_SERVICE_CLASS);
+                }
             } catch (Throwable e) {
                 reportWtf("starting Print Service", e);
             }
diff --git a/services/print/Android.mk b/services/print/Android.mk
new file mode 100644
index 0000000..33604b7
--- /dev/null
+++ b/services/print/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := services.print
+
+LOCAL_SRC_FILES += \
+      $(call all-java-files-under,java)
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
index 852736b..1e35678 100644
--- a/services/print/java/com/android/server/print/PrintManagerService.java
+++ b/services/print/java/com/android/server/print/PrintManagerService.java
@@ -52,7 +52,6 @@
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.BackgroundThread;
 import com.android.server.SystemService;
-import com.android.server.devicepolicy.DevicePolicyManagerService;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
diff --git a/services/print/java/service.mk b/services/print/java/service.mk
deleted file mode 100644
index cba3612..0000000
--- a/services/print/java/service.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-# Include only if the service is required
-ifneq ($(findstring print,$(REQUIRED_SERVICES)),)
-
-SUB_DIR := print/java
-
-LOCAL_SRC_FILES += \
-      $(call all-java-files-under,$(SUB_DIR))
-
-#DEFINED_SERVICES += com.android.server.print.PrintManagerService
-
-endif