Home | History | Annotate | Download | only in testingcamera2
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.testingcamera2;
     18 
     19 import android.content.Context;
     20 import android.hardware.camera2.CameraDevice;
     21 import android.hardware.camera2.CaptureRequest;
     22 import android.util.AttributeSet;
     23 import android.view.LayoutInflater;
     24 import android.view.Surface;
     25 import android.view.View;
     26 import android.widget.ArrayAdapter;
     27 import android.widget.Button;
     28 import android.widget.ListView;
     29 import android.widget.Spinner;
     30 
     31 import org.xmlpull.v1.XmlPullParser;
     32 import org.xmlpull.v1.XmlPullParserException;
     33 
     34 import java.io.IOException;
     35 import java.util.ArrayList;
     36 import java.util.List;
     37 import java.util.Locale;
     38 
     39 public class RequestControlPane extends ControlPane {
     40     // XML attributes
     41 
     42     /** Name of pane tag */
     43     private static final String PANE_NAME = "request_pane";
     44 
     45     /** Attribute: ID for pane (integer) */
     46     private static final String PANE_ID = "id";
     47 
     48     // End XML attributes
     49 
     50     private enum TemplateType {
     51         MANUAL(CameraDevice.TEMPLATE_MANUAL),
     52         PREVIEW(CameraDevice.TEMPLATE_PREVIEW),
     53         RECORD(CameraDevice.TEMPLATE_RECORD),
     54         STILL_CAPTURE(CameraDevice.TEMPLATE_STILL_CAPTURE),
     55         VIDEO_SNAPSHOT(CameraDevice.TEMPLATE_VIDEO_SNAPSHOT),
     56         ZERO_SHUTTER_LAG(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG);
     57 
     58         private int mTemplateVal;
     59 
     60         TemplateType(int templateVal) {
     61             mTemplateVal = templateVal;
     62         }
     63 
     64         int getTemplateValue() {
     65             return mTemplateVal;
     66         }
     67     }
     68 
     69     private static int mRequestPaneIdCounter = 0;
     70 
     71     private final int mPaneId;
     72 
     73     private List<CameraControlPane> mCameraPanes;
     74     private final List<TargetControlPane> mTargetPanes = new ArrayList<TargetControlPane>();
     75 
     76     private Spinner mCameraSpinner;
     77     private Spinner mTemplateSpinner;
     78     private ListView mOutputListView;
     79 
     80     private CheckableListAdapter mOutputAdapter;
     81 
     82     /**
     83      * Constructor for tooling only
     84      */
     85     public RequestControlPane(Context context, AttributeSet attrs) {
     86         super(context, attrs, null, null);
     87 
     88         mPaneId = 0;
     89         setUpUI(context);
     90     }
     91 
     92     public RequestControlPane(TestingCamera21 tc, AttributeSet attrs, StatusListener listener) {
     93         super(tc, attrs, listener, tc.getPaneTracker());
     94 
     95         mPaneId = mRequestPaneIdCounter++;
     96         setUpUI(tc);
     97     }
     98 
     99     public RequestControlPane(TestingCamera21 tc, XmlPullParser configParser,
    100             StatusListener listener) throws XmlPullParserException, IOException {
    101         super(tc, null, listener, tc.getPaneTracker());
    102 
    103         this.setName(tc.getResources().getString(R.string.request_pane_title));
    104 
    105         configParser.require(XmlPullParser.START_TAG, XmlPullParser.NO_NAMESPACE, PANE_NAME);
    106 
    107         int paneId = getAttributeInt(configParser, PANE_ID, -1);
    108         if (paneId == -1) {
    109             mPaneId = mRequestPaneIdCounter++;
    110         } else {
    111             mPaneId = paneId;
    112             if (mPaneId >= mRequestPaneIdCounter) {
    113                 mRequestPaneIdCounter = mPaneId + 1;
    114             }
    115         }
    116 
    117         configParser.next();
    118         configParser.require(XmlPullParser.END_TAG, XmlPullParser.NO_NAMESPACE, PANE_NAME);
    119 
    120         setUpUI(tc);
    121     }
    122 
    123     public void notifyPaneEvent(ControlPane sourcePane, PaneTracker.PaneEvent event) {
    124         switch (event) {
    125             case NEW_CAMERA_SELECTED:
    126                 if (mCameraPanes.size() > 0
    127                         && sourcePane == mCameraPanes.get(mCameraSpinner.getSelectedItemPosition())) {
    128                     updateOutputList();
    129                 }
    130                 break;
    131             case CAMERA_CONFIGURED:
    132                 if (mCameraPanes.size() > 0
    133                         && sourcePane == mCameraPanes.get(mCameraSpinner.getSelectedItemPosition())) {
    134                     updateOutputList();
    135                 }
    136                 break;
    137             default:
    138                 super.notifyPaneEvent(sourcePane, event);
    139         }
    140     }
    141 
    142     private void setUpUI(Context context) {
    143         String paneName =
    144                 String.format(Locale.US, "%s %d",
    145                         context.getResources().getString(R.string.request_pane_title), mPaneId);
    146         this.setName(paneName);
    147 
    148         LayoutInflater inflater =
    149                 (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    150 
    151         inflater.inflate(R.layout.request_pane, this);
    152 
    153         Button captureButton = (Button) findViewById(R.id.request_pane_capture_button);
    154         captureButton.setOnClickListener(mCaptureButtonListener);
    155         Button repeatButton = (Button) findViewById(R.id.request_pane_repeat_button);
    156         repeatButton.setOnClickListener(mRepeatButtonListener);
    157 
    158         mCameraSpinner = (Spinner) findViewById(R.id.request_pane_camera_spinner);
    159         mTemplateSpinner = (Spinner) findViewById(R.id.request_pane_template_spinner);
    160         mOutputListView = (ListView) findViewById(R.id.request_pane_output_listview);
    161 
    162         mOutputAdapter = new CheckableListAdapter(context, R.layout.checkable_list_item,
    163                 new ArrayList<CheckableListAdapter.CheckableItem>());
    164         mOutputListView.setAdapter(mOutputAdapter);
    165 
    166         String[] templateNames = new String[TemplateType.values().length];
    167         for (int i = 0; i < templateNames.length; i++) {
    168             templateNames[i] = TemplateType.values()[i].toString();
    169         }
    170         mTemplateSpinner.setAdapter(new ArrayAdapter<String>(getContext(), R.layout.spinner_item,
    171                 templateNames));
    172 
    173         mPaneTracker.addPaneListener(new CameraPanesListener());
    174         mCameraPanes = mPaneTracker.getPanes(CameraControlPane.class);
    175         updateCameraPaneList();
    176     }
    177 
    178     private class CameraPanesListener extends PaneTracker.PaneSetChangedListener<CameraControlPane> {
    179         public CameraPanesListener() {
    180             super(CameraControlPane.class);
    181         }
    182 
    183         @Override
    184         public void onPaneAdded(ControlPane pane) {
    185             mCameraPanes.add((CameraControlPane) pane);
    186             updateCameraPaneList();
    187         }
    188 
    189         @Override
    190         public void onPaneRemoved(ControlPane pane) {
    191             mCameraPanes.remove((CameraControlPane) pane);
    192             updateCameraPaneList();
    193         }
    194     }
    195 
    196     private OnClickListener mCaptureButtonListener = new OnClickListener() {
    197         @Override
    198         public void onClick(View v) {
    199             if (mCameraPanes.size() == 0) {
    200                 TLog.e("No camera selected for request");
    201                 return;
    202             }
    203             CameraControlPane camera = mCameraPanes.get(mCameraSpinner.getSelectedItemPosition());
    204 
    205             CaptureRequest request = createRequest(camera);
    206             if (request != null) {
    207                 camera.capture(request);
    208             }
    209         }
    210     };
    211 
    212     private OnClickListener mRepeatButtonListener = new OnClickListener() {
    213         @Override
    214         public void onClick(View v) {
    215             if (mCameraPanes.size() == 0) {
    216                 TLog.e("No camera selected for request");
    217                 return;
    218             }
    219             CameraControlPane camera = mCameraPanes.get(mCameraSpinner.getSelectedItemPosition());
    220 
    221             CaptureRequest request = createRequest(camera);
    222             if (request != null) {
    223                 camera.repeat(request);
    224             }
    225         }
    226     };
    227 
    228     private CaptureRequest createRequest(CameraControlPane camera) {
    229         if (mTargetPanes.size() == 0) {
    230             TLog.e("No target(s) selected for request");
    231             return null;
    232         }
    233 
    234 
    235         TemplateType template = TemplateType.valueOf((String) mTemplateSpinner.getSelectedItem());
    236         CaptureRequest.Builder builder = camera.getRequestBuilder(template.getTemplateValue());
    237         // TODO: Add setting overrides
    238 
    239         List<Integer> targetPostions = mOutputAdapter.getCheckedPositions();
    240         for (int i : targetPostions) {
    241             TargetControlPane target = mTargetPanes.get(i);
    242             Surface targetSurface = target.getTargetSurfaceForCameraPane(camera.getPaneName());
    243             if (targetSurface == null) {
    244                 TLog.e("Target not configured for camera");
    245                 return null;
    246             }
    247             builder.addTarget(targetSurface);
    248         }
    249 
    250         CaptureRequest request = builder.build();
    251         return request;
    252     }
    253 
    254     private void updateCameraPaneList() {
    255         String currentSelection = (String) mCameraSpinner.getSelectedItem();
    256         int newSelectionIndex = 0;
    257         String[] cameraSpinnerItems = new String[mCameraPanes.size()];
    258         for (int i = 0; i < cameraSpinnerItems.length; i++) {
    259             cameraSpinnerItems[i] = mCameraPanes.get(i).getPaneName();
    260             if (cameraSpinnerItems[i].equals(currentSelection)) {
    261                 newSelectionIndex = i;
    262             }
    263         }
    264         mCameraSpinner.setAdapter(new ArrayAdapter<String>(getContext(), R.layout.spinner_item,
    265                 cameraSpinnerItems));
    266         mCameraSpinner.setSelection(newSelectionIndex);
    267 
    268         updateOutputList();
    269     }
    270 
    271     private void updateOutputList() {
    272         if (mCameraPanes.size() > 0) {
    273             CameraControlPane currentCamera =
    274                     mCameraPanes.get(mCameraSpinner.getSelectedItemPosition());
    275             mTargetPanes.clear();
    276             List<TargetControlPane> newPanes = currentCamera.getCurrentConfiguredTargets();
    277             if (newPanes != null) {
    278                 mTargetPanes.addAll(currentCamera.getCurrentConfiguredTargets());
    279             }
    280 
    281             String[] outputSpinnerItems = new String[mTargetPanes.size()];
    282             for (int i = 0; i < outputSpinnerItems.length; i++) {
    283                 outputSpinnerItems[i] = mTargetPanes.get(i).getPaneName();
    284             }
    285 
    286             mOutputAdapter.updateItems(outputSpinnerItems);
    287 
    288         }
    289     }
    290 
    291 }
    292