1 /* 2 * Copyright (C) 2020 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.effectstest; 18 19 import android.os.Handler; 20 import android.os.Looper; 21 import android.util.Log; 22 23 import com.android.internal.annotations.GuardedBy; 24 25 class VisualizerInstanceMT implements VisualizerInstance { 26 27 private static final String TAG = "VisualizerInstanceMT"; 28 29 private final Object mLock = new Object(); 30 private final int mThreadCount; 31 @GuardedBy("mLock") 32 private Handler mVisualizerHandler; 33 @GuardedBy("mLock") 34 private VisualizerInstanceSync mVisualizer; 35 VisualizerInstanceMT(int session, Handler uiHandler, int extraThreadCount)36 VisualizerInstanceMT(int session, Handler uiHandler, int extraThreadCount) { 37 Log.d(TAG, "Multi-threaded constructor"); 38 mThreadCount = 1 + extraThreadCount; 39 Thread t = new Thread() { 40 @Override public void run() { 41 Looper.prepare(); 42 VisualizerInstanceSync v = new VisualizerInstanceSync(session, uiHandler); 43 synchronized (mLock) { 44 mVisualizerHandler = new Handler(); 45 mVisualizer = v; 46 } 47 Looper.loop(); 48 } 49 }; 50 t.start(); 51 } 52 getVisualizer()53 private VisualizerInstance getVisualizer() { 54 synchronized (mLock) { 55 return mVisualizer != null ? new VisualizerInstanceSync(mVisualizer) : null; 56 } 57 } 58 59 private interface VisualizerOperation { run(VisualizerInstance v)60 void run(VisualizerInstance v); 61 } 62 runOperationMt(VisualizerOperation op)63 private void runOperationMt(VisualizerOperation op) { 64 final VisualizerInstance v = getVisualizer(); 65 if (v == null) return; 66 for (int i = 0; i < mThreadCount; ++i) { 67 Thread t = new Thread() { 68 @Override 69 public void run() { 70 op.run(v); 71 } 72 }; 73 t.start(); 74 } 75 } 76 77 @Override enableDataCaptureListener(boolean enable)78 public void enableDataCaptureListener(boolean enable) { 79 runOperationMt(v -> v.enableDataCaptureListener(enable)); 80 } 81 82 @Override getEnabled()83 public boolean getEnabled() { 84 final VisualizerInstance v = getVisualizer(); 85 return v != null ? v.getEnabled() : false; 86 } 87 88 @Override release()89 public void release() { 90 runOperationMt(v -> v.release()); 91 synchronized (mLock) { 92 if (mVisualizerHandler == null) return; 93 mVisualizerHandler.post(() -> { 94 synchronized (mLock) { 95 mVisualizerHandler = null; 96 mVisualizer = null; 97 Looper.myLooper().quitSafely(); 98 } 99 Log.d(TAG, "Exiting looper"); 100 }); 101 } 102 } 103 104 @Override setEnabled(boolean enabled)105 public void setEnabled(boolean enabled) { 106 runOperationMt(v -> v.setEnabled(enabled)); 107 } 108 109 @Override startStopCapture(boolean start)110 public void startStopCapture(boolean start) { 111 runOperationMt(v -> v.startStopCapture(start)); 112 } 113 } 114