Make UsbService optional

Tweaked the services Android.mk to build dependencies
when building with mm[m].

Change-Id: I6dad511c652bcacc085f27ede5f8f22a6982c6bd
diff --git a/core/java/com/android/server/SystemService.java b/core/java/com/android/server/SystemService.java
index 194a084..e374563 100644
--- a/core/java/com/android/server/SystemService.java
+++ b/core/java/com/android/server/SystemService.java
@@ -49,9 +49,32 @@
      * Boot Phases
      */
     public static final int PHASE_WAIT_FOR_DEFAULT_DISPLAY = 100; // maybe should be a dependency?
+
+    /**
+     * After receiving this boot phase, services can obtain lock settings data.
+     */
     public static final int PHASE_LOCK_SETTINGS_READY = 480;
+
+    /**
+     * After receiving this boot phase, services can safely call into core system services
+     * such as the PowerManager or PackageManager.
+     */
     public static final int PHASE_SYSTEM_SERVICES_READY = 500;
+
+    /**
+     * After receiving this boot phase, services can broadcast Intents.
+     */
+    public static final int PHASE_ACTIVITY_MANAGER_READY = 550;
+
+    /**
+     * After receiving this boot phase, services can start/bind to third party apps.
+     * Apps will be able to make Binder calls into services at this point.
+     */
     public static final int PHASE_THIRD_PARTY_APPS_CAN_START = 600;
+
+    /**
+     * After receiving this boot phase, services must have finished all boot-related work.
+     */
     public static final int PHASE_BOOT_COMPLETE = 1000;
 
     private final Context mContext;
diff --git a/core/java/com/android/server/SystemServiceManager.java b/core/java/com/android/server/SystemServiceManager.java
index 6c853be..eb8df0e 100644
--- a/core/java/com/android/server/SystemServiceManager.java
+++ b/core/java/com/android/server/SystemServiceManager.java
@@ -45,18 +45,13 @@
     }
 
     /**
-     * Starts a service by name if the class exists, otherwise ignores it.
+     * Starts a service by class name.
      *
-     * @return The service instance, or null if not found.
+     * @return The service instance.
      */
     @SuppressWarnings("unchecked")
