1227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/* 2227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Copyright 2013 The Android Open Source Project 3227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 4227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Licensed under the Apache License, Version 2.0 (the "License"); 5227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * you may not use this file except in compliance with the License. 6227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * You may obtain a copy of the License at 7227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 8227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * http://www.apache.org/licenses/LICENSE-2.0 9227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 10227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Unless required by applicable law or agreed to in writing, software 11227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * distributed under the License is distributed on an "AS IS" BASIS, 12227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * See the License for the specific language governing permissions and 14227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * limitations under the License. 15227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 16227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 17227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspackage androidx.media.filterfw.samples.simplecamera; 18227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 19227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.os.ConditionVariable; 20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.os.Handler; 21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.os.Looper; 22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.util.Log; 23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.concurrent.TimeoutException; 25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/** 27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Camera test thread wrapper for handling camera callbacks 28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspublic class CameraTestThread implements AutoCloseable { 30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static final String TAG = "CameraTestThread"; 31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE); 32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Timeout for initializing looper and opening camera in Milliseconds. 33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static final long WAIT_FOR_COMMAND_TO_COMPLETE = 5000; 34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private Looper mLooper = null; 35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private Handler mHandler = null; 36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Create and start a looper thread, return the Handler 39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public synchronized Handler start() throws Exception { 41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks final ConditionVariable startDone = new ConditionVariable(); 42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mLooper != null || mHandler !=null) { 43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Log.w(TAG, "Looper thread already started"); 44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mHandler; 45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks new Thread() { 48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void run() { 50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (VERBOSE) Log.v(TAG, "start loopRun"); 51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Looper.prepare(); 52227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Save the looper so that we can terminate this thread 53227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // after we are done with it. 54227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mLooper = Looper.myLooper(); 55227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mHandler = new Handler(); 56227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks startDone.open(); 57227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Looper.loop(); 58227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (VERBOSE) Log.v(TAG, "createLooperThread: finished"); 59227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 60227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks }.start(); 61227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 62227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (VERBOSE) Log.v(TAG, "start waiting for looper"); 63227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (!startDone.block(WAIT_FOR_COMMAND_TO_COMPLETE)) { 64227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new TimeoutException("createLooperThread: start timeout"); 65227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 66227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mHandler; 67227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 68227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 69227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 70227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Terminate the looper thread 71227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 72227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public synchronized void close() throws Exception { 73227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mLooper == null || mHandler == null) { 74227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Log.w(TAG, "Looper thread doesn't start yet"); 75227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return; 76227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 77227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 78227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (VERBOSE) Log.v(TAG, "Terminate looper thread"); 79227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mLooper.quit(); 80227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mLooper.getThread().join(); 81227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mLooper = null; 82227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mHandler = null; 83227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 84227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 85227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 86227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks protected void finalize() throws Throwable { 87227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks try { 88227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks close(); 89227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } finally { 90227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks super.finalize(); 91227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 92227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 93227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks} 94