17c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala/*
27c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala * Copyright (C) 2014 The Android Open Source Project
37c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala *
47c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala * Licensed under the Apache License, Version 2.0 (the "License");
57c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala * you may not use this file except in compliance with the License.
67c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala * You may obtain a copy of the License at
77c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala *
87c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala *      http://www.apache.org/licenses/LICENSE-2.0
97c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala *
107c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala * Unless required by applicable law or agreed to in writing, software
117c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala * distributed under the License is distributed on an "AS IS" BASIS,
127c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala * See the License for the specific language governing permissions and
147c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala * limitations under the License.
157c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala */
167c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
177c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalapackage com.android.testingcamera2;
187c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
197c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport java.util.ArrayList;
207c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport java.util.HashSet;
21fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvalaimport java.util.LinkedList;
227c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport java.util.List;
237c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport java.util.Locale;
247c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport java.util.Set;
257c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
267c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport android.content.Context;
277c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport android.util.AttributeSet;
287c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport android.view.LayoutInflater;
297c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport android.view.Surface;
307c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport android.view.View;
317c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport android.widget.AdapterView;
327c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport android.widget.AdapterView.OnItemSelectedListener;
337c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport android.widget.ArrayAdapter;
347c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport android.widget.Button;
357c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport android.widget.CompoundButton;
367c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport android.widget.Spinner;
377c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport android.widget.TextView;
387c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport android.widget.ToggleButton;
397c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport android.hardware.camera2.CameraAccessException;
4061791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkinimport android.hardware.camera2.CameraCaptureSession;
41b6dca4d979f37748eeb53184a3c3184dbe04d123Eino-Ville Talvalaimport android.hardware.camera2.CameraCaptureSession.CaptureCallback;
427c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport android.hardware.camera2.CameraCharacteristics;
437c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport android.hardware.camera2.CameraDevice;
447c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport android.hardware.camera2.CameraManager;
457c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport android.hardware.camera2.CaptureRequest;
46fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvalaimport android.hardware.camera2.CaptureResult;
47fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvalaimport android.hardware.camera2.TotalCaptureResult;
487c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
497c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport org.xmlpull.v1.XmlPullParser;
507c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport org.xmlpull.v1.XmlPullParserException;
517c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
527c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport com.android.testingcamera2.PaneTracker.PaneEvent;
537c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
547c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalaimport java.io.IOException;
557c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
567c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala/**
577c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala *
587c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala * Basic control pane block for the control list
597c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala *
607c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala */
617c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvalapublic class CameraControlPane extends ControlPane {
627c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
637c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    // XML attributes
647c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
657c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    /** Name of pane tag */
667c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private static final String PANE_NAME = "camera_pane";
677c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
687c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    /** Attribute: ID for pane (integer) */
697c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private static final String PANE_ID = "id";
707c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    /** Attribute: ID for camera to select (String) */
717c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private static final String CAMERA_ID = "camera_id";
727c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
737c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    // End XML attributes
747c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
75fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala    private static final int MAX_CACHED_RESULTS = 100;
76fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala
777c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private static int mCameraPaneIdCounter = 0;
787c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
797c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    /**
807c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     * These correspond to the callbacks from
813a7882e8950b2de5f7693807794ad10c11b499daEino-Ville Talvala     * android.hardware.camera2.CameraDevice.StateCallback, plus UNAVAILABLE for
827c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     * when there's not a valid camera selected.
837c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     */
847c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private enum CameraState {
857c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        UNAVAILABLE,
867c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        CLOSED,
877c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        OPENED,
887c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        DISCONNECTED,
897c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        ERROR
907c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    }
917c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
9261791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin    /**
933a7882e8950b2de5f7693807794ad10c11b499daEino-Ville Talvala     * These correspond to the callbacks from {@link CameraCaptureSession.StateCallback}, plus
9461791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin     * {@code CONFIGURING} for before a session is returned and {@code NONE} for when there
9561791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin     * is no session created.
9661791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin     */
9761791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin    private enum SessionState {
9861791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        NONE,
9961791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        CONFIGURED,
10061791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        CONFIGURE_FAILED,
10161791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        READY,
10261791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        ACTIVE,
10361791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        CLOSED
10461791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin    }
10561791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin
1067c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private enum CameraCall {
1077c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        NONE,
1087c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        CONFIGURE
1097c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    }
1107c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
1117c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private final int mPaneId;
1127c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
1137c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private CameraOps2 mCameraOps;
1147c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private InfoDisplayer mInfoDisplayer;
1157c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
1167c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private Spinner mCameraSpinner;
1177c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private ToggleButton mOpenButton;
1187c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private Button mInfoButton;
1197c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private TextView mStatusText;
1207c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private Button mConfigureButton;
1217c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private Button mStopButton;
1227c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private Button mFlushButton;
1237c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
1247c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    /**
1257c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     * All controls that should be enabled when there's a valid camera ID
1267c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     * selected
1277c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     */
12861791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin    private final Set<View> mBaseControls = new HashSet<View>();
1297c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    /**
1307c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     * All controls that should be enabled when camera is at least in the OPEN
1317c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     * state
1327c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     */
13361791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin    private final Set<View> mOpenControls = new HashSet<View>();
1347c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    /**
1357c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     * All controls that should be enabled when camera is at least in the IDLE
1367c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     * state
1377c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     */
13861791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin    private final Set<View> mConfiguredControls = new HashSet<View>();
1397c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
1407c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private String[] mCameraIds;
1417c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private String mCurrentCameraId;
1427c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
1437c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private CameraState mCameraState;
1447c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private CameraDevice mCurrentCamera;
14561791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin    private CameraCaptureSession mCurrentCaptureSession;
14661791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin    private SessionState mSessionState = SessionState.NONE;
1477c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private CameraCall mActiveCameraCall;
148fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala    private LinkedList<TotalCaptureResult> mRecentResults = new LinkedList<>();
1497c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
1507c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private List<Surface> mConfiguredSurfaces;
1517c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private List<TargetControlPane> mConfiguredTargetPanes;
1527c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
1537c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    /**
1547c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     * Constructor for tooling only
1557c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     */
1567c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    public CameraControlPane(Context context, AttributeSet attrs) {
1577c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        super(context, attrs, null, null);
1587c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
1597c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mPaneId = 0;
1607c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        setUpUI(context);
1617c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    }
1627c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
1637c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    public CameraControlPane(TestingCamera21 tc, AttributeSet attrs, StatusListener listener) {
1647c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
1657c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        super(tc, attrs, listener, tc.getPaneTracker());
1667c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
1677c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mPaneId = mCameraPaneIdCounter++;
1687c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        setUpUI(tc);
1697c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        initializeCameras(tc);
1707c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
1717c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        if (mCameraIds != null) {
1727c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            switchToCamera(mCameraIds[0]);
1737c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
1747c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    }
1757c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
1767c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    public CameraControlPane(TestingCamera21 tc, XmlPullParser configParser, StatusListener listener)
1777c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            throws XmlPullParserException, IOException {
1787c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        super(tc, null, listener, tc.getPaneTracker());
1797c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
1807c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        configParser.require(XmlPullParser.START_TAG, XmlPullParser.NO_NAMESPACE, PANE_NAME);
1817c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
1827c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        int paneId = getAttributeInt(configParser, PANE_ID, -1);
1837c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        if (paneId == -1) {
1847c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            mPaneId = mCameraPaneIdCounter++;
1857c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        } else {
1867c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            mPaneId = paneId;
1877c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            if (mPaneId >= mCameraPaneIdCounter) {
1887c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                mCameraPaneIdCounter = mPaneId + 1;
1897c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            }
1907c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
1917c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
1927c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        String cameraId = getAttributeString(configParser, CAMERA_ID, null);
1937c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
1947c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        configParser.next();
1957c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        configParser.require(XmlPullParser.END_TAG, XmlPullParser.NO_NAMESPACE, PANE_NAME);
1967c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
1977c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        setUpUI(tc);
1987c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        initializeCameras(tc);
1997c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
2007c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        boolean gotCamera = false;
2017c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        if (mCameraIds != null && cameraId != null) {
2027c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            for (int i = 0; i < mCameraIds.length; i++) {
2037c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                if (cameraId.equals(mCameraIds[i])) {
2047c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                    switchToCamera(mCameraIds[i]);
2057c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                    mCameraSpinner.setSelection(i);
2067c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                    gotCamera = true;
2077c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                }
2087c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            }
2097c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
2107c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
2117c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        if (!gotCamera && mCameraIds != null) {
2127c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            switchToCamera(mCameraIds[0]);
2137c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
2147c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    }
2157c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
2167c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    @Override
2177c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    public void remove() {
2187c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        closeCurrentCamera();
2197c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        super.remove();
2207c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    }
2217c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
2227c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    /**
2237c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     * Get list of target panes that are currently actively configured for this
2247c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     * camera
2257c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     */
2267c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    public List<TargetControlPane> getCurrentConfiguredTargets() {
2277c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        return mConfiguredTargetPanes;
2287c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    }
2297c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
2307c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    /**
2317c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     * Interface to be implemented by an application service for displaying a
2327c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     * camera's information.
2337c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     */
2347c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    public interface InfoDisplayer {
2357c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        public void showCameraInfo(String cameraId);
2367c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    }
2377c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
2387c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    public CameraCharacteristics getCharacteristics() {
2397c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        if (mCurrentCameraId != null) {
2407c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            return mCameraOps.getCameraInfo(mCurrentCameraId);
2417c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
2427c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        return null;
2437c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    }
2447c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
2457c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    public CaptureRequest.Builder getRequestBuilder(int template) {
246fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala        CaptureRequest.Builder request = null;
2477c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        if (mCurrentCamera != null) {
2487c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            try {
249fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala                request = mCurrentCamera.createCaptureRequest(template);
250fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala                // Workaround for b/15748139
251fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala                request.set(CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE,
252fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala                        CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE_ON);
2537c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            } catch (CameraAccessException e) {
2547c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                TLog.e("Unable to build request for camera %s with template %d.", e,
2557c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                        mCurrentCameraId, template);
2567c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            }
2577c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
258fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala        return request;
2597c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    }
2607c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
2617c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    /**
2627c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     * Send single capture to camera device.
2637c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     *
2647c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     * @param request
2657c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     * @return true if capture sent successfully
2667c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala     */
2677c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    public boolean capture(CaptureRequest request) {
26861791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        if (mCurrentCaptureSession != null) {
2697c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            try {
270fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala                mCurrentCaptureSession.capture(request, mResultListener, null);
2717c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                return true;
2727c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            } catch (CameraAccessException e) {
2737c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                TLog.e("Unable to capture for camera %s.", e, mCurrentCameraId);
2747c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            }
2757c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
2767c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        return false;
2777c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    }
2787c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
2797c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    public boolean repeat(CaptureRequest request) {
28061791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        if (mCurrentCaptureSession != null) {
2817c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            try {
282fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala                mCurrentCaptureSession.setRepeatingRequest(request, mResultListener, null);
2837c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                return true;
2847c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            } catch (CameraAccessException e) {
2857c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                TLog.e("Unable to set repeating request for camera %s.", e, mCurrentCameraId);
2867c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            }
2877c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
2887c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        return false;
2897c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    }
2907c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
291fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala    public TotalCaptureResult getResultAt(long timestamp) {
292fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala        for (TotalCaptureResult result : mRecentResults) {
293fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala            long resultTimestamp = result.get(CaptureResult.SENSOR_TIMESTAMP);
294fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala            if (resultTimestamp == timestamp) return result;
295fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala            if (resultTimestamp > timestamp) return null;
296fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala        }
297fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala        return null;
298fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala    }
299fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala
300b6dca4d979f37748eeb53184a3c3184dbe04d123Eino-Ville Talvala    private CaptureCallback mResultListener = new CaptureCallback() {
301fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala        public void onCaptureCompleted(
302fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala                CameraCaptureSession session,
303fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala                CaptureRequest request,
304fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala                TotalCaptureResult result) {
305fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala            mRecentResults.add(result);
306fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala            if (mRecentResults.size() > MAX_CACHED_RESULTS) {
307fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala                mRecentResults.remove();
308fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala            }
309fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala        }
310fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala    };
311fdfd60aee36376910bacac00426d1b0f22bcfa2bEino-Ville Talvala
3127c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private void setUpUI(Context context) {
3137c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        String paneName =
3147c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                String.format(Locale.US, "%s %c",
3157c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                        context.getResources().getString(R.string.camera_pane_title),
3167c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                        (char) ('A' + mPaneId));
3177c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        this.setName(paneName);
3187c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
3197c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        LayoutInflater inflater =
3207c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
3217c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
3227c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        inflater.inflate(R.layout.camera_pane, this);
3237c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
3247c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mCameraSpinner = (Spinner) findViewById(R.id.camera_pane_camera_spinner);
3257c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mCameraSpinner.setOnItemSelectedListener(mCameraSpinnerListener);
3267c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
3277c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mOpenButton = (ToggleButton) findViewById(R.id.camera_pane_open_button);
3287c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mOpenButton.setOnCheckedChangeListener(mOpenButtonListener);
3297c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mBaseControls.add(mOpenButton);
3307c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
3317c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mInfoButton = (Button) findViewById(R.id.camera_pane_info_button);
3327c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mInfoButton.setOnClickListener(mInfoButtonListener);
3337c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mBaseControls.add(mInfoButton);
3347c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
3357c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mStatusText = (TextView) findViewById(R.id.camera_pane_status_text);
3367c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
3377c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mConfigureButton = (Button) findViewById(R.id.camera_pane_configure_button);
3387c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mConfigureButton.setOnClickListener(mConfigureButtonListener);
3397c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mOpenControls.add(mConfigureButton);
3407c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
3417c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mStopButton = (Button) findViewById(R.id.camera_pane_stop_button);
3427c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mStopButton.setOnClickListener(mStopButtonListener);
3437c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mConfiguredControls.add(mStopButton);
3447c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mFlushButton = (Button) findViewById(R.id.camera_pane_flush_button);
3457c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mFlushButton.setOnClickListener(mFlushButtonListener);
3467c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mConfiguredControls.add(mFlushButton);
3477c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    }
3487c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
3497c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private void initializeCameras(TestingCamera21 tc) {
3507c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mCameraOps = tc.getCameraOps();
35161791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        mInfoDisplayer = tc;
3527c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
3537c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        updateCameraList();
3547c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    }
3557c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
3567c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private void updateCameraList() {
3577c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mCameraIds = null;
3587c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        try {
3593a7882e8950b2de5f7693807794ad10c11b499daEino-Ville Talvala            mCameraIds = mCameraOps.getCamerasAndListen(mCameraAvailabilityCallback);
3607c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            String[] cameraSpinnerItems = new String[mCameraIds.length];
3617c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            for (int i = 0; i < mCameraIds.length; i++) {
3627c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                cameraSpinnerItems[i] = String.format("Camera %s", mCameraIds[i]);
3637c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            }
3647c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            mCameraSpinner.setAdapter(new ArrayAdapter<String>(getContext(), R.layout.spinner_item,
3657c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                    cameraSpinnerItems));
3667c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
3677c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        } catch (CameraAccessException e) {
3687c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            TLog.e("Exception trying to get list of cameras: " + e);
3697c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
3707c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    }
3717c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
37261791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin    private final CompoundButton.OnCheckedChangeListener mOpenButtonListener =
3737c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            new CompoundButton.OnCheckedChangeListener() {
3747c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                @Override
3757c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
3767c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                    if (isChecked) {
3777c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                        // Open camera
3787c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                        mCurrentCamera = null;
3797c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                        boolean success = mCameraOps.openCamera(mCurrentCameraId, mCameraListener);
3807c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                        buttonView.setChecked(success);
3817c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                    } else {
3827c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                        // Close camera
3837c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                        closeCurrentCamera();
3847c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                    }
3857c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                }
3867c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            };
3877c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
38861791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin    private final OnClickListener mInfoButtonListener = new OnClickListener() {
3897c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        @Override
3907c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        public void onClick(View v) {
3917c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            mInfoDisplayer.showCameraInfo(mCurrentCameraId);
3927c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
3937c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    };
3947c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
39561791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin    private final OnClickListener mStopButtonListener = new OnClickListener() {
3967c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        @Override
3977c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        public void onClick(View v) {
39861791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin            if (mCurrentCaptureSession != null) {
3997c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                try {
40061791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                    mCurrentCaptureSession.stopRepeating();
4017c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                } catch (CameraAccessException e) {
4027c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                    TLog.e("Unable to stop repeating request for camera %s.", e, mCurrentCameraId);
4037c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                }
4047c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            }
4057c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
4067c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    };
4077c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
40861791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin    private final OnClickListener mFlushButtonListener = new OnClickListener() {
4097c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        @Override
4107c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        public void onClick(View v) {
41161791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin            if (mCurrentCaptureSession != null) {
4127c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                try {
41361791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                    mCurrentCaptureSession.abortCaptures();
4147c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                } catch (CameraAccessException e) {
4157c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                    TLog.e("Unable to flush camera %s.", e, mCurrentCameraId);
4167c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                }
4177c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            }
4187c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
4197c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    };
4207c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
42161791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin    private final OnClickListener mConfigureButtonListener = new OnClickListener() {
4227c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        @Override
4237c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        public void onClick(View v) {
4247c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            List<Surface> targetSurfaces = new ArrayList<Surface>();
4257c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            List<TargetControlPane> targetPanes = new ArrayList<TargetControlPane>();
4267c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            for (TargetControlPane targetPane : mPaneTracker.getPanes(TargetControlPane.class)) {
4277c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                Surface target = targetPane.getTargetSurfaceForCameraPane(getPaneName());
4287c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                if (target != null) {
4297c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                    targetSurfaces.add(target);
4307c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                    targetPanes.add(targetPane);
4317c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                }
4327c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            }
4337c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            try {
4347c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                TLog.i("Configuring camera %s with %d surfaces", mCurrentCamera.getId(),
4357c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                        targetSurfaces.size());
4367c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                mActiveCameraCall = CameraCall.CONFIGURE;
4377c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                if (targetSurfaces.size() > 0) {
43861791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                    mCurrentCamera.createCaptureSession(targetSurfaces, mSessionListener, /*handler*/null);
43961791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                } else if (mCurrentCaptureSession != null) {
44061791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                    mCurrentCaptureSession.close();
44161791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                    mCurrentCaptureSession = null;
4427c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                }
4437c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                mConfiguredSurfaces = targetSurfaces;
4447c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                mConfiguredTargetPanes = targetPanes;
4457c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            } catch (CameraAccessException e) {
4467c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                mActiveCameraCall = CameraCall.NONE;
4477c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                TLog.e("Unable to configure camera %s.", e, mCurrentCamera.getId());
4487c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            } catch (IllegalArgumentException e) {
4497c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                mActiveCameraCall = CameraCall.NONE;
4507c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                TLog.e("Unable to configure camera %s.", e, mCurrentCamera.getId());
4517c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            } catch (IllegalStateException e) {
4527c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                mActiveCameraCall = CameraCall.NONE;
4537c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                TLog.e("Unable to configure camera %s.", e, mCurrentCamera.getId());
4547c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            }
4557c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
4567c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    };
4577c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
4583a7882e8950b2de5f7693807794ad10c11b499daEino-Ville Talvala    private final CameraCaptureSession.StateCallback mSessionListener =
4593a7882e8950b2de5f7693807794ad10c11b499daEino-Ville Talvala            new CameraCaptureSession.StateCallback() {
46061791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin
46161791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        @Override
46261791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        public void onConfigured(CameraCaptureSession session) {
46361791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin            mCurrentCaptureSession = session;
4641820b2153fcd3069c89d97d990d3caeeddcdeda2Eino-Ville Talvala            TLog.i("Configuration completed for camera %s.", mCurrentCamera.getId());
46561791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin
46661791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin            setSessionState(SessionState.CONFIGURED);
46761791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        }
46861791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin
4697c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        @Override
47061791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        public void onConfigureFailed(CameraCaptureSession session) {
47161791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin            mActiveCameraCall = CameraCall.NONE;
47261791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin            TLog.e("Configuration failed for camera %s.", mCurrentCamera.getId());
47361791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin
47461791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin            setSessionState(SessionState.CONFIGURE_FAILED);
47561791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        }
47661791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin
47761791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        @Override
47861791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        public void onReady(CameraCaptureSession session) {
47961791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin            setSessionState(SessionState.READY);
48061791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        }
48161791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin
48261791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        /**
48361791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin         * This method is called when the session starts actively processing capture requests.
48461791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin         *
48561791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin         * <p>If capture requests are submitted prior to {@link #onConfigured} being called,
48661791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin         * then the session will start processing those requests immediately after the callback,
48761791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin         * and this method will be immediately called after {@link #onConfigured}.
48861791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin         *
48961791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin         * <p>If the session runs out of capture requests to process and calls {@link #onReady},
49061791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin         * then this callback will be invoked again once new requests are submitted for capture.</p>
49161791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin         */
49261791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        @Override
49361791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        public void onActive(CameraCaptureSession session) {
49461791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin            setSessionState(SessionState.ACTIVE);
49561791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        }
49661791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin
49761791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        /**
49861791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin         * This method is called when the session is closed.
49961791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin         *
50061791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin         * <p>A session is closed when a new session is created by the parent camera device,
50161791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin         * or when the parent camera device is closed (either by the user closing the device,
50261791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin         * or due to a camera device disconnection or fatal error).</p>
50361791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin         *
50461791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin         * <p>Once a session is closed, all methods on it will throw an IllegalStateException, and
50561791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin         * any repeating requests or bursts are stopped (as if {@link #stopRepeating()} was called).
50661791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin         * However, any in-progress capture requests submitted to the session will be completed
50761791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin         * as normal.</p>
50861791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin         */
50961791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        @Override
51061791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        public void onClosed(CameraCaptureSession session) {
5111820b2153fcd3069c89d97d990d3caeeddcdeda2Eino-Ville Talvala            // Ignore closes if the session has been replaced
5121820b2153fcd3069c89d97d990d3caeeddcdeda2Eino-Ville Talvala            if (mCurrentCaptureSession != null && session != mCurrentCaptureSession) {
5131820b2153fcd3069c89d97d990d3caeeddcdeda2Eino-Ville Talvala                return;
5141820b2153fcd3069c89d97d990d3caeeddcdeda2Eino-Ville Talvala            }
51561791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin            setSessionState(SessionState.CLOSED);
51661791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        }
51761791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin    };
51861791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin
5193a7882e8950b2de5f7693807794ad10c11b499daEino-Ville Talvala    private final CameraDevice.StateCallback mCameraListener = new CameraDevice.StateCallback() {
52061791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        @Override
5217c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        public void onClosed(CameraDevice camera) {
5227c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            // Don't change state on close, tracked by callers of close()
5237c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
5247c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
5257c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        @Override
5267c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        public void onDisconnected(CameraDevice camera) {
5277c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            setCameraState(CameraState.DISCONNECTED);
5287c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
5297c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
5307c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        @Override
5317c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        public void onError(CameraDevice camera, int error) {
5327c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            setCameraState(CameraState.ERROR);
5337c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
5347c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
5357c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        @Override
5367c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        public void onOpened(CameraDevice camera) {
5377c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            mCurrentCamera = camera;
5387c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            setCameraState(CameraState.OPENED);
5397c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
5407c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    };
5417c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
5427c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private void switchToCamera(String newCameraId) {
5437c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        closeCurrentCamera();
5447c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
5457c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mCurrentCameraId = newCameraId;
5467c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
5477c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        if (mCurrentCameraId == null) {
5487c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            setCameraState(CameraState.UNAVAILABLE);
5497c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        } else {
5507c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            setCameraState(CameraState.CLOSED);
5517c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
5527c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
5537c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        mPaneTracker.notifyOtherPanes(this, PaneTracker.PaneEvent.NEW_CAMERA_SELECTED);
5547c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    }
5557c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
5567c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private void closeCurrentCamera() {
5577c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        if (mCurrentCamera != null) {
5587c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            mCurrentCamera.close();
5597c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            mCurrentCamera = null;
5607c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            setCameraState(CameraState.CLOSED);
5617c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            mOpenButton.setChecked(false);
5627c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
5637c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    }
5647c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
56561791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin    private void setSessionState(SessionState newState) {
56661791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        mSessionState = newState;
56761791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        mStatusText.setText("S." + mSessionState.toString());
56861791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin
56961791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        switch (mSessionState) {
57061791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin            case CONFIGURE_FAILED:
57161791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                mActiveCameraCall = CameraCall.NONE;
57261791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                // fall-through
5737c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            case CLOSED:
5747c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                enableBaseControls(true);
5751820b2153fcd3069c89d97d990d3caeeddcdeda2Eino-Ville Talvala                enableOpenControls(true);
5767c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                enableConfiguredControls(false);
5777c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                mConfiguredTargetPanes = null;
5787c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                break;
57961791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin            case NONE:
5807c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                enableBaseControls(true);
5817c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                enableOpenControls(true);
5827c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                enableConfiguredControls(false);
5837c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                mConfiguredTargetPanes = null;
5847c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                break;
58561791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin            case CONFIGURED:
58661791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                if (mActiveCameraCall != CameraCall.CONFIGURE) {
58761791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                    throw new AssertionError();
5887c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                }
58961791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                mPaneTracker.notifyOtherPanes(this, PaneEvent.CAMERA_CONFIGURED);
59061791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                mActiveCameraCall = CameraCall.NONE;
59161791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                // fall-through
59261791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin            case READY:
5937c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            case ACTIVE:
5947c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                enableBaseControls(true);
5957c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                enableOpenControls(true);
5967c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                enableConfiguredControls(true);
5977c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                break;
59861791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin            default:
59961791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                throw new AssertionError("Unhandled case " + mSessionState);
60061791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        }
60161791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin    }
60261791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin
60361791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin    private void setCameraState(CameraState newState) {
60461791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        mCameraState = newState;
60561791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        mStatusText.setText("C." + mCameraState.toString());
60661791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin        switch (mCameraState) {
60761791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin            case UNAVAILABLE:
60861791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                enableBaseControls(false);
60961791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                enableOpenControls(false);
61061791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                enableConfiguredControls(false);
61161791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                mConfiguredTargetPanes = null;
61261791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                break;
61361791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin            case CLOSED:
61461791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin            case DISCONNECTED:
61561791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin            case ERROR:
61661791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                enableBaseControls(true);
61761791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                enableOpenControls(false);
61861791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                enableConfiguredControls(false);
61961791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                mConfiguredTargetPanes = null;
62061791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                break;
62161791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin            case OPENED:
62261791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                enableBaseControls(true);
62361791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                enableOpenControls(true);
62461791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                enableConfiguredControls(false);
62561791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                mConfiguredTargetPanes = null;
62661791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin                break;
6277c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
6287c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    }
6297c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
6307c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private void enableBaseControls(boolean enabled) {
6317c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        for (View v : mBaseControls) {
6327c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            v.setEnabled(enabled);
6337c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
6347c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        if (!enabled) {
6357c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            mOpenButton.setChecked(false);
6367c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
6377c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    }
6387c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
6397c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private void enableOpenControls(boolean enabled) {
6407c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        for (View v : mOpenControls) {
6417c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            v.setEnabled(enabled);
6427c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
6437c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    }
6447c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
6457c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    private void enableConfiguredControls(boolean enabled) {
6467c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        for (View v : mConfiguredControls) {
6477c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            v.setEnabled(enabled);
6487c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
6497c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    }
6507c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
6513a7882e8950b2de5f7693807794ad10c11b499daEino-Ville Talvala    private final CameraManager.AvailabilityCallback mCameraAvailabilityCallback =
6523a7882e8950b2de5f7693807794ad10c11b499daEino-Ville Talvala            new CameraManager.AvailabilityCallback() {
6537c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        @Override
6547c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        public void onCameraAvailable(String cameraId) {
655855e70adcfd44412a87fb73703f8127f07ffb8c3Eino-Ville Talvala            // TODO: Update camera list in an intelligent fashion
656855e70adcfd44412a87fb73703f8127f07ffb8c3Eino-Ville Talvala            // (can't just call updateCameraList or the selected camera may change)
6577c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
6587c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
6597c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        @Override
6607c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        public void onCameraUnavailable(String cameraId) {
661855e70adcfd44412a87fb73703f8127f07ffb8c3Eino-Ville Talvala            // TODO: Update camera list in an intelligent fashion
662855e70adcfd44412a87fb73703f8127f07ffb8c3Eino-Ville Talvala            // (can't just call updateCameraList or the selected camera may change)
6637c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
6647c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    };
6657c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
66661791ada457c5282a583ac869e0f1ba0e8d1e9f4Igor Murashkin    private final OnItemSelectedListener mCameraSpinnerListener = new OnItemSelectedListener() {
6677c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        @Override
6687c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
6697c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            String newCameraId = mCameraIds[pos];
6707c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            if (newCameraId != mCurrentCameraId) {
6717c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala                switchToCamera(newCameraId);
6727c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            }
6737c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
6747c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala
6757c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        @Override
6767c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        public void onNothingSelected(AdapterView<?> parent) {
6777c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala            switchToCamera(null);
6787c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala        }
6797c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala    };
6807c5f2935442e974ce30158e35d142f7e2c3ee1a2Eino-Ville Talvala}
681