177b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin/* 277b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * Copyright 2014 The Android Open Source Project 377b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * 477b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * Licensed under the Apache License, Version 2.0 (the "License"); 577b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * you may not use this file except in compliance with the License. 677b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * You may obtain a copy of the License at 777b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * 877b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * http://www.apache.org/licenses/LICENSE-2.0 977b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * 1077b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * Unless required by applicable law or agreed to in writing, software 1177b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * distributed under the License is distributed on an "AS IS" BASIS, 1277b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1377b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * See the License for the specific language governing permissions and 1477b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * limitations under the License. 1577b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin */ 1677b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkinpackage com.android.ex.camera2.blocking; 1777b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 1877b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkinimport android.hardware.camera2.CameraCaptureSession; 1977b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkinimport android.os.ConditionVariable; 2039c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yehimport android.os.SystemClock; 2177b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkinimport android.util.Log; 22ebb6c5111f287a8cf55f1dcac7d7c5b76d9260ffEino-Ville Talvalaimport android.view.Surface; 2377b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 2477b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkinimport com.android.ex.camera2.exceptions.TimeoutRuntimeException; 2577b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkinimport com.android.ex.camera2.utils.StateChangeListener; 2677b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkinimport com.android.ex.camera2.utils.StateWaiter; 2777b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 2839c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yehimport java.util.List; 2977b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkinimport java.util.ArrayList; 3039c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yehimport java.util.HashMap; 3177b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkinimport java.util.concurrent.Future; 3277b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkinimport java.util.concurrent.TimeUnit; 3377b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkinimport java.util.concurrent.TimeoutException; 3477b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 3577b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 3677b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin/** 3777b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * A camera session listener that implements blocking operations on session state changes. 3877b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * 3977b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * <p>Provides a waiter that can be used to block until the next unobserved state of the 4077b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * requested type arrives.</p> 4177b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * 42bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala * <p>Pass-through all StateCallback changes to the proxy.</p> 4377b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * 4477b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * @see #getStateWaiter 4577b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin */ 46bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvalapublic class BlockingSessionCallback extends CameraCaptureSession.StateCallback { 4777b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin /** 4877b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * Session is configured, ready for captures 4977b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin */ 5077b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin public static final int SESSION_CONFIGURED = 0; 5177b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 5277b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin /** 5377b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * Session has failed to configure, can't do any captures 5477b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin */ 5577b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin public static final int SESSION_CONFIGURE_FAILED = 1; 5677b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 5777b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin /** 5877b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * Session is ready 5977b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin */ 6077b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin public static final int SESSION_READY = 2; 6177b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 6277b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin /** 6377b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * Session is active (transitory) 6477b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin */ 6577b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin public static final int SESSION_ACTIVE = 3; 6677b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 6777b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin /** 6877b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * Session is closed 6977b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin */ 7077b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin public static final int SESSION_CLOSED = 4; 7177b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 72046ba28a082f30d56a1ac63eaa13b5cf95093db6Jiawen Chen private static final int NUM_STATES = 5; 7377b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 7477b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin /* 7577b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * Private fields 7677b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin */ 77bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala private static final String TAG = "BlockingSessionCallback"; 7877b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE); 7977b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 80bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala private final CameraCaptureSession.StateCallback mProxy; 8177b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin private final SessionFuture mSessionFuture = new SessionFuture(); 8277b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 839b5facd03adbb55f6a1faa49788308f763a54ff0Ruben Brunk private final StateWaiter mStateWaiter = new StateWaiter(sStateNames); 8477b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin private final StateChangeListener mStateChangeListener = mStateWaiter.getListener(); 8539c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh private final HashMap<CameraCaptureSession, List<Surface> > mPreparedSurfaces = new HashMap<>(); 8677b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 879b5facd03adbb55f6a1faa49788308f763a54ff0Ruben Brunk private static final String[] sStateNames = { 8877b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin "SESSION_CONFIGURED", 8977b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin "SESSION_CONFIGURE_FAILED", 9077b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin "SESSION_READY", 9177b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin "SESSION_ACTIVE", 9277b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin "SESSION_CLOSED" 9377b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin }; 9477b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 9577b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin /** 9677b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * Create a blocking session listener without forwarding the session listener invocations 9777b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * to another session listener. 9877b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin */ 99bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala public BlockingSessionCallback() { 10077b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin mProxy = null; 10177b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin } 10277b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 10377b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin /** 10477b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * Create a blocking session listener; forward original listener invocations 10577b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * into {@code listener}. 10677b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * 10777b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * @param listener a non-{@code null} listener to forward invocations into 10877b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * 10977b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * @throws NullPointerException if {@code listener} was {@code null} 11077b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin */ 111bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala public BlockingSessionCallback(CameraCaptureSession.StateCallback listener) { 11277b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin if (listener == null) { 11377b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin throw new NullPointerException("listener must not be null"); 11477b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin } 11577b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin mProxy = listener; 11677b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin } 11777b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 11877b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin /** 11977b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * Acquire the state waiter; can be used to block until a set of state transitions have 12077b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * been reached. 12177b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * 12277b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * <p>Only one thread should wait at a time.</p> 12377b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin */ 12477b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin public StateWaiter getStateWaiter() { 12577b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin return mStateWaiter; 12677b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin } 12777b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 12877b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin /** 12977b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * Return session if already have it; otherwise wait until any of the session listener 13077b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * invocations fire and the session is available. 13177b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * 13277b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * <p>Does not consume any of the states from the state waiter.</p> 13377b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * 13477b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * @param timeoutMs how many milliseconds to wait for 13577b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * @return a non-{@code null} {@link CameraCaptureSession} instance 13677b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * 13777b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin * @throws TimeoutRuntimeException if waiting for more than {@long timeoutMs} 13877b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin */ 13977b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin public CameraCaptureSession waitAndGetSession(long timeoutMs) { 14077b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin try { 14177b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin return mSessionFuture.get(timeoutMs, TimeUnit.MILLISECONDS); 14277b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin } catch (TimeoutException e) { 14377b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin throw new TimeoutRuntimeException( 14477b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin String.format("Failed to get session after %s milliseconds", timeoutMs), e); 14577b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin } 14677b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin } 14777b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 14877b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin /* 149bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala * CameraCaptureSession.StateCallback implementation 15077b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin */ 15177b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 15277b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin @Override 15377b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin public void onActive(CameraCaptureSession session) { 15477b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin mSessionFuture.setSession(session); 15577b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin if (mProxy != null) mProxy.onActive(session); 15677b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin mStateChangeListener.onStateChanged(SESSION_ACTIVE); 15777b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin } 15877b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 15977b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin @Override 16077b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin public void onClosed(CameraCaptureSession session) { 16177b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin mSessionFuture.setSession(session); 16277b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin if (mProxy != null) mProxy.onClosed(session); 16377b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin mStateChangeListener.onStateChanged(SESSION_CLOSED); 16439c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh synchronized (mPreparedSurfaces) { 16539c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh mPreparedSurfaces.remove(session); 16639c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh } 16777b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin } 16877b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 16977b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin @Override 17077b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin public void onConfigured(CameraCaptureSession session) { 17177b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin mSessionFuture.setSession(session); 172046ba28a082f30d56a1ac63eaa13b5cf95093db6Jiawen Chen if (mProxy != null) { 173046ba28a082f30d56a1ac63eaa13b5cf95093db6Jiawen Chen mProxy.onConfigured(session); 174046ba28a082f30d56a1ac63eaa13b5cf95093db6Jiawen Chen } 17577b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin mStateChangeListener.onStateChanged(SESSION_CONFIGURED); 17677b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin } 17777b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 17877b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin @Override 17977b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin public void onConfigureFailed(CameraCaptureSession session) { 18077b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin mSessionFuture.setSession(session); 181046ba28a082f30d56a1ac63eaa13b5cf95093db6Jiawen Chen if (mProxy != null) { 182046ba28a082f30d56a1ac63eaa13b5cf95093db6Jiawen Chen mProxy.onConfigureFailed(session); 183046ba28a082f30d56a1ac63eaa13b5cf95093db6Jiawen Chen } 18477b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin mStateChangeListener.onStateChanged(SESSION_CONFIGURE_FAILED); 18577b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin } 18677b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 18777b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin @Override 18877b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin public void onReady(CameraCaptureSession session) { 18977b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin mSessionFuture.setSession(session); 190046ba28a082f30d56a1ac63eaa13b5cf95093db6Jiawen Chen if (mProxy != null) { 191046ba28a082f30d56a1ac63eaa13b5cf95093db6Jiawen Chen mProxy.onReady(session); 192046ba28a082f30d56a1ac63eaa13b5cf95093db6Jiawen Chen } 19377b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin mStateChangeListener.onStateChanged(SESSION_READY); 19477b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin } 19577b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 196ebb6c5111f287a8cf55f1dcac7d7c5b76d9260ffEino-Ville Talvala @Override 197ebb6c5111f287a8cf55f1dcac7d7c5b76d9260ffEino-Ville Talvala public void onSurfacePrepared(CameraCaptureSession session, Surface surface) { 198ebb6c5111f287a8cf55f1dcac7d7c5b76d9260ffEino-Ville Talvala mSessionFuture.setSession(session); 199ebb6c5111f287a8cf55f1dcac7d7c5b76d9260ffEino-Ville Talvala if (mProxy != null) { 200ebb6c5111f287a8cf55f1dcac7d7c5b76d9260ffEino-Ville Talvala mProxy.onSurfacePrepared(session, surface); 201ebb6c5111f287a8cf55f1dcac7d7c5b76d9260ffEino-Ville Talvala } 202ebb6c5111f287a8cf55f1dcac7d7c5b76d9260ffEino-Ville Talvala // Surface prepared doesn't cause a session state change, so don't trigger the 203ebb6c5111f287a8cf55f1dcac7d7c5b76d9260ffEino-Ville Talvala // state change listener 20439c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh synchronized (mPreparedSurfaces) { 20539c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh List<Surface> preparedSurfaces = mPreparedSurfaces.get(session); 20639c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh if (preparedSurfaces == null) { 20739c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh preparedSurfaces = new ArrayList<Surface>(); 20839c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh } 20939c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh preparedSurfaces.add(surface); 21039c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh mPreparedSurfaces.put(session, preparedSurfaces); 21139c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh mPreparedSurfaces.notifyAll(); 21239c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh } 21339c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh } 21439c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh 2153308f56e9af5f38f4b03e8b7700d3e8bf400fb38Shuzhen Wang @Override 2163308f56e9af5f38f4b03e8b7700d3e8bf400fb38Shuzhen Wang public void onCaptureQueueEmpty(CameraCaptureSession session) { 2173308f56e9af5f38f4b03e8b7700d3e8bf400fb38Shuzhen Wang mSessionFuture.setSession(session); 2183308f56e9af5f38f4b03e8b7700d3e8bf400fb38Shuzhen Wang if (mProxy != null) { 2193308f56e9af5f38f4b03e8b7700d3e8bf400fb38Shuzhen Wang mProxy.onCaptureQueueEmpty(session); 2203308f56e9af5f38f4b03e8b7700d3e8bf400fb38Shuzhen Wang } 2213308f56e9af5f38f4b03e8b7700d3e8bf400fb38Shuzhen Wang } 2223308f56e9af5f38f4b03e8b7700d3e8bf400fb38Shuzhen Wang 22339c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh /** 22439c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh * Wait until the designated surface is prepared by the camera capture session. 22539c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh * 22639c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh * @param session the input {@link CameraCaptureSession} to wait for 22739c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh * @param surface the input {@link Surface} to wait for 22839c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh * @param timeoutMs how many milliseconds to wait for 22939c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh * 23039c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh * @throws TimeoutRuntimeException if waiting for more than {@long timeoutMs} 23139c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh */ 23239c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh public void waitForSurfacePrepared( 23339c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh CameraCaptureSession session, Surface surface, long timeoutMs) { 23439c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh synchronized (mPreparedSurfaces) { 23539c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh List<Surface> preparedSurfaces = mPreparedSurfaces.get(session); 23639c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh if (preparedSurfaces != null && preparedSurfaces.contains(surface)) { 23739c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh return; 23839c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh } 23939c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh try { 24039c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh long waitTimeRemaining = timeoutMs; 24139c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh while (waitTimeRemaining > 0) { 24239c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh long waitStartTime = SystemClock.elapsedRealtime(); 24339c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh mPreparedSurfaces.wait(timeoutMs); 24439c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh long waitTime = SystemClock.elapsedRealtime() - waitStartTime; 24539c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh waitTimeRemaining -= waitTime; 24639c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh preparedSurfaces = mPreparedSurfaces.get(session); 24739c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh if (waitTimeRemaining >= 0 && preparedSurfaces != null && 24839c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh preparedSurfaces.contains(surface)) { 24939c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh return; 25039c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh } 25139c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh } 25239c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh throw new TimeoutRuntimeException( 25339c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh "Unable to get Surface prepared in " + timeoutMs + "ms"); 25439c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh } catch (InterruptedException ie) { 25539c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh throw new AssertionError(); 25639c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh } 25739c31d49ce38158b7708581df0813b03e32d6eeaYin-Chia Yeh } 258ebb6c5111f287a8cf55f1dcac7d7c5b76d9260ffEino-Ville Talvala } 259ebb6c5111f287a8cf55f1dcac7d7c5b76d9260ffEino-Ville Talvala 26077b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin private static class SessionFuture implements Future<CameraCaptureSession> { 26177b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin private volatile CameraCaptureSession mSession; 26277b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin ConditionVariable mCondVar = new ConditionVariable(/*opened*/false); 26377b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 26477b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin public void setSession(CameraCaptureSession session) { 26577b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin mSession = session; 26677b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin mCondVar.open(); 26777b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin } 26877b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 26977b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin @Override 27077b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin public boolean cancel(boolean mayInterruptIfRunning) { 27177b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin return false; // don't allow canceling this task 27277b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin } 27377b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 27477b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin @Override 27577b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin public boolean isCancelled() { 27677b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin return false; // can never cancel this task 27777b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin } 27877b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 27977b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin @Override 28077b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin public boolean isDone() { 28177b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin return mSession != null; 28277b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin } 28377b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 28477b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin @Override 28577b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin public CameraCaptureSession get() { 28677b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin mCondVar.block(); 28777b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin return mSession; 28877b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin } 28977b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 29077b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin @Override 29177b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin public CameraCaptureSession get(long timeout, TimeUnit unit) throws TimeoutException { 29277b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin long timeoutMs = unit.convert(timeout, TimeUnit.MILLISECONDS); 29377b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin if (!mCondVar.block(timeoutMs)) { 29477b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin throw new TimeoutException( 29577b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin "Failed to receive session after " + timeout + " " + unit); 29677b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin } 29777b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 29877b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin if (mSession == null) { 29977b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin throw new AssertionError(); 30077b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin } 30177b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin return mSession; 30277b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin } 30377b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin 30477b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin } 30577b7bbe039393c2d8c1107c07c65028886eef252Igor Murashkin} 306