Merge "Make the MIDI Manager optional, enabled by "android.software.midi" feature"
diff --git a/api/current.txt b/api/current.txt
index 4c761ce..d0a445b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -9146,6 +9146,7 @@
     field public static final java.lang.String FEATURE_LOCATION_NETWORK = "android.hardware.location.network";
     field public static final java.lang.String FEATURE_MANAGED_USERS = "android.software.managed_users";
     field public static final java.lang.String FEATURE_MICROPHONE = "android.hardware.microphone";
+    field public static final java.lang.String FEATURE_MIDI = "android.software.midi";
     field public static final java.lang.String FEATURE_NFC = "android.hardware.nfc";
     field public static final java.lang.String FEATURE_NFC_HOST_CARD_EMULATION = "android.hardware.nfc.hce";
     field public static final java.lang.String FEATURE_OPENGLES_EXTENSION_PACK = "android.hardware.opengles.aep";
diff --git a/api/system-current.txt b/api/system-current.txt
index 4a331de..40927c1 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -9395,6 +9395,7 @@
     field public static final java.lang.String FEATURE_LOCATION_NETWORK = "android.hardware.location.network";
     field public static final java.lang.String FEATURE_MANAGED_USERS = "android.software.managed_users";
     field public static final java.lang.String FEATURE_MICROPHONE = "android.hardware.microphone";
+    field public static final java.lang.String FEATURE_MIDI = "android.software.midi";
     field public static final java.lang.String FEATURE_NFC = "android.hardware.nfc";
     field public static final java.lang.String FEATURE_NFC_HOST_CARD_EMULATION = "android.hardware.nfc.hce";
     field public static final java.lang.String FEATURE_OPENGLES_EXTENSION_PACK = "android.hardware.opengles.aep";
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 59a16da..f0d1da9 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1600,6 +1600,12 @@
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_GAMEPAD = "android.hardware.gamepad";
 
+    /**
+     * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+     * The device has a full implementation of the android.media.midi.* APIs.
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_MIDI = "android.software.midi";
 
     /**
      * Action to external storage service to clean out removed apps.
diff --git a/services/Android.mk b/services/Android.mk
index 8777085..1918db5 100644
--- a/services/Android.mk
+++ b/services/Android.mk
@@ -24,6 +24,7 @@
     appwidget \
     backup \
     devicepolicy \
+    midi \
     net \
     print \
     restrictions \
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 65e3534..8c653e2 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -124,6 +124,8 @@
             "com.android.server.print.PrintManagerService";
     private static final String USB_SERVICE_CLASS =
             "com.android.server.usb.UsbService$Lifecycle";
+    private static final String MIDI_SERVICE_CLASS =
+            "com.android.server.midi.MidiService$Lifecycle";
     private static final String WIFI_SERVICE_CLASS =
             "com.android.server.wifi.WifiService";
     private static final String WIFI_P2P_SERVICE_CLASS =
@@ -810,6 +812,11 @@
             }
 
             if (!disableNonCoreServices) {
+                if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_MIDI)) {
+                    // Start MIDI Manager service
+                    mSystemServiceManager.startService(MIDI_SERVICE_CLASS);
+                }
+
                 if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)
                         || mPackageManager.hasSystemFeature(
                                 PackageManager.FEATURE_USB_ACCESSORY)) {
@@ -827,16 +834,6 @@
                 }
             }
 
-            if (!disableNonCoreServices) {
-                try {
-                    Slog.i(TAG, "MIDI Service");
-                    ServiceManager.addService(Context.MIDI_SERVICE,
-                            new MidiService(context));
-                } catch (Throwable e) {
-                    reportWtf("starting MIDI Service", e);
-                }
-            }
-
             mSystemServiceManager.startService(TwilightService.class);
 
             mSystemServiceManager.startService(JobSchedulerService.class);
diff --git a/services/midi/Android.mk b/services/midi/Android.mk
new file mode 100644
index 0000000..faac01c
--- /dev/null
+++ b/services/midi/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := services.midi
+
+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/MidiService.java b/services/midi/java/com/android/server/midi/MidiService.java
similarity index 97%
rename from services/core/java/com/android/server/MidiService.java
rename to services/midi/java/com/android/server/midi/MidiService.java
index e753664..1d2180e 100644
--- a/services/core/java/com/android/server/MidiService.java
+++ b/services/midi/java/com/android/server/midi/MidiService.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server;
+package com.android.server.midi;
 
 import android.content.Context;
 import android.content.Intent;
@@ -40,6 +40,7 @@
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.XmlUtils;
+import com.android.server.SystemService;
 
 import org.xmlpull.v1.XmlPullParser;
 
@@ -51,6 +52,21 @@
 import java.util.List;
 
 public class MidiService extends IMidiManager.Stub {
+
+    public static class Lifecycle extends SystemService {
+        private MidiService mMidiService;
+
+        public Lifecycle(Context context) {
+            super(context);
+        }
+
+        @Override
+        public void onStart() {
+            mMidiService = new MidiService(getContext());
+            publishBinderService(Context.MIDI_SERVICE, mMidiService);
+        }
+    }
+
     private static final String TAG = "MidiService";
 
     private final Context mContext;
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index c041029..2728af1 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -17,6 +17,7 @@
 package com.android.server.usb;
 
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.hardware.usb.UsbConstants;
 import android.hardware.usb.UsbDevice;
@@ -55,6 +56,7 @@
 
     private final Context mContext;
     private IAudioService mAudioService;
+    private final boolean mHasMidiFeature;
 
     private final AlsaCardsParser mCardsParser = new AlsaCardsParser();
     private final AlsaDevicesParser mDevicesParser = new AlsaDevicesParser();
@@ -126,6 +128,7 @@
 
     /* package */ UsbAlsaManager(Context context) {
         mContext = context;
+        mHasMidiFeature = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI);
 
         // initial scan
         mCardsParser.scan();
@@ -389,7 +392,7 @@
             // mDevicesParser.scan()
 
             boolean hasMidi = mDevicesParser.hasMIDIDevices(addedCard);
-            if (hasMidi) {
+            if (hasMidi && mHasMidiFeature) {
                 int device = mDevicesParser.getDefaultDeviceNum(addedCard);
                 AlsaDevice alsaDevice = waitForAlsaDevice(addedCard, device, AlsaDevice.TYPE_MIDI);
                 if (alsaDevice != null) {
@@ -459,6 +462,10 @@
     }
 
    /* package */ void setPeripheralMidiState(boolean enabled, int card, int device) {
+        if (!mHasMidiFeature) {
+            return;
+        }
+
         if (enabled && mPeripheralMidiDevice == null) {
             Bundle properties = new Bundle();
             Resources r = mContext.getResources();