1e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall/* 2e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall * Copyright (C) 2015 The Android Open Source Project 3e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall * 4e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall * Licensed under the Apache License, Version 2.0 (the "License"); 5e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall * you may not use this file except in compliance with the License. 6e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall * You may obtain a copy of the License at 7e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall * 8e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall * http://www.apache.org/licenses/LICENSE-2.0 9e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall * 10e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall * Unless required by applicable law or agreed to in writing, software 11e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall * distributed under the License is distributed on an "AS IS" BASIS, 12e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall * See the License for the specific language governing permissions and 14e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall * limitations under the License. 15e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall */ 16e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall 17e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lallpackage com.android.camera.one.v2.core; 18e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall 19e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lallimport android.hardware.camera2.CameraAccessException; 20e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall 21e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lallimport com.android.camera.async.ConcurrentState; 22e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lallimport com.android.camera.async.Observable; 23e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lallimport com.android.camera.async.SafeCloseable; 24e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lallimport com.android.camera.one.v2.camera2proxy.CameraCaptureSessionClosedException; 25e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall 26e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lallimport java.util.List; 27e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lallimport java.util.concurrent.Executor; 28e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lallimport java.util.concurrent.atomic.AtomicBoolean; 29ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lallimport java.util.concurrent.atomic.AtomicInteger; 30e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall 31e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lallimport javax.annotation.Nonnull; 32e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lallimport javax.annotation.Nullable; 33e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lallimport javax.annotation.ParametersAreNonnullByDefault; 34e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall 35e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall/** 36e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall * Decorates a {@link FrameServer} to enable listening for changes to 37e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall * availability (whether or not an exclusive session can likely be acquired 38e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall * immediately). 39e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall */ 40e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall@ParametersAreNonnullByDefault 41e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lallfinal class ObservableFrameServer implements FrameServer, Observable<Boolean> { 42ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall /** 43ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall * The total number of clients which either have an exclusive Session or are 44ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall * waiting to acquire one. When this is positive, the frame server is "not 45ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall * available". 46ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall */ 47ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall private final AtomicInteger mClientCount; 48e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall private final ConcurrentState<Boolean> mAvailability; 49e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall private final FrameServer mDelegate; 50e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall 51e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall private class SessionImpl implements Session { 52e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall private final AtomicBoolean mClosed; 53e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall private final Session mDelegate; 54e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall 55e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall private SessionImpl(Session delegate) { 56e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall mClosed = new AtomicBoolean(false); 57e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall mDelegate = delegate; 58e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall } 59e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall 60e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall @Override 61e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall public void submitRequest(List<Request> burstRequests, RequestType type) 62e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall throws CameraAccessException, InterruptedException, 63e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall CameraCaptureSessionClosedException, ResourceAcquisitionFailedException { 64e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall mDelegate.submitRequest(burstRequests, type); 65e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall } 66e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall 67e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall @Override 68e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall public void close() { 69e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall if (!mClosed.getAndSet(true)) { 70ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall int clients = mClientCount.decrementAndGet(); 71ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall mAvailability.update(clients == 0); 72e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall mDelegate.close(); 73e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall } 74e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall } 75e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall } 76e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall 77e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall public ObservableFrameServer(FrameServer delegate) { 78e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall mDelegate = delegate; 79ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall mClientCount = new AtomicInteger(0); 80e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall mAvailability = new ConcurrentState<>(true); 81e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall } 82e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall 83e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall @Nonnull 84e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall @Override 85e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall public Session createExclusiveSession() throws InterruptedException { 86ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall int clients = mClientCount.incrementAndGet(); 87ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall mAvailability.update(clients == 0); 88ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall try { 89ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall // Ownership of the incremented value in mClientCount is passed to 90ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall // the session, which is responsible for decrementing it later. 91ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall Session session = mDelegate.createExclusiveSession(); 92ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall return new SessionImpl(session); 93ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall } catch (InterruptedException e) { 94ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall // If no session was acquired, we still "own" the increment of 95ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall // mClientCount and must decrement it here. 96ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall clients = mClientCount.decrementAndGet(); 97ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall mAvailability.update(clients == 0); 98ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall throw e; 99ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall } 100e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall } 101e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall 102e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall @Nullable 103e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall @Override 104e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall public Session tryCreateExclusiveSession() { 105e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall Session session = mDelegate.tryCreateExclusiveSession(); 106e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall if (session == null) { 107e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall return null; 108e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall } else { 109ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall int clients = mClientCount.incrementAndGet(); 110ccb0c17a104801a994c901d1c89c9d99005782edPuneet Lall mAvailability.update(clients == 0); 111e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall return new SessionImpl(session); 112e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall } 113e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall } 114e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall 115e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall @Nonnull 116e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall @Override 117e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall public SafeCloseable addCallback(Runnable callback, Executor executor) { 118e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall return mAvailability.addCallback(callback, executor); 119e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall } 120e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall 121e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall @Nonnull 122e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall @Override 123e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall public Boolean get() { 124e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall return mAvailability.get(); 125e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall } 126e4e15811211d6470a6182f4a1d080b962caa9ae4Puneet Lall} 127