1 /*
2  * Copyright 2013 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 androidx.media.filterfw.samples.simplecamera;
18 
19 import android.os.ConditionVariable;
20 import android.os.Handler;
21 import android.os.Looper;
22 import android.util.Log;
23 
24 import java.util.concurrent.TimeoutException;
25 
26 /**
27  * Camera test thread wrapper for handling camera callbacks
28  */
29 public class CameraTestThread implements AutoCloseable {
30     private static final String TAG = "CameraTestThread";
31     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
32     // Timeout for initializing looper and opening camera in Milliseconds.
33     private static final long WAIT_FOR_COMMAND_TO_COMPLETE = 5000;
34     private Looper mLooper = null;
35     private Handler mHandler = null;
36 
37     /**
38      * Create and start a looper thread, return the Handler
39      */
start()40     public synchronized Handler start() throws Exception {
41         final ConditionVariable startDone = new ConditionVariable();
42         if (mLooper != null || mHandler !=null) {
43             Log.w(TAG, "Looper thread already started");
44             return mHandler;
45         }
46 
47         new Thread() {
48             @Override
49             public void run() {
50                 if (VERBOSE) Log.v(TAG, "start loopRun");
51                 Looper.prepare();
52                 // Save the looper so that we can terminate this thread
53                 // after we are done with it.
54                 mLooper = Looper.myLooper();
55                 mHandler = new Handler();
56                 startDone.open();
57                 Looper.loop();
58                 if (VERBOSE) Log.v(TAG, "createLooperThread: finished");
59             }
60         }.start();
61 
62         if (VERBOSE) Log.v(TAG, "start waiting for looper");
63         if (!startDone.block(WAIT_FOR_COMMAND_TO_COMPLETE)) {
64             throw new TimeoutException("createLooperThread: start timeout");
65         }
66         return mHandler;
67     }
68 
69     /**
70      * Terminate the looper thread
71      */
close()72     public synchronized void close() throws Exception {
73         if (mLooper == null || mHandler == null) {
74             Log.w(TAG, "Looper thread doesn't start yet");
75             return;
76         }
77 
78         if (VERBOSE) Log.v(TAG, "Terminate looper thread");
79         mLooper.quit();
80         mLooper.getThread().join();
81         mLooper = null;
82         mHandler = null;
83     }
84 
85     @Override
finalize()86     protected void finalize() throws Throwable {
87         try {
88             close();
89         } finally {
90             super.finalize();
91         }
92     }
93 }
94