• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TemplateType(int templateVal)60         TemplateType(int templateVal) {
61             mTemplateVal = templateVal;
62         }
63 
getTemplateValue()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      */
RequestControlPane(Context context, AttributeSet attrs)85     public RequestControlPane(Context context, AttributeSet attrs) {
86         super(context, attrs, null, null);
87 
88         mPaneId = 0;
89         setUpUI(context);
90     }
91 
RequestControlPane(TestingCamera21 tc, AttributeSet attrs, StatusListener listener)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 
RequestControlPane(TestingCamera21 tc, XmlPullParser configParser, StatusListener listener)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 
notifyPaneEvent(ControlPane sourcePane, PaneTracker.PaneEvent event)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 
setUpUI(Context context)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> {
CameraPanesListener()179         public CameraPanesListener() {
180             super(CameraControlPane.class);
181         }
182 
183         @Override
onPaneAdded(ControlPane pane)184         public void onPaneAdded(ControlPane pane) {
185             mCameraPanes.add((CameraControlPane) pane);
186             updateCameraPaneList();
187         }
188 
189         @Override
onPaneRemoved(ControlPane pane)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 
createRequest(CameraControlPane camera)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 
updateCameraPaneList()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 
updateOutputList()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