1 package com.google.oboe.samples.megadrone; 2 3 /* 4 * Copyright 2018 The Android Open Source Project 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 import androidx.appcompat.app.AppCompatActivity; 20 21 import android.content.Context; 22 import android.media.AudioManager; 23 import android.os.Build; 24 import android.os.Bundle; 25 import android.util.Log; 26 import android.view.MotionEvent; 27 28 public class MainActivity extends AppCompatActivity { 29 30 private final String TAG = MainActivity.class.toString(); 31 private static long mEngineHandle = 0; 32 startEngine(int[] cpuIds)33 private native long startEngine(int[] cpuIds); stopEngine(long engineHandle)34 private native void stopEngine(long engineHandle); tap(long engineHandle, boolean isDown)35 private native void tap(long engineHandle, boolean isDown); 36 native_setDefaultStreamValues(int sampleRate, int framesPerBurst)37 private static native void native_setDefaultStreamValues(int sampleRate, int framesPerBurst); 38 39 // Used to load the 'native-lib' library on application startup. 40 static { 41 System.loadLibrary("megadrone"); 42 } 43 44 @Override onCreate(Bundle savedInstanceState)45 protected void onCreate(Bundle savedInstanceState) { 46 super.onCreate(savedInstanceState); 47 setContentView(R.layout.activity_main); 48 setDefaultStreamValues(this); 49 } 50 51 @Override onResume()52 protected void onResume(){ 53 mEngineHandle = startEngine(getExclusiveCores()); 54 super.onResume(); 55 } 56 57 @Override onPause()58 protected void onPause(){ 59 stopEngine(mEngineHandle); 60 super.onPause(); 61 } 62 63 @Override onTouchEvent(MotionEvent event)64 public boolean onTouchEvent(MotionEvent event) { 65 66 if (event.getAction() == MotionEvent.ACTION_DOWN){ 67 tap(mEngineHandle, true); 68 } else if (event.getAction() == MotionEvent.ACTION_UP){ 69 tap(mEngineHandle, false); 70 } 71 return super.onTouchEvent(event); 72 } 73 74 // Obtain CPU cores which are reserved for the foreground app. The audio thread can be 75 // bound to these cores to avoids the risk of it being migrated to slower or more contended 76 // core(s). getExclusiveCores()77 private int[] getExclusiveCores(){ 78 int[] exclusiveCores = {}; 79 80 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { 81 Log.w(TAG, "getExclusiveCores() not supported. Only available on API " + 82 Build.VERSION_CODES.N + "+"); 83 } else { 84 try { 85 exclusiveCores = android.os.Process.getExclusiveCores(); 86 } catch (RuntimeException e){ 87 Log.w(TAG, "getExclusiveCores() is not supported on this device."); 88 } 89 } 90 return exclusiveCores; 91 } 92 setDefaultStreamValues(Context context)93 static void setDefaultStreamValues(Context context) { 94 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1){ 95 AudioManager myAudioMgr = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 96 String sampleRateStr = myAudioMgr.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE); 97 int defaultSampleRate = Integer.parseInt(sampleRateStr); 98 String framesPerBurstStr = myAudioMgr.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER); 99 int defaultFramesPerBurst = Integer.parseInt(framesPerBurstStr); 100 101 native_setDefaultStreamValues(defaultSampleRate, defaultFramesPerBurst); 102 } 103 } 104 } 105 106 107