blob: e629cdd7983cdfca517f66fc73122b1c0c54a2aa [file] [log] [blame]
Chien-Yu Chen3068d732015-02-09 13:29:57 -08001/*
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
17#define LOG_TAG "CameraFlashlight"
18#define ATRACE_TAG ATRACE_TAG_CAMERA
Chien-Yu Chen88da5262015-02-17 13:56:46 -080019// #define LOG_NDEBUG 0
Chien-Yu Chen3068d732015-02-09 13:29:57 -080020
21#include <utils/Log.h>
22#include <utils/Trace.h>
23#include <cutils/properties.h>
24
25#include "camera/CameraMetadata.h"
26#include "CameraFlashlight.h"
27#include "gui/IGraphicBufferConsumer.h"
28#include "gui/BufferQueue.h"
29#include "camera/camera2/CaptureRequest.h"
Eino-Ville Talvalad309fb92015-11-25 12:12:45 -080030#include "device3/Camera3Device.h"
Chien-Yu Chen3068d732015-02-09 13:29:57 -080031
32
33namespace android {
34
Yin-Chia Yehc3e9d6f2018-02-06 10:56:32 -080035using hardware::camera::common::V1_0::TorchModeStatus;
36
Chien-Yu Chen88da5262015-02-17 13:56:46 -080037/////////////////////////////////////////////////////////////////////
38// CameraFlashlight implementation begins
39// used by camera service to control flashflight.
40/////////////////////////////////////////////////////////////////////
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -080041
42CameraFlashlight::CameraFlashlight(sp<CameraProviderManager> providerManager,
Yin-Chia Yehc3e9d6f2018-02-06 10:56:32 -080043 CameraProviderManager::StatusListener* callbacks) :
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -080044 mProviderManager(providerManager),
45 mCallbacks(callbacks),
Chien-Yu Chen88da5262015-02-17 13:56:46 -080046 mFlashlightMapInitialized(false) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -080047}
48
49CameraFlashlight::~CameraFlashlight() {
50}
51
Chien-Yu Chen88da5262015-02-17 13:56:46 -080052status_t CameraFlashlight::createFlashlightControl(const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -080053 ALOGV("%s: creating a flash light control for camera %s", __FUNCTION__,
54 cameraId.string());
55 if (mFlashControl != NULL) {
56 return INVALID_OPERATION;
57 }
58
Emilian Peevf53f66e2017-04-11 14:29:43 +010059 if (mProviderManager->supportSetTorchMode(cameraId.string())) {
60 mFlashControl = new ProviderFlashControl(mProviderManager);
Chien-Yu Chen3068d732015-02-09 13:29:57 -080061 } else {
Emilian Peevf53f66e2017-04-11 14:29:43 +010062 // Only HAL1 devices do not support setTorchMode
63 mFlashControl =
Yin-Chia Yehc3e9d6f2018-02-06 10:56:32 -080064 new CameraHardwareInterfaceFlashControl(mProviderManager, mCallbacks);
Chien-Yu Chen3068d732015-02-09 13:29:57 -080065 }
66
67 return OK;
68}
69
Chien-Yu Chen88da5262015-02-17 13:56:46 -080070status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) {
71 if (!mFlashlightMapInitialized) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -070072 ALOGE("%s: findFlashUnits() must be called before this method.",
73 __FUNCTION__);
Chien-Yu Chen3068d732015-02-09 13:29:57 -080074 return NO_INIT;
75 }
76
77 ALOGV("%s: set torch mode of camera %s to %d", __FUNCTION__,
78 cameraId.string(), enabled);
79
80 status_t res = OK;
81 Mutex::Autolock l(mLock);
82
Ruben Brunkcc776712015-02-17 20:18:47 -080083 if (mOpenedCameraIds.indexOf(cameraId) != NAME_NOT_FOUND) {
84 // This case is needed to avoid state corruption during the following call sequence:
85 // CameraService::setTorchMode for camera ID 0 begins, does torch status checks
86 // CameraService::connect for camera ID 0 begins, calls prepareDeviceOpen, ends
87 // CameraService::setTorchMode for camera ID 0 continues, calls
88 // CameraFlashlight::setTorchMode
89
90 // TODO: Move torch status checks and state updates behind this CameraFlashlight lock
91 // to avoid other similar race conditions.
92 ALOGE("%s: Camera device %s is in use, cannot set torch mode.",
93 __FUNCTION__, cameraId.string());
94 return -EBUSY;
95 }
96
Chien-Yu Chen3068d732015-02-09 13:29:57 -080097 if (mFlashControl == NULL) {
98 res = createFlashlightControl(cameraId);
99 if (res) {
100 return res;
101 }
102 res = mFlashControl->setTorchMode(cameraId, enabled);
103 return res;
104 }
105
106 // if flash control already exists, turning on torch mode may fail if it's
107 // tied to another camera device for module v2.3 and below.
108 res = mFlashControl->setTorchMode(cameraId, enabled);
109 if (res == BAD_INDEX) {
110 // flash control is tied to another camera device, need to close it and
111 // try again.
112 mFlashControl.clear();
113 res = createFlashlightControl(cameraId);
114 if (res) {
115 return res;
116 }
117 res = mFlashControl->setTorchMode(cameraId, enabled);
118 }
119
120 return res;
121}
122
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800123status_t CameraFlashlight::findFlashUnits() {
124 Mutex::Autolock l(mLock);
125 status_t res;
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800126
127 std::vector<String8> cameraIds;
Yin-Chia Yeh98c72a82018-08-28 11:20:16 -0700128 std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
Yin-Chia Yeh6b1f6112018-02-28 13:05:59 -0800129 int numberOfCameras = static_cast<int>(ids.size());
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700130 cameraIds.resize(numberOfCameras);
Emilian Peevf53f66e2017-04-11 14:29:43 +0100131 // No module, must be provider
Emilian Peevf53f66e2017-04-11 14:29:43 +0100132 for (size_t i = 0; i < cameraIds.size(); i++) {
133 cameraIds[i] = String8(ids[i].c_str());
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800134 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800135
Emilian Peevaee727d2017-05-04 16:35:48 +0100136 mFlashControl.clear();
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800137
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800138 for (auto &id : cameraIds) {
Emilian Peevaee727d2017-05-04 16:35:48 +0100139 ssize_t index = mHasFlashlightMap.indexOfKey(id);
140 if (0 <= index) {
141 continue;
142 }
143
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800144 bool hasFlash = false;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800145 res = createFlashlightControl(id);
146 if (res) {
147 ALOGE("%s: failed to create flash control for %s", __FUNCTION__,
148 id.string());
149 } else {
150 res = mFlashControl->hasFlashUnit(id, &hasFlash);
151 if (res == -EUSERS || res == -EBUSY) {
152 ALOGE("%s: failed to check if camera %s has a flash unit. Some "
153 "camera devices may be opened", __FUNCTION__,
154 id.string());
155 return res;
156 } else if (res) {
157 ALOGE("%s: failed to check if camera %s has a flash unit. %s"
158 " (%d)", __FUNCTION__, id.string(), strerror(-res),
159 res);
160 }
161
162 mFlashControl.clear();
163 }
164 mHasFlashlightMap.add(id, hasFlash);
165 }
166
167 mFlashlightMapInitialized = true;
168 return OK;
169}
170
171bool CameraFlashlight::hasFlashUnit(const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800172 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800173 return hasFlashUnitLocked(cameraId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800174}
175
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800176bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) {
177 if (!mFlashlightMapInitialized) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -0700178 ALOGE("%s: findFlashUnits() must be called before this method.",
179 __FUNCTION__);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800180 return false;
181 }
182
183 ssize_t index = mHasFlashlightMap.indexOfKey(cameraId);
184 if (index == NAME_NOT_FOUND) {
Yin-Chia Yeh6b1f6112018-02-28 13:05:59 -0800185 // Might be external camera
186 ALOGW("%s: camera %s not present when findFlashUnits() was called",
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800187 __FUNCTION__, cameraId.string());
188 return false;
189 }
190
191 return mHasFlashlightMap.valueAt(index);
192}
193
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700194bool CameraFlashlight::isBackwardCompatibleMode(const String8& cameraId) {
195 bool backwardCompatibleMode = false;
Emilian Peevf53f66e2017-04-11 14:29:43 +0100196 if (mProviderManager != nullptr &&
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700197 !mProviderManager->supportSetTorchMode(cameraId.string())) {
198 backwardCompatibleMode = true;
199 }
200 return backwardCompatibleMode;
201}
202
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800203status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800204 ALOGV("%s: prepare for device open", __FUNCTION__);
205
206 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800207 if (!mFlashlightMapInitialized) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -0700208 ALOGE("%s: findFlashUnits() must be called before this method.",
209 __FUNCTION__);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800210 return NO_INIT;
211 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800212
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700213 if (isBackwardCompatibleMode(cameraId)) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800214 // framework is going to open a camera device, all flash light control
215 // should be closed for backward compatible support.
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800216 mFlashControl.clear();
217
218 if (mOpenedCameraIds.size() == 0) {
219 // notify torch unavailable for all cameras with a flash
Yin-Chia Yeh98c72a82018-08-28 11:20:16 -0700220 std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
Yin-Chia Yeh6b1f6112018-02-28 13:05:59 -0800221 int numCameras = static_cast<int>(ids.size());
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800222 for (int i = 0; i < numCameras; i++) {
Yin-Chia Yeh6b1f6112018-02-28 13:05:59 -0800223 String8 id8(ids[i].c_str());
224 if (hasFlashUnitLocked(id8)) {
Yin-Chia Yehc3e9d6f2018-02-06 10:56:32 -0800225 mCallbacks->onTorchStatusChanged(
Yin-Chia Yeh6b1f6112018-02-28 13:05:59 -0800226 id8, TorchModeStatus::NOT_AVAILABLE);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800227 }
228 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800229 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800230
231 // close flash control that may be opened by calling hasFlashUnitLocked.
232 mFlashControl.clear();
233 }
234
235 if (mOpenedCameraIds.indexOf(cameraId) == NAME_NOT_FOUND) {
236 mOpenedCameraIds.add(cameraId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800237 }
238
239 return OK;
240}
241
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800242status_t CameraFlashlight::deviceClosed(const String8& cameraId) {
243 ALOGV("%s: device %s is closed", __FUNCTION__, cameraId.string());
244
245 Mutex::Autolock l(mLock);
246 if (!mFlashlightMapInitialized) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -0700247 ALOGE("%s: findFlashUnits() must be called before this method.",
248 __FUNCTION__);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800249 return NO_INIT;
250 }
251
252 ssize_t index = mOpenedCameraIds.indexOf(cameraId);
253 if (index == NAME_NOT_FOUND) {
254 ALOGE("%s: couldn't find camera %s in the opened list", __FUNCTION__,
255 cameraId.string());
256 } else {
257 mOpenedCameraIds.removeAt(index);
258 }
259
260 // Cannot do anything until all cameras are closed.
261 if (mOpenedCameraIds.size() != 0)
262 return OK;
263
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700264 if (isBackwardCompatibleMode(cameraId)) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800265 // notify torch available for all cameras with a flash
Yin-Chia Yeh98c72a82018-08-28 11:20:16 -0700266 std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
Yin-Chia Yeh6b1f6112018-02-28 13:05:59 -0800267 int numCameras = static_cast<int>(ids.size());
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800268 for (int i = 0; i < numCameras; i++) {
Yin-Chia Yeh6b1f6112018-02-28 13:05:59 -0800269 String8 id8(ids[i].c_str());
270 if (hasFlashUnitLocked(id8)) {
Yin-Chia Yehc3e9d6f2018-02-06 10:56:32 -0800271 mCallbacks->onTorchStatusChanged(
Yin-Chia Yeh6b1f6112018-02-28 13:05:59 -0800272 id8, TorchModeStatus::AVAILABLE_OFF);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800273 }
274 }
275 }
276
277 return OK;
278}
279// CameraFlashlight implementation ends
280
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800281
282FlashControlBase::~FlashControlBase() {
283}
284
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800285/////////////////////////////////////////////////////////////////////
286// ModuleFlashControl implementation begins
287// Flash control for camera module v2.4 and above.
288/////////////////////////////////////////////////////////////////////
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800289ProviderFlashControl::ProviderFlashControl(sp<CameraProviderManager> providerManager) :
290 mProviderManager(providerManager) {
291}
292
293ProviderFlashControl::~ProviderFlashControl() {
294}
295
296status_t ProviderFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) {
297 if (!hasFlash) {
298 return BAD_VALUE;
299 }
300 *hasFlash = mProviderManager->hasFlashUnit(cameraId.string());
301 return OK;
302}
303
304status_t ProviderFlashControl::setTorchMode(const String8& cameraId, bool enabled) {
305 ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
306 cameraId.string(), enabled);
307
308 return mProviderManager->setTorchMode(cameraId.string(), enabled);
309}
310// ProviderFlashControl implementation ends
311
312/////////////////////////////////////////////////////////////////////
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800313// CameraHardwareInterfaceFlashControl implementation begins
314// Flash control for camera module <= v2.3 and camera HAL v1
315/////////////////////////////////////////////////////////////////////
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800316
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700317CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
318 sp<CameraProviderManager> manager,
Yin-Chia Yehc3e9d6f2018-02-06 10:56:32 -0800319 CameraProviderManager::StatusListener* callbacks) :
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700320 mProviderManager(manager),
Yin-Chia Yehc3e9d6f2018-02-06 10:56:32 -0800321 mCallbacks(callbacks),
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700322 mTorchEnabled(false) {
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800323}
324
325CameraHardwareInterfaceFlashControl::~CameraHardwareInterfaceFlashControl() {
326 disconnectCameraDevice();
327
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700328 mSurface.clear();
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800329 mSurfaceTexture.clear();
330 mProducer.clear();
331 mConsumer.clear();
332
333 if (mTorchEnabled) {
334 if (mCallbacks) {
335 ALOGV("%s: notify the framework that torch was turned off",
336 __FUNCTION__);
Yin-Chia Yehc3e9d6f2018-02-06 10:56:32 -0800337 mCallbacks->onTorchStatusChanged(mCameraId, TorchModeStatus::AVAILABLE_OFF);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800338 }
339 }
340}
341
342status_t CameraHardwareInterfaceFlashControl::setTorchMode(
343 const String8& cameraId, bool enabled) {
344 Mutex::Autolock l(mLock);
345
346 // pre-check
347 status_t res;
348 if (enabled) {
349 bool hasFlash = false;
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700350 // Check if it has a flash unit and leave camera device open.
351 res = hasFlashUnitLocked(cameraId, &hasFlash, /*keepDeviceOpen*/true);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800352 // invalid camera?
353 if (res) {
354 // hasFlashUnitLocked() returns BAD_INDEX if mDevice is connected to
355 // another camera device.
356 return res == BAD_INDEX ? BAD_INDEX : -EINVAL;
357 }
358 // no flash unit?
359 if (!hasFlash) {
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700360 // Disconnect camera device if it has no flash.
361 disconnectCameraDevice();
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800362 return -ENOSYS;
363 }
364 } else if (mDevice == NULL || cameraId != mCameraId) {
365 // disabling the torch mode of an un-opened or different device.
366 return OK;
367 } else {
368 // disabling the torch mode of currently opened device
369 disconnectCameraDevice();
370 mTorchEnabled = false;
Yin-Chia Yehc3e9d6f2018-02-06 10:56:32 -0800371 mCallbacks->onTorchStatusChanged(cameraId, TorchModeStatus::AVAILABLE_OFF);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800372 return OK;
373 }
374
375 res = startPreviewAndTorch();
376 if (res) {
377 return res;
378 }
379
380 mTorchEnabled = true;
Yin-Chia Yehc3e9d6f2018-02-06 10:56:32 -0800381 mCallbacks->onTorchStatusChanged(cameraId, TorchModeStatus::AVAILABLE_ON);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800382 return OK;
383}
384
385status_t CameraHardwareInterfaceFlashControl::hasFlashUnit(
386 const String8& cameraId, bool *hasFlash) {
387 Mutex::Autolock l(mLock);
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700388 // Close device after checking if it has a flash unit.
389 return hasFlashUnitLocked(cameraId, hasFlash, /*keepDeviceOpen*/false);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800390}
391
392status_t CameraHardwareInterfaceFlashControl::hasFlashUnitLocked(
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700393 const String8& cameraId, bool *hasFlash, bool keepDeviceOpen) {
394 bool closeCameraDevice = false;
395
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800396 if (!hasFlash) {
397 return BAD_VALUE;
398 }
399
400 status_t res;
401 if (mDevice == NULL) {
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700402 // Connect to camera device to query if it has a flash unit.
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800403 res = connectCameraDevice(cameraId);
404 if (res) {
405 return res;
406 }
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700407 // Close camera device only when it is just opened and the caller doesn't want to keep
408 // the camera device open.
409 closeCameraDevice = !keepDeviceOpen;
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800410 }
411
412 if (cameraId != mCameraId) {
413 return BAD_INDEX;
414 }
415
416 const char *flashMode =
417 mParameters.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES);
418 if (flashMode && strstr(flashMode, CameraParameters::FLASH_MODE_TORCH)) {
419 *hasFlash = true;
420 } else {
421 *hasFlash = false;
422 }
423
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700424 if (closeCameraDevice) {
425 res = disconnectCameraDevice();
426 if (res != OK) {
427 ALOGE("%s: Failed to disconnect camera device. %s (%d)", __FUNCTION__,
428 strerror(-res), res);
429 return res;
430 }
431 }
432
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800433 return OK;
434}
435
436status_t CameraHardwareInterfaceFlashControl::startPreviewAndTorch() {
437 status_t res = OK;
438 res = mDevice->startPreview();
439 if (res) {
440 ALOGE("%s: start preview failed. %s (%d)", __FUNCTION__,
441 strerror(-res), res);
442 return res;
443 }
444
445 mParameters.set(CameraParameters::KEY_FLASH_MODE,
446 CameraParameters::FLASH_MODE_TORCH);
447
448 return mDevice->setParameters(mParameters);
449}
450
451status_t CameraHardwareInterfaceFlashControl::getSmallestSurfaceSize(
452 int32_t *width, int32_t *height) {
453 if (!width || !height) {
454 return BAD_VALUE;
455 }
456
457 int32_t w = INT32_MAX;
458 int32_t h = 1;
459 Vector<Size> sizes;
460
461 mParameters.getSupportedPreviewSizes(sizes);
462 for (size_t i = 0; i < sizes.size(); i++) {
463 Size s = sizes[i];
464 if (w * h > s.width * s.height) {
465 w = s.width;
466 h = s.height;
467 }
468 }
469
470 if (w == INT32_MAX) {
471 return NAME_NOT_FOUND;
472 }
473
474 *width = w;
475 *height = h;
476
477 return OK;
478}
479
480status_t CameraHardwareInterfaceFlashControl::initializePreviewWindow(
Chih-Hung Hsieh8b0b9712016-08-09 14:25:53 -0700481 const sp<CameraHardwareInterface>& device, int32_t width, int32_t height) {
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800482 status_t res;
483 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
484
485 mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
486 true, true);
487 if (mSurfaceTexture == NULL) {
488 return NO_MEMORY;
489 }
490
491 int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
492 res = mSurfaceTexture->setDefaultBufferSize(width, height);
493 if (res) {
494 return res;
495 }
496 res = mSurfaceTexture->setDefaultBufferFormat(format);
497 if (res) {
498 return res;
499 }
500
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700501 mSurface = new Surface(mProducer, /*useAsync*/ true);
502 if (mSurface == NULL) {
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800503 return NO_MEMORY;
504 }
505
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700506 res = native_window_api_connect(mSurface.get(), NATIVE_WINDOW_API_CAMERA);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800507 if (res) {
508 ALOGE("%s: Unable to connect to native window", __FUNCTION__);
509 return res;
510 }
511
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700512 return device->setPreviewWindow(mSurface);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800513}
514
515status_t CameraHardwareInterfaceFlashControl::connectCameraDevice(
516 const String8& cameraId) {
517 sp<CameraHardwareInterface> device =
518 new CameraHardwareInterface(cameraId.string());
519
Emilian Peevf53f66e2017-04-11 14:29:43 +0100520 status_t res = device->initialize(mProviderManager);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800521 if (res) {
522 ALOGE("%s: initializing camera %s failed", __FUNCTION__,
523 cameraId.string());
524 return res;
525 }
526
527 // need to set __get_memory in set_callbacks().
Yin-Chia Yehb5df5472017-03-20 19:32:19 -0700528 device->setCallbacks(NULL, NULL, NULL, NULL, NULL);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800529
530 mParameters = device->getParameters();
531
532 int32_t width, height;
533 res = getSmallestSurfaceSize(&width, &height);
534 if (res) {
535 ALOGE("%s: failed to get smallest surface size for camera %s",
536 __FUNCTION__, cameraId.string());
537 return res;
538 }
539
540 res = initializePreviewWindow(device, width, height);
541 if (res) {
542 ALOGE("%s: failed to initialize preview window for camera %s",
543 __FUNCTION__, cameraId.string());
544 return res;
545 }
546
547 mCameraId = cameraId;
548 mDevice = device;
549 return OK;
550}
551
552status_t CameraHardwareInterfaceFlashControl::disconnectCameraDevice() {
553 if (mDevice == NULL) {
554 return OK;
555 }
556
Jim Kaye3d1c4782016-04-12 17:24:46 -0700557 if (mParameters.get(CameraParameters::KEY_FLASH_MODE)) {
558 // There is a flash, turn if off.
559 // (If there isn't one, leave the parameter null)
560 mParameters.set(CameraParameters::KEY_FLASH_MODE,
561 CameraParameters::FLASH_MODE_OFF);
562 mDevice->setParameters(mParameters);
563 }
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800564 mDevice->stopPreview();
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700565 status_t res = native_window_api_disconnect(mSurface.get(),
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800566 NATIVE_WINDOW_API_CAMERA);
567 if (res) {
568 ALOGW("%s: native_window_api_disconnect failed: %s (%d)",
569 __FUNCTION__, strerror(-res), res);
570 }
571 mDevice->setPreviewWindow(NULL);
572 mDevice->release();
Oleksiy Avramchenko8a4a0ac2015-09-14 11:00:33 +0200573 mDevice = NULL;
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800574
575 return OK;
576}
577// CameraHardwareInterfaceFlashControl implementation ends
578
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800579}