OmniLib: Create OmniRomSystemServer to handle our platform init.
Change-Id: I7b62978e2a284a3a1ec1ffc1d8c72545d7b0c939
diff --git a/Android.bp b/Android.bp
index 1784ff6..3eddf86 100644
--- a/Android.bp
+++ b/Android.bp
@@ -61,5 +61,6 @@
libs: [
"framework",
"OmniPreference",
+ "services",
],
}
diff --git a/res/values/config.xml b/res/values/config.xml
index 496982d..f1e549f 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -20,4 +20,12 @@
<bool name="config_FastChargingLedSupported">false</bool>
<!-- Default value for led color when fast charging is active -->
<integer name="config_notificationsFastBatteryARGB">0x0000FF</integer>
+
+ <!-- Defines external services to be started by the OmniRomSystemServer at boot. The service itself
+ should publish as a binder services in its onStart -->
+ <string-array name="config_externalOmniRomServices">
+ </string-array>
+
+ <!-- The LineageSystemServer class that is invoked from Android's SystemServer -->
+ <string name="config_externalSystemServer" translatable="false">org.omnirom.omnilib.internal.OmniRomSystemServer</string>
</resources>
diff --git a/res/values/symbols.xml b/res/values/symbols.xml
index 3537b6d..00e8cc7 100644
--- a/res/values/symbols.xml
+++ b/res/values/symbols.xml
@@ -45,4 +45,9 @@
<java-symbol name="reboot_system_message" type="string" />
<java-symbol type="array" name="config_rebootActionsList" />
+ <!-- External OmniRom specific core services -->
+ <java-symbol type="array" name="config_externalOmniRomServices" />
+ <!-- OmniRom system server -->
+ <java-symbol type="string" name="config_externalSystemServer" />
+
</resources>
diff --git a/src/org/omnirom/omnilib/internal/OmniRomSystemServer.java b/src/org/omnirom/omnilib/internal/OmniRomSystemServer.java
new file mode 100644
index 0000000..16368e4
--- /dev/null
+++ b/src/org/omnirom/omnilib/internal/OmniRomSystemServer.java
@@ -0,0 +1,90 @@
+/*
+ * SPDX-FileCopyrightText: 2016 The CyanogenMod Project
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package org.omnirom.omnilib.internal;
+
+import android.content.Context;
+import android.os.SystemProperties;
+import android.util.Slog;
+import com.android.server.LocalServices;
+import com.android.server.SystemServiceManager;
+
+import org.omnirom.omnilib.internal.common.OmniRomSystemServiceHelper;
+
+/**
+ * Base OmniRom System Server which handles the starting and states of various OmniRom
+ * specific system services. Since its part of the main looper provided by the system
+ * server, it will be available indefinitely (until all the things die).
+ */
+public class OmniRomSystemServer {
+ private static final String TAG = "OmniRomSystemServer";
+ private Context mSystemContext;
+ private OmniRomSystemServiceHelper mSystemServiceHelper;
+
+ private static final String ENCRYPTING_STATE = "trigger_restart_min_framework";
+ private static final String ENCRYPTED_STATE = "1";
+
+ public OmniRomSystemServer(Context systemContext) {
+ mSystemContext = systemContext;
+ mSystemServiceHelper = new OmniRomSystemServiceHelper(mSystemContext);
+ }
+
+ public static boolean coreAppsOnly() {
+ // Only run "core" apps+services if we're encrypting the device.
+ final String cryptState = SystemProperties.get("vold.decrypt");
+ final boolean isAlarmBoot = SystemProperties.getBoolean("ro.alarm_boot", false);
+ return ENCRYPTING_STATE.equals(cryptState) ||
+ ENCRYPTED_STATE.equals(cryptState) ||
+ isAlarmBoot;
+ }
+
+ /**
+ * Invoked via reflection by the SystemServer
+ */
+ private void run() {
+ // Start services.
+ try {
+ startServices();
+ } catch (Throwable ex) {
+ Slog.e("System", "******************************************");
+ Slog.e("System", "************ Failure starting omnirom system services", ex);
+ throw ex;
+ }
+ }
+
+ private void startServices() {
+ final Context context = mSystemContext;
+ final SystemServiceManager ssm = LocalServices.getService(SystemServiceManager.class);
+ String[] externalServices = context.getResources().getStringArray(
+ org.omnirom.omnilib.R.array.config_externalOmniRomServices);
+
+ for (String service : externalServices) {
+ try {
+ Slog.i(TAG, "Attempting to start service " + service);
+ OmniRomSystemService omniromSystemService = mSystemServiceHelper.getServiceFor(service);
+ if (context.getPackageManager().hasSystemFeature(
+ omniromSystemService.getFeatureDeclaration())) {
+ if (coreAppsOnly() && !omniromSystemService.isCoreService()) {
+ Slog.d(TAG, "Not starting " + service +
+ " - only parsing core apps");
+ } else {
+ Slog.i(TAG, "Starting service " + service);
+ ssm.startService(omniromSystemService.getClass());
+ }
+ } else {
+ Slog.i(TAG, "Not starting service " + service +
+ " due to feature not declared on device");
+ }
+ } catch (Throwable e) {
+ reportWtf("starting " + service , e);
+ }
+ }
+ }
+
+ private void reportWtf(String msg, Throwable e) {
+ Slog.w(TAG, "***********************************************");
+ Slog.wtf(TAG, "BOOT FAILURE " + msg, e);
+ }
+}
diff --git a/src/org/omnirom/omnilib/internal/OmniRomSystemService.java b/src/org/omnirom/omnilib/internal/OmniRomSystemService.java
new file mode 100644
index 0000000..3426733
--- /dev/null
+++ b/src/org/omnirom/omnilib/internal/OmniRomSystemService.java
@@ -0,0 +1,26 @@
+/*
+ * SPDX-FileCopyrightText: 2016 The CyanogenMod Project
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package org.omnirom.omnilib.internal;
+
+import android.content.Context;
+import com.android.server.SystemService;
+
+public abstract class OmniRomSystemService extends SystemService {
+ public OmniRomSystemService(Context context) {
+ super(context);
+ }
+
+ public abstract String getFeatureDeclaration();
+
+
+ /**
+ * Override and return true if the service should be started
+ * before the device is decrypted.
+ */
+ public boolean isCoreService() {
+ return true;
+ }
+}
diff --git a/src/org/omnirom/omnilib/internal/common/OmniRomSystemServiceHelper.java b/src/org/omnirom/omnilib/internal/common/OmniRomSystemServiceHelper.java
new file mode 100644
index 0000000..fc32326
--- /dev/null
+++ b/src/org/omnirom/omnilib/internal/common/OmniRomSystemServiceHelper.java
@@ -0,0 +1,56 @@
+/*
+ * SPDX-FileCopyrightText: 2016 The CyanogenMod Project
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package org.omnirom.omnilib.internal.common;
+
+import android.content.Context;
+import org.omnirom.omnilib.internal.OmniRomSystemService;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Helper methods for fetching a OmniRomSystemService from a class declaration
+ */
+public class OmniRomSystemServiceHelper {
+ private Context mContext;
+
+ public OmniRomSystemServiceHelper(Context context) {
+ mContext = context;
+ }
+
+ public OmniRomSystemService getServiceFor(String className) {
+ final Class<OmniRomSystemService> serviceClass;
+ try {
+ serviceClass = (Class<OmniRomSystemService>)Class.forName(className);
+ } catch (ClassNotFoundException ex) {
+ throw new RuntimeException("Failed to create service " + className
+ + ": service class not found", ex);
+ }
+
+ return getServiceFromClass(serviceClass);
+ }
+
+ public <T extends OmniRomSystemService> T getServiceFromClass(Class<T> serviceClass) {
+ final T service;
+ try {
+ Constructor<T> constructor = serviceClass.getConstructor(Context.class);
+ service = constructor.newInstance(mContext);
+ } catch (InstantiationException ex) {
+ throw new RuntimeException("Failed to create service " + serviceClass
+ + ": service could not be instantiated", ex);
+ } catch (IllegalAccessException ex) {
+ throw new RuntimeException("Failed to create service " + serviceClass
+ + ": service must have a public constructor with a Context argument", ex);
+ } catch (NoSuchMethodException ex) {
+ throw new RuntimeException("Failed to create service " + serviceClass
+ + ": service must have a public constructor with a Context argument", ex);
+ } catch (InvocationTargetException ex) {
+ throw new RuntimeException("Failed to create service " + serviceClass
+ + ": service constructor threw an exception", ex);
+ }
+ return service;
+ }
+}