-    public SystemService startServiceIfExists(String className) {
-        try {
-            return startService((Class<SystemService>)Class.forName(className));
-        } catch (ClassNotFoundException cnfe) {
-            Slog.i(TAG, className + " not available, ignoring.");
-            return null;
-        }
+    public SystemService startService(String className) throws ClassNotFoundException {
+        return startService((Class<SystemService>) Class.forName(className));
     }
 
     /**
diff --git a/services/Android.mk b/services/Android.mk
index a8881b6..5260540 100644
--- a/services/Android.mk
+++ b/services/Android.mk
@@ -8,13 +8,23 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under,java)
 
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    services.core \
-    services.accessibility \
-    services.appwidget \
-    services.backup \
-    services.devicepolicy \
-    services.print
+# Uncomment to enable output of certain warnings (deprecated, unchecked)
+# LOCAL_JAVACFLAGS := -Xlint
+
+# Services that will be built as part of services.jar
+# These should map to directory names relative to this
+# Android.mk.
+services := \
+    core \
+    accessibility \
+    appwidget \
+    backup \
+    devicepolicy \
+    print \
+    usb
+
+# The convention is to name each service module 'services.$(module_name)'
+LOCAL_STATIC_JAVA_LIBRARIES := $(addprefix services.,$(services))
 
 include $(BUILD_JAVA_LIBRARY)
 
@@ -39,7 +49,16 @@
 
 include $(BUILD_SHARED_LIBRARY)
 
+# =============================================================
+
 ifeq (,$(ONE_SHOT_MAKEFILE))
-include $(call all-makefiles-under, $(LOCAL_PATH))
+# A full make is happening, so make everything.
+include $(call all-makefiles-under,$(LOCAL_PATH))
+else
+# If we ran an mm[m] command, we still want to build the individual
+# services that we depend on. This differs from the above condition
+# by only including service makefiles and not any tests or other
+# modules.
+include $(patsubst %,$(LOCAL_PATH)/%/Android.mk,$(services))
 endif
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index afd7845..0e056eb 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -112,6 +112,8 @@
             "com.android.server.appwidget.AppWidgetService";
     private static final String PRINT_MANAGER_SERVICE_CLASS =
             "com.android.server.print.PrintManagerService";
+    private static final String USB_SERVICE_CLASS =
+            "com.android.server.usb.UsbService$Lifecycle";
 
     private final int mFactoryTestMode;
     private Timer mProfilerSnapshotTimer;
@@ -534,8 +536,7 @@
 
                 try {
                     if (pm.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN)) {
-                        mSystemServiceManager.startServiceIfExists(
-                                DEVICE_POLICY_MANAGER_SERVICE_CLASS);
+                        mSystemServiceManager.startService(DEVICE_POLICY_MANAGER_SERVICE_CLASS);
                     }
                 } catch (Throwable e) {
                     reportWtf("starting DevicePolicyService", e);
@@ -761,10 +762,11 @@
 
             if (!disableNonCoreServices) {
                 try {
-                    Slog.i(TAG, "USB Service");
-                    // Manage USB host and device support
-                    usb = new UsbService(context);
-                    ServiceManager.addService(Context.USB_SERVICE, usb);
+                    if (pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST) ||
+                            pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY)) {
+                        // Manage USB host and device support
+                        mSystemServiceManager.startService(USB_SERVICE_CLASS);
+                    }
                 } catch (Throwable e) {
                     reportWtf("starting UsbService", e);
                 }
@@ -786,7 +788,7 @@
             if (!disableNonCoreServices) {
                 try {
                     if (pm.hasSystemFeature(PackageManager.FEATURE_BACKUP)) {
-                        mSystemServiceManager.startServiceIfExists(BACKUP_MANAGER_SERVICE_CLASS);
+                        mSystemServiceManager.startService(BACKUP_MANAGER_SERVICE_CLASS);
                     }
                 } catch (Throwable e) {
                     Slog.e(TAG, "Failure starting Backup Service", e);
@@ -794,7 +796,7 @@
 
                 try {
                     if (pm.hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS)) {
-                        mSystemServiceManager.startServiceIfExists(APPWIDGET_SERVICE_CLASS);
+                        mSystemServiceManager.startService(APPWIDGET_SERVICE_CLASS);
                     }
                 } catch (Throwable e) {
                     reportWtf("starting AppWidget Service", e);
@@ -880,7 +882,7 @@
 
             try {
                 if (pm.hasSystemFeature(PackageManager.FEATURE_PRINTING)) {
-                    mSystemServiceManager.startServiceIfExists(PRINT_MANAGER_SERVICE_CLASS);
+                    mSystemServiceManager.startService(PRINT_MANAGER_SERVICE_CLASS);
                 }
             } catch (Throwable e) {
                 reportWtf("starting Print Service", e);
@@ -972,7 +974,6 @@
         }
 
         // These are needed to propagate to the runnable below.
-        final Context contextF = context;
         final MountService mountServiceF = mountService;
         final BatteryService batteryF = battery;
         final NetworkManagementService networkManagementF = networkManagement;
@@ -980,7 +981,6 @@
         final NetworkPolicyManagerService networkPolicyF = networkPolicy;
         final ConnectivityService connectivityF = connectivity;
         final DockObserver dockF = dock;
-        final UsbService usbF = usb;
         final WallpaperManagerService wallpaperF = wallpaper;
         final InputMethodManagerService immF = imm;
         final RecognitionManagerService recognitionF = recognition;
@@ -1000,132 +1000,138 @@
         // where third party code can really run (but before it has actually
         // started launching the initial applications), for us to complete our
         // initialization.
+        final Handler handler = new Handler();
         mActivityManagerService.systemReady(new Runnable() {
+            @Override
             public void run() {
-                Slog.i(TAG, "Making services ready");
+                // We initiate all boot phases on the SystemServer thread.
+                handler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        Slog.i(TAG, "Making services ready");
+                        mSystemServiceManager.startBootPhase(
+                                SystemService.PHASE_ACTIVITY_MANAGER_READY);
 
-                try {
-                    mActivityManagerService.startObservingNativeCrashes();
-                } catch (Throwable e) {
-                    reportWtf("observing native crashes", e);
-                }
-                try {
-                    startSystemUi(contextF);
-                } catch (Throwable e) {
-                    reportWtf("starting System UI", e);
-                }
-                try {
-                    if (mountServiceF != null) mountServiceF.systemReady();
-                } catch (Throwable e) {
-                    reportWtf("making Mount Service ready", e);
-                }
-                try {
-                    if (batteryF != null) batteryF.systemReady();
-                } catch (Throwable e) {
-                    reportWtf("making Battery Service ready", e);
-                }
-                try {
-                    if (networkManagementF != null) networkManagementF.systemReady();
-                } catch (Throwable e) {
-                    reportWtf("making Network Managment Service ready", e);
-                }
-                try {
-                    if (networkStatsF != null) networkStatsF.systemReady();
-                } catch (Throwable e) {
-                    reportWtf("making Network Stats Service ready", e);
-                }
-                try {
-                    if (networkPolicyF != null) networkPolicyF.systemReady();
-                } catch (Throwable e) {
-                    reportWtf("making Network Policy Service ready", e);
-                }
-                try {
-                    if (connectivityF != null) connectivityF.systemReady();
-                } catch (Throwable e) {
-                    reportWtf("making Connectivity Service ready", e);
-                }
-                try {
-                    if (dockF != null) dockF.systemReady();
-                } catch (Throwable e) {
-                    reportWtf("making Dock Service ready", e);
-                }
-                try {
-                    if (usbF != null) usbF.systemReady();
-                } catch (Throwable e) {
-                    reportWtf("making USB Service ready", e);
-                }
-                try {
-                    if (recognitionF != null) recognitionF.systemReady();
-                } catch (Throwable e) {
-                    reportWtf("making Recognition Service ready", e);
-                }
-                Watchdog.getInstance().start();
+                        try {
+                            mActivityManagerService.startObservingNativeCrashes();
+                        } catch (Throwable e) {
+                            reportWtf("observing native crashes", e);
+                        }
+                        try {
+                            startSystemUi(context);
+                        } catch (Throwable e) {
+                            reportWtf("starting System UI", e);
+                        }
+                        try {
+                            if (mountServiceF != null) mountServiceF.systemReady();
+                        } catch (Throwable e) {
+                            reportWtf("making Mount Service ready", e);
+                        }
+                        try {
+                            if (batteryF != null) batteryF.systemReady();
+                        } catch (Throwable e) {
+                            reportWtf("making Battery Service ready", e);
+                        }
+                        try {
+                            if (networkManagementF != null) networkManagementF.systemReady();
+                        } catch (Throwable e) {
+                            reportWtf("making Network Managment Service ready", e);
+                        }
+                        try {
+                            if (networkStatsF != null) networkStatsF.systemReady();
+                        } catch (Throwable e) {
+                            reportWtf("making Network Stats Service ready", e);
+                        }
+                        try {
+                            if (networkPolicyF != null) networkPolicyF.systemReady();
+                        } catch (Throwable e) {
+                            reportWtf("making Network Policy Service ready", e);
+                        }
+                        try {
+                            if (connectivityF != null) connectivityF.systemReady();
+                        } catch (Throwable e) {
+                            reportWtf("making Connectivity Service ready", e);
+                        }
+                        try {
+                            if (dockF != null) dockF.systemReady();
+                        } catch (Throwable e) {
+                            reportWtf("making Dock Service ready", e);
+                        }
+                        try {
+                            if (recognitionF != null) recognitionF.systemReady();
+                        } catch (Throwable e) {
+                            reportWtf("making Recognition Service ready", e);
+                        }
+                        Watchdog.getInstance().start();
 
-                // It is now okay to let the various system services start their
-                // third party code...
-                mSystemServiceManager.startBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
+                        // It is now okay to let the various system services start their
+                        // third party code...
+                        mSystemServiceManager.startBootPhase(
+                                SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
 
-                try {
-                    if (wallpaperF != null) wallpaperF.systemRunning();
-                } catch (Throwable e) {
-                    reportWtf("Notifying WallpaperService running", e);
-                }
-                try {
-                    if (immF != null) immF.systemRunning(statusBarF);
-                } catch (Throwable e) {
-                    reportWtf("Notifying InputMethodService running", e);
-                }
-                try {
-                    if (locationF != null) locationF.systemRunning();
-                } catch (Throwable e) {
-                    reportWtf("Notifying Location Service running", e);
-                }
-                try {
-                    if (countryDetectorF != null) countryDetectorF.systemRunning();
-                } catch (Throwable e) {
-                    reportWtf("Notifying CountryDetectorService running", e);
-                }
-                try {
-                    if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemRunning();
-                } catch (Throwable e) {
-                    reportWtf("Notifying NetworkTimeService running", e);
-                }
-                try {
-                    if (commonTimeMgmtServiceF != null) commonTimeMgmtServiceF.systemRunning();
-                } catch (Throwable e) {
-                    reportWtf("Notifying CommonTimeManagementService running", e);
-                }
-                try {
-                    if (textServiceManagerServiceF != null)
-                        textServiceManagerServiceF.systemRunning();
-                } catch (Throwable e) {
-                    reportWtf("Notifying TextServicesManagerService running", e);
-                }
-                try {
-                    if (atlasF != null) atlasF.systemRunning();
-                } catch (Throwable e) {
-                    reportWtf("Notifying AssetAtlasService running", e);
-                }
-                try {
-                    // TODO(BT) Pass parameter to input manager
-                    if (inputManagerF != null) inputManagerF.systemRunning();
-                } catch (Throwable e) {
-                    reportWtf("Notifying InputManagerService running", e);
-                }
+                        try {
+                            if (wallpaperF != null) wallpaperF.systemRunning();
+                        } catch (Throwable e) {
+                            reportWtf("Notifying WallpaperService running", e);
+                        }
+                        try {
+                            if (immF != null) immF.systemRunning(statusBarF);
+                        } catch (Throwable e) {
+                            reportWtf("Notifying InputMethodService running", e);
+                        }
+                        try {
+                            if (locationF != null) locationF.systemRunning();
+                        } catch (Throwable e) {
+                            reportWtf("Notifying Location Service running", e);
+                        }
+                        try {
+                            if (countryDetectorF != null) countryDetectorF.systemRunning();
+                        } catch (Throwable e) {
+                            reportWtf("Notifying CountryDetectorService running", e);
+                        }
+                        try {
+                            if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemRunning();
+                        } catch (Throwable e) {
+                            reportWtf("Notifying NetworkTimeService running", e);
+                        }
+                        try {
+                            if (commonTimeMgmtServiceF != null) {
+                                commonTimeMgmtServiceF.systemRunning();
+                            }
+                        } catch (Throwable e) {
+                            reportWtf("Notifying CommonTimeManagementService running", e);
+                        }
+                        try {
+                            if (textServiceManagerServiceF != null)
+                                textServiceManagerServiceF.systemRunning();
+                        } catch (Throwable e) {
+                            reportWtf("Notifying TextServicesManagerService running", e);
+                        }
+                        try {
+                            if (atlasF != null) atlasF.systemRunning();
+                        } catch (Throwable e) {
+                            reportWtf("Notifying AssetAtlasService running", e);
+                        }
+                        try {
+                            // TODO(BT) Pass parameter to input manager
+                            if (inputManagerF != null) inputManagerF.systemRunning();
+                        } catch (Throwable e) {
+                            reportWtf("Notifying InputManagerService running", e);
+                        }
+                        try {
+                            if (telephonyRegistryF != null) telephonyRegistryF.systemRunning();
+                        } catch (Throwable e) {
+                            reportWtf("Notifying TelephonyRegistry running", e);
+                        }
+                        try {
+                            if (mediaRouterF != null) mediaRouterF.systemRunning();
+                        } catch (Throwable e) {
+                            reportWtf("Notifying MediaRouterService running", e);
+                        }
 
-                try {
-                    if (telephonyRegistryF != null) telephonyRegistryF.systemRunning();
-                } catch (Throwable e) {
-                    reportWtf("Notifying TelephonyRegistry running", e);
-                }
-
-                try {
-                    if (mediaRouterF != null) mediaRouterF.systemRunning();
-                } catch (Throwable e) {
-                    reportWtf("Notifying MediaRouterService running", e);
-                }
-
-                mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETE);
+                        mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETE);
+                    }
+                });
             }
         });
     }
diff --git a/services/usb/Android.mk b/services/usb/Android.mk
new file mode 100644
index 0000000..feabf0a
--- /dev/null
+++ b/services/usb/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := services.usb
+
+LOCAL_SRC_FILES += \
+      $(call all-java-files-under,java)
+
+LOCAL_JAVA_LIBRARIES := services.core
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/core/java/com/android/server/usb/UsbDebuggingManager.java b/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
similarity index 100%
rename from services/core/java/com/android/server/usb/UsbDebuggingManager.java
rename to services/usb/java/com/android/server/usb/UsbDebuggingManager.java
diff --git a/services/core/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
similarity index 99%
rename from services/core/java/com/android/server/usb/UsbDeviceManager.java
rename to services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 5a60de0..9a4d8d8 100644
--- a/services/core/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -812,7 +812,7 @@
                     if (mOemModeMap == null) {
                         mOemModeMap = new HashMap<String, List<Pair<String, String>>>();
                     }
-                    List overrideList = mOemModeMap.get(items[0]);
+                    List<Pair<String, String>> overrideList = mOemModeMap.get(items[0]);
                     if (overrideList == null) {
                         overrideList = new LinkedList<Pair<String, String>>();
                         mOemModeMap.put(items[0], overrideList);
diff --git a/services/core/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java
similarity index 100%
rename from services/core/java/com/android/server/usb/UsbHostManager.java
rename to services/usb/java/com/android/server/usb/UsbHostManager.java
diff --git a/services/core/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
similarity index 94%
rename from services/core/java/com/android/server/usb/UsbService.java
rename to services/usb/java/com/android/server/usb/UsbService.java
index 36669b1..b6ae192 100644
--- a/services/core/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -32,6 +32,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.SystemService;
 
 import java.io.File;
 import java.io.FileDescriptor;
@@ -43,6 +44,28 @@
  * support is delegated to UsbDeviceManager.
  */
 public class UsbService extends IUsbManager.Stub {
+
+    public static class Lifecycle extends SystemService {
+        private UsbService mUsbService;
+
+        public Lifecycle(Context context) {
+            super(context);
+        }
+
+        @Override
+        public void onStart() {
+            mUsbService = new UsbService(getContext());
+            publishBinderService(Context.USB_SERVICE, mUsbService);
+        }
+
+        @Override
+        public void onBootPhase(int phase) {
+            if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
+                mUsbService.systemReady();
+            }
+        }
+    }
+
     private static final String TAG = "UsbService";
 
     private final Context mContext;
diff --git a/services/core/java/com/android/server/usb/UsbSettingsManager.java b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
similarity index 100%
rename from services/core/java/com/android/server/usb/UsbSettingsManager.java
rename to services/usb/java/com/android/server/usb/UsbSettingsManager.java