1e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer/* 2e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * Copyright (C) 2016 The Android Open Source Project 3e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * 4e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * Licensed under the Apache License, Version 2.0 (the "License"); 5e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * you may not use this file except in compliance with the License. 6e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * You may obtain a copy of the License at 7e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * 8e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * http://www.apache.org/licenses/LICENSE-2.0 9e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * 10e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * Unless required by applicable law or agreed to in writing, software 11e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * distributed under the License is distributed on an "AS IS" BASIS, 12e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * See the License for the specific language governing permissions and 14e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * limitations under the License. 15e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer */ 16e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 17e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerpackage org.chromium.latency.walt; 18e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 19e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerimport android.content.BroadcastReceiver; 20e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerimport android.content.Context; 21e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerimport android.content.Intent; 22e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerimport android.os.Bundle; 23e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerimport android.support.v4.app.Fragment; 24e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerimport android.text.method.ScrollingMovementMethod; 25e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerimport android.view.LayoutInflater; 26e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerimport android.view.View; 27e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerimport android.view.ViewGroup; 28e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerimport android.widget.TextView; 29e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 30e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerimport java.util.Locale; 31e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 32e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerpublic class MidiFragment extends Fragment 33e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer implements View.OnClickListener, BaseTest.TestStateListener { 34e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 35e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer private SimpleLogger logger; 36e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer private TextView textView; 37e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer private View startMidiInButton; 38e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer private View startMidiOutButton; 39e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer private HistogramChart latencyChart; 40e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer private MidiTest midiTest; 41e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 42e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer public MidiFragment() { 43e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // Required empty public constructor 44e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 45e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 46e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer @Override 47e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer public View onCreateView(LayoutInflater inflater, ViewGroup container, 48e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer Bundle savedInstanceState) { 49e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer logger = SimpleLogger.getInstance(getContext()); 50e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer midiTest = new MidiTest(getActivity()); 51e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer midiTest.setTestStateListener(this); 52e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 53e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer final View view = inflater.inflate(R.layout.fragment_midi, container, false); 54e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer textView = (TextView) view.findViewById(R.id.txt_box_midi); 55e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer startMidiInButton = view.findViewById(R.id.button_start_midi_in); 56e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer startMidiOutButton = view.findViewById(R.id.button_start_midi_out); 57e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer latencyChart = (HistogramChart) view.findViewById(R.id.latency_chart); 58e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer textView.setMovementMethod(new ScrollingMovementMethod()); 59e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer return view; 60e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 61e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 62e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer @Override 63e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer public void onResume() { 64e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer super.onResume(); 65e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 66e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // Register this fragment class as the listener for some button clicks 67e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer startMidiInButton.setOnClickListener(this); 68e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer startMidiOutButton.setOnClickListener(this); 69e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 70e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer textView.setText(logger.getLogText()); 71e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer logger.registerReceiver(logReceiver); 72e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 73e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 74e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer @Override 75e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer public void onPause() { 76e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer logger.unregisterReceiver(logReceiver); 77e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer super.onPause(); 78e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 79e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 80e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer @Override 81e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer public void onClick(View v) { 82e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer switch (v.getId()) { 83e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer case R.id.button_start_midi_in: 84e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer disableButtons(); 85e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer latencyChart.setVisibility(View.VISIBLE); 86e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer latencyChart.clearData(); 87e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer latencyChart.setLegendEnabled(false); 88e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer latencyChart.getBarChart().getDescription().setText("MIDI Input Latency [ms]"); 89e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer midiTest.testMidiIn(); 90e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer break; 91e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer case R.id.button_start_midi_out: 92e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer disableButtons(); 93e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer latencyChart.setVisibility(View.VISIBLE); 94e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer latencyChart.clearData(); 95e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer latencyChart.setLegendEnabled(false); 96e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer latencyChart.getBarChart().getDescription().setText("MIDI Output Latency [ms]"); 97e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer midiTest.testMidiOut(); 98e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer break; 99e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 100e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 101e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 102e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer private void disableButtons() { 103e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer startMidiInButton.setEnabled(false); 104e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer startMidiOutButton.setEnabled(false); 105e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 106e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 107e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer private BroadcastReceiver logReceiver = new BroadcastReceiver() { 108e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer @Override 109e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer public void onReceive(Context context, Intent intent) { 110e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer String msg = intent.getStringExtra("message"); 111e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer textView.append(msg + "\n"); 112e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 113e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer }; 114e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 115e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer @Override 116e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer public void onTestStopped() { 117e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer if (!midiTest.deltasOutputTotal.isEmpty()) { 118e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer latencyChart.setLegendEnabled(true); 119e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer latencyChart.setLabel(String.format( 120e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer Locale.US, "Median=%.1f ms", Utils.median(midiTest.deltasOutputTotal))); 121e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } else if (!midiTest.deltasInputTotal.isEmpty()) { 122e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer latencyChart.setLegendEnabled(true); 123e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer latencyChart.setLabel(String.format( 124e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer Locale.US, "Median=%.1f ms", Utils.median(midiTest.deltasInputTotal))); 125e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 126e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer LogUploader.uploadIfAutoEnabled(getContext()); 127e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer startMidiInButton.setEnabled(true); 128e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer startMidiOutButton.setEnabled(true); 129e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 130e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 131e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer @Override 132e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer public void onTestStoppedWithError() { 133e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer onTestStopped(); 134e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer latencyChart.setVisibility(View.GONE); 135e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 136e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 137e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer @Override 138e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer public void onTestPartialResult(double value) { 139e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer latencyChart.addEntry(value); 140e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 141e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 142e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer public static boolean hasMidi(Context context) { 143e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer return context.getPackageManager(). 144e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer hasSystemFeature("android.software.midi"); 145e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 146e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer} 147