1/*
2 * Copyright (C) 2015 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
17package com.android.camera.device;
18
19import com.android.camera.async.Lifetime;
20import com.google.common.util.concurrent.ListenableFuture;
21
22import javax.annotation.Nullable;
23import javax.annotation.concurrent.GuardedBy;
24
25/**
26 * This class manages the lifecycle of a single device and API version.
27 * A single instance deals with multiple requests for the same device
28 * by canceling previous, uncompleted future requests, and tolerates
29 * multiple calls to open() and close(). Once the device reaches the
30 * shutdown phase (Defined as a close event with no pending open
31 * requests) The object is no longer useful and a new instance should
32 * be created.
33 */
34public class CameraDeviceLifecycle<TDevice> implements
35      SingleDeviceLifecycle<TDevice, CameraDeviceKey> {
36
37    private final Object mLock;
38    private final CameraDeviceKey mDeviceKey;
39
40    @GuardedBy("mLock")
41    private final SingleDeviceStateMachine<TDevice, CameraDeviceKey> mDeviceState;
42
43    @Nullable
44    @GuardedBy("mLock")
45    private SingleDeviceRequest<TDevice> mDeviceRequest;
46
47    // TODO: Consider passing in parent lifetime to ensure this is
48    // ALWAYS shut down.
49    public CameraDeviceLifecycle(CameraDeviceKey cameraDeviceKey,
50          SingleDeviceStateMachine<TDevice, CameraDeviceKey> deviceState) {
51        mDeviceKey = cameraDeviceKey;
52        mDeviceState = deviceState;
53        mLock = new Object();
54    }
55
56    @Override
57    public CameraDeviceKey getId() {
58        return mDeviceKey;
59    }
60
61    @Override
62    public ListenableFuture<TDevice> createRequest(Lifetime lifetime) {
63        synchronized (mLock) {
64            mDeviceRequest = new SingleDeviceRequest<>(lifetime);
65            lifetime.add(mDeviceRequest);
66            mDeviceState.setRequest(mDeviceRequest);
67
68            return mDeviceRequest.getFuture();
69        }
70    }
71
72    /**
73     * Request that the device represented by this lifecycle should
74     * attempt to reach an open state.
75     */
76    @Override
77    public void open() {
78        synchronized (mLock) {
79            mDeviceState.requestOpen();
80        }
81    }
82
83    /**
84     * Request that the device represented by this lifecycle should
85     * attempt to reach a closed state.
86     */
87    @Override
88    public void close() {
89        synchronized (mLock) {
90            if (mDeviceRequest != null) {
91                mDeviceRequest.close();
92                mDeviceRequest = null;
93            }
94            mDeviceState.requestClose();
95        }
96    }
97}
98