• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.cts.verifier.audio;
18 
19 import java.io.IOException;
20 
21 import android.media.midi.MidiDevice;
22 import android.media.midi.MidiDeviceInfo;
23 import android.media.midi.MidiManager;
24 import android.media.midi.MidiReceiver;
25 import android.os.Bundle;
26 import android.util.Log;
27 
28 import com.android.compatibility.common.util.CddTest;
29 
30 import com.android.cts.verifier.audio.midilib.MidiIODevice;
31 import com.android.cts.verifier.audio.midilib.NativeMidiManager;
32 import com.android.cts.verifier.R;
33 
34 /*
35  * A note about the USB MIDI device.
36  * Any USB MIDI peripheral with standard female DIN jacks can be used. A standard MIDI cable
37  * plugged into both input and output is required for the USB Loopback Test. A Bluetooth MIDI
38  * device like the Yamaha MD-BT01 plugged into both input and output is required for the
39  * Bluetooth Loopback test.
40  */
41 
42 /*
43  * A note about the "virtual MIDI" device...
44  * See file MidiEchoService for implementation of the echo server itself.
45  * This service is started by the main manifest file (AndroidManifest.xml).
46  */
47 
48 /*
49  * A note about Bluetooth MIDI devices...
50  * Any Bluetooth MIDI device needs to be paired with the DUT with the "MIDI+BTLE" application
51  * available in the Play Store:
52  * (https://play.google.com/store/apps/details?id=com.mobileer.example.midibtlepairing).
53  */
54 
55 /**
56  * CTS Verifier Activity for MIDI test
57  */
58 @CddTest(requirement = "5.9/C-1-3,C-1-2")
59 public class MidiNativeTestActivity extends MidiTestActivityBase {
60     private static final String TAG = "MidiNativeTestActivity";
61     private static final boolean DEBUG = false;
62 
MidiNativeTestActivity()63     public MidiNativeTestActivity() {
64         super();
65         initTestModules(new NativeMidiTestModule(MidiDeviceInfo.TYPE_USB),
66                 new NativeMidiTestModule(MidiDeviceInfo.TYPE_VIRTUAL),
67                 new BTMidiTestModule());
68 
69         NativeMidiManager.loadNativeAPI();
70         NativeMidiManager.initN();
71     }
72 
73     @Override
onCreate(Bundle savedInstanceState)74     protected void onCreate(Bundle savedInstanceState) {
75         if (DEBUG) {
76             Log.i(TAG, "---- onCreate()");
77         }
78 
79         setContentView(R.layout.ndk_midi_activity);
80 
81         super.onCreate(savedInstanceState);
82 
83         startMidiEchoServer();
84         scanMidiDevices();
85 
86         connectDeviceListener();
87     }
88 
89     @Override
onPause()90     protected void onPause () {
91         super.onPause();
92         if (DEBUG) {
93             Log.i(TAG, "---- onPause()");
94         }
95 
96         boolean isFound = stopService(mMidiServiceIntent);
97         if (DEBUG) {
98             Log.i(TAG, "---- Stop Service: " + isFound);
99         }
100     }
101 
102     /**
103      * A class to control and represent the state of a given test.
104      * It hold the data needed for IO, and the logic for sending, receiving and matching
105      * the MIDI data stream.
106      */
107     public class NativeMidiTestModule extends MidiTestModule {
108         private static final String TAG = "NativeMidiTestModule";
109         private static final boolean DEBUG = true;
110 
111         private NativeMidiManager   mNativeMidiManager;
112 
NativeMidiTestModule(int deviceType)113         public NativeMidiTestModule(int deviceType) {
114             super(deviceType);
115             mNativeMidiManager = new NativeMidiManager();
116 
117             // this call is just to keep the build from stripping out "endTest", because
118             // it is only called from JNI.
119             endTest(TESTSTATUS_NOTRUN);
120         }
121 
closePorts()122         protected void closePorts() {
123             // NOP
124         }
125 
126         @Override
startLoopbackTest(int testID)127         void startLoopbackTest(int testID) {
128             synchronized (mTestLock) {
129                 mTestRunning = true;
130                 enableTestButtons(false);
131             }
132 
133             if (DEBUG) {
134                 Log.i(TAG, "---- startLoopbackTest()");
135             }
136 
137             mRunningTestID = testID;
138 
139             synchronized (mTestLock) {
140                 mTestStatus = TESTSTATUS_NOTRUN;
141             }
142 
143             if (mIODevice.mSendDevInfo != null) {
144                 mMidiManager.openDevice(mIODevice.mSendDevInfo, new TestModuleOpenListener(), null);
145             }
146 
147             startTimeoutHandler();
148         }
149 
150         @Override
hasTestPassed()151         boolean hasTestPassed() {
152             int status;
153             synchronized (mTestLock) {
154                 status = mTestStatus;
155             }
156             return status == TESTSTATUS_PASSED;
157         }
158 
endTest(int endCode)159         public void endTest(int endCode) {
160             synchronized (mTestLock) {
161                 mTestRunning = false;
162                 mTestStatus = endCode;
163             }
164             if (endCode != TESTSTATUS_NOTRUN) {
165                 updateTestStateUI();
166                 enableTestButtons(true);
167             }
168 
169             closePorts();
170         }
171 
172         /**
173          * Listens for MIDI device opens. Opens I/O ports and sends out the apriori
174          * setup messages.
175          */
176         class TestModuleOpenListener implements MidiManager.OnDeviceOpenedListener {
177             //
178             // This is where the logical part of the test starts
179             //
180             @Override
onDeviceOpened(MidiDevice device)181             public void onDeviceOpened(MidiDevice device) {
182                 if (DEBUG) {
183                     Log.i(TAG, "---- onDeviceOpened()");
184                 }
185                 mNativeMidiManager.startTest(NativeMidiTestModule.this, device,
186                         mRunningTestID == TESTID_BTLOOPBACK);
187             }
188         }
189     } /* class NativeMidiTestModule */
190 
191     /**
192      * Test Module for Bluetooth Loopback.
193      * This is a specialization of NativeMidiTestModule (which has the connections for the BL device
194      * itself) with and added MidiIODevice object for the USB audio device which does the
195      * "looping back".
196      */
197     private class BTMidiTestModule extends NativeMidiTestModule {
198         private static final String TAG = "BTMidiTestModule";
199         private MidiIODevice mUSBLoopbackDevice = new MidiIODevice(MidiDeviceInfo.TYPE_USB);
200 
BTMidiTestModule()201         public BTMidiTestModule() {
202             super(MidiDeviceInfo.TYPE_BLUETOOTH);
203         }
204 
205         @Override
scanDevices(MidiDeviceInfo[] devInfos)206         public void scanDevices(MidiDeviceInfo[] devInfos) {
207             // (normal) Scan for BT MIDI device
208             super.scanDevices(devInfos);
209             // Find a USB Loopback Device
210             mUSBLoopbackDevice.scanDevices(devInfos);
211         }
212 
closePorts()213         protected void closePorts() {
214             super.closePorts();
215             if (mUSBLoopbackDevice != null) {
216                 mUSBLoopbackDevice.closePorts();
217             }
218         }
219 
220         @Override
startLoopbackTest(int testID)221         void startLoopbackTest(int testID) {
222             if (DEBUG) {
223                 Log.i(TAG, "---- startLoopbackTest()");
224             }
225             // Setup the USB Loopback Device
226             mUSBLoopbackDevice.closePorts();
227 
228             if (mIODevice.mSendDevInfo != null) {
229                 mMidiManager.openDevice(
230                         mUSBLoopbackDevice.mSendDevInfo, new USBLoopbackOpenListener(), null);
231             }
232 
233             // Now start the test as usual
234             super.startLoopbackTest(testID);
235         }
236 
237         /**
238          * We need this OnDeviceOpenedListener to open the USB-Loopback device
239          */
240         private class USBLoopbackOpenListener implements MidiManager.OnDeviceOpenedListener {
241             @Override
onDeviceOpened(MidiDevice device)242             public void onDeviceOpened(MidiDevice device) {
243                 if (DEBUG) {
244                     Log.i("USBLoopbackOpenListener", "---- onDeviceOpened()");
245                 }
246                 mUSBLoopbackDevice.openPorts(device, new USBMidiEchoReceiver());
247             }
248         } /* class USBLoopbackOpenListener */
249 
250         /**
251          * MidiReceiver subclass for BlueTooth Loopback Test
252          *
253          * This class receives bytes from the USB Interface (presumably coming from the
254          * Bluetooth MIDI peripheral) and echoes them back out (presumably to the Bluetooth
255          * MIDI peripheral).
256          */
257         //TODO - This could be pulled out into a separate class and shared with the identical
258         // code in MidiJavaTestActivity is we pass in the send port
259         private class USBMidiEchoReceiver extends MidiReceiver {
260             private int mTotalBytesEchoed;
261 
262             @Override
onSend(byte[] msg, int offset, int count, long timestamp)263             public void onSend(byte[] msg, int offset, int count, long timestamp) throws IOException {
264                 mTotalBytesEchoed += count;
265                 if (DEBUG) {
266                     Log.i(TAG, "---- USBMidiEchoReceiver.onSend() count:" + count +
267                             " total:" + mTotalBytesEchoed);
268                 }
269                 if (mUSBLoopbackDevice.mSendPort == null) {
270                     Log.e(TAG, "(native) mUSBLoopbackDevice.mSendPort is null");
271                 } else {
272                     mUSBLoopbackDevice.mSendPort.onSend(msg, offset, count, timestamp);
273                 }
274             }
275         } /* class USBMidiEchoReceiver */
276     } /* class BTMidiTestModule */
277 } /* class MidiNativeTestActivity */
